예제 #1
0
void sunxi_snd_txctrl_daudio0(struct snd_pcm_substream *substream, int on,int hub_en)
{
	u32 reg_val;
	/*flush TX FIFO*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	reg_val |= SUNXI_DAUDIOFCTL_FTX;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	/*clear TX counter*/
	sunxi_smc_writel(0, sunxi_daudio.regs + SUNXI_DAUDIOTXCNT);

	if (on) {
		/* enable DMA DRQ mode for play */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
		reg_val |= SUNXI_DAUDIOINT_TXDRQEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOINT);
	} else {
		/* DISBALE dma DRQ mode */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
		reg_val &= ~SUNXI_DAUDIOINT_TXDRQEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOINT);
	}
	if (hub_en) {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		reg_val |= SUNXI_DAUDIOFCTL_HUBEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	} else {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		reg_val &= ~SUNXI_DAUDIOFCTL_HUBEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	}
}
예제 #2
0
int sunxi_daudio0_hw_params(struct snd_pcm_substream *substream,
																struct snd_pcm_hw_params *params,
																struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct sunxi_dma_params *dma_data;

	u32 reg_val = 0;

	switch (params_format(params))
	{
		case SNDRV_PCM_FORMAT_S16_LE:
		sample_resolution = 16;
		break;
	case SNDRV_PCM_FORMAT_S20_3LE:
		sample_resolution = 24;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		sample_resolution = 24;
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		sample_resolution = 24;
		break;
	default:
		return -EINVAL;
	}
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	sunxi_daudio.samp_res = sample_resolution;
	reg_val &= ~SUNXI_DAUDIOFAT0_SR;
	if(sample_resolution == 16)
		reg_val |= (3<<4);
	else if(sample_resolution == 20)
		reg_val |= (4<<4);
	else
		reg_val |= (5<<4);
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFAT0);

	if (sample_resolution == 24) {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		reg_val &= ~(0x1<<2);
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	} else {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		reg_val |= SUNXI_DAUDIOFCTL_TXIM;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	}

	/* play or record */
	if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		dma_data = &sunxi_daudio_pcm_stereo_out;
	else
		dma_data = &sunxi_daudio_pcm_stereo_in;

	snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
	return 0;
}
예제 #3
0
static int sunxi_daudio0_resume(struct snd_soc_dai *cpu_dai)
{
	u32 reg_val;
	pr_debug("[DAUDIO]Entered %s\n", __func__);
	#if defined(CONFIG_ARCH_SUN8IW6) || defined(CONFIG_ARCH_SUN8IW8)
	/*enable the module clock*/
	if (clk_prepare_enable(daudio_pllx8)) {
		pr_err("open daudio_pllx8 failed! line = %d\n", __LINE__);
	}
	/*enable the module clock*/
	if (clk_prepare_enable(daudio_pll2clk)) {
		pr_err("open daudio_pll2clk failed! line = %d\n", __LINE__);
	}
	#endif
	/*enable the module clock*/
	if (clk_prepare_enable(daudio_moduleclk)) {
		pr_err("open daudio_moduleclk failed! line = %d\n", __LINE__);
	}
	/*for evb pin config*/
	daudio_pinctrl = devm_pinctrl_get_select_default(cpu_dai->dev);
	if (IS_ERR_OR_NULL(daudio_pinctrl)) {
		dev_warn(cpu_dai->dev,
			"pins are not configured from the driver\n");
	}

	daudioregrestore();
	/*Global Enable Digital Audio Interface*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	reg_val |= SUNXI_DAUDIOCTL_GEN;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	
	return 0;
}
예제 #4
0
int sunxi_daudio0_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
                                 unsigned int freq, int daudio_pcm_select)
{
#ifdef CONFIG_ARCH_SUN9IW1
	if (clk_set_rate(daudio_pll3clk, freq)) {
		pr_err("try to set the daudio_pll2clk failed!\n");
	}
	/*
	*22579200:reg:0xf6000008 val is 0x8104361c
	*	  reg:0x06000108 val is 0xc00121ff
	*24576000:reg:0xf6000008 val is 0x81043d1d
	*	  reg:0x06000108 val is 0xc000e147
	*/
	pr_debug("0xf6000008 = %#x, line:%d, freq:%d\n", sunxi_smc_readl((void __iomem *)0xf6000008), __LINE__, freq);
#else
	#ifdef CONFIG_ARCH_SUN8IW7
		if (clk_set_rate(daudio_pll, freq)) {
			pr_err("try to set the daudio_pll rate failed!\n");
		}
	#else
	if (clk_set_rate(daudio_pll2clk, freq)) {
		pr_err("try to set the daudio_pll2clk failed!\n");
	}
	#endif
#endif
	daudio_select = daudio_pcm_select;

	return 0;
}
예제 #5
0
int r_i2s_rx_disable(void)
{
	int reg_val;
	/* DAUDIO RX DISABLE */
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	reg_val &= ~SUNXI_DAUDIOCTL_RXEN;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	return 0;
}
예제 #6
0
static int sun8i_cpu_power_switch_set(unsigned int cluster, unsigned int cpu, bool enable)
{
	if (enable) {
		if (0x00 == sunxi_smc_readl(sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu))) {
			pr_debug("%s: power switch enable already\n", __func__);
			return 0;
		}
		/* de-active cpu power clamp */
		sunxi_smc_writel(0xFE, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(20);

		sunxi_smc_writel(0xF8, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(10);

		sunxi_smc_writel(0xE0, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(10);
#ifdef CONFIG_ARCH_SUN8IW6
		sunxi_smc_writel(0xc0, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(10);
#endif
		sunxi_smc_writel(0x80, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(10);

		sunxi_smc_writel(0x00, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(20);
		while(0x00 != sunxi_smc_readl(sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu))) {
			;
		}
	} else {
		if (0xFF == sunxi_smc_readl(sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu))) {
			pr_debug("%s: power switch disable already\n", __func__);
			return 0;
		}
		sunxi_smc_writel(0xFF, sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu));
		udelay(30);
		while(0xFF != sunxi_smc_readl(sun8i_prcm_base + SUNXI_CPU_PWR_CLAMP(cluster, cpu))) {
			;
		}
	}
	return 0;
}
예제 #7
0
void sunxi_snd_rxctrl_daudio0(struct snd_pcm_substream *substream, int on)
{
	u32 reg_val;
	/*flush RX FIFO*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	reg_val |= SUNXI_DAUDIOFCTL_FRX;	
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	/*clear RX counter*/
	sunxi_smc_writel(0, sunxi_daudio.regs + SUNXI_DAUDIORXCNT);

	if (on) {
		/* enable DMA DRQ mode for record */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
		reg_val |= SUNXI_DAUDIOINT_RXDRQEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOINT);
	} else {
		/* DISBALE dma DRQ mode */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
		reg_val &= ~SUNXI_DAUDIOINT_RXDRQEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOINT);
	}
}
void sunxi_snd_rxctrl_daudio0(struct snd_pcm_substream *substream, int on)
{
	u32 reg_val;
	/*flush RX FIFO*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	reg_val |= SUNXI_DAUDIOFCTL_FRX;	
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
	/*clear RX counter*/
	sunxi_smc_writel(0, sunxi_daudio.regs + SUNXI_DAUDIORXCNT);
	/* DAUDIO RX ENABLE */
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	reg_val |= SUNXI_DAUDIOCTL_RXEN;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	/*for IO TO IO transfer*/
	if (!substream) {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_TXCHCFG);
		reg_val &= ~(0x7<<4);
		reg_val |= (0x1)<<4;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_TXCHCFG);

		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIORXCHSEL);
		reg_val |= (0x1<<12);
		reg_val	|= (0x1<<0);
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIORXCHSEL);

		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIORXCHMAP);
		reg_val = 0x10;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIORXCHMAP);

		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		reg_val |= SUNXI_DAUDIOFCTL_RXOM;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		/*clear RX counter*/
		sunxi_smc_writel(0, sunxi_daudio.regs + SUNXI_DAUDIORXCNT);
	}

	if (on) {
		/* enable DMA DRQ mode for record */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
		reg_val |= SUNXI_DAUDIOINT_RXDRQEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOINT);
	} else {
		/* DISBALE dma DRQ mode */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
		reg_val &= ~SUNXI_DAUDIOINT_RXDRQEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOINT);
	}
}
예제 #9
0
static int sunxi_daudio0_suspend(struct snd_soc_dai *cpu_dai)
{
	u32 reg_val;
	u32 pin_index = 0;
	u32 config;
	struct gpio_config *pin_daudio0_cfg;
	char pin_name[SUNXI_PIN_NAME_MAX_LEN];
	pr_debug("[DAUDIO]Entered %s\n", __func__);

	/*Global disable Digital Audio Interface*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	reg_val &= ~SUNXI_DAUDIOCTL_GEN;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);

	daudioregsave();

	if ((NULL == daudio_moduleclk) ||(IS_ERR(daudio_moduleclk))) {
		pr_err("daudio_moduleclk handle is invalid, just return\n");
		return -EFAULT;
	} else {
		/*release the module clock*/
		clk_disable(daudio_moduleclk);
	}
	#if defined(CONFIG_ARCH_SUN8IW6) || defined(CONFIG_ARCH_SUN8IW8)
	if ((NULL == daudio_pll2clk) ||(IS_ERR(daudio_pll2clk))) {
		pr_err("daudio_pll2clk handle is invalid, just return\n");
		return -EFAULT;
	} else {
		/*release the module clock*/
		clk_disable(daudio_pll2clk);
	}
	if ((NULL == daudio_pllx8) ||(IS_ERR(daudio_pllx8))) {
		pr_err("daudio_pllx8 handle is invalid, just return\n");
		return -EFAULT;
	} else {
		/*release the module clock*/
		clk_disable(daudio_pllx8);
	}
	#endif
	devm_pinctrl_put(daudio_pinctrl);
	/* request pin individually */
	for (pin_index = 0; pin_index < pin_count; pin_index++) {
		pin_daudio0_cfg = &(pin_daudio0_list[pin_index].gpio);
		/* valid pin of sunxi-pinctrl, config pin attributes individually.*/
		sunxi_gpio_to_name(pin_daudio0_cfg->gpio, pin_name);
		config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 7);
		pin_config_set(SUNXI_PINCTRL, pin_name, config);
	}
	return 0;
}
예제 #10
0
static int sunxi_daudio0_trigger(struct snd_pcm_substream *substream,
                              int cmd, struct snd_soc_dai *dai)
{
	int ret = 0;
	u32 reg_val;
	switch (cmd) {
		case SNDRV_PCM_TRIGGER_START:
		case SNDRV_PCM_TRIGGER_RESUME:
		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
			if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
				sunxi_snd_rxctrl_daudio0(substream, 1);
			} else {
				sunxi_snd_txctrl_daudio0(substream, 1,0);
			}
			/*Global Enable Digital Audio Interface*/
			reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
			reg_val |= SUNXI_DAUDIOCTL_GEN;
			if (daudio0_loop_en) {
				reg_val |= SUNXI_DAUDIOCTL_LOOP; /*for test*/
			}
			sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
			break;
		case SNDRV_PCM_TRIGGER_STOP:
		case SNDRV_PCM_TRIGGER_SUSPEND:
		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
			if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
				sunxi_snd_rxctrl_daudio0(substream, 0);
			} else {
			  	sunxi_snd_txctrl_daudio0(substream, 0,0);
			}
			break;
		default:
			ret = -EINVAL;
			break;
	}

	return ret;
}
예제 #11
0
int sunxi_daudio0_set_rate(int freq) {
	int reg_val;
#ifdef CONFIG_ARCH_SUN9IW1
	if (clk_set_rate(daudio_pll3clk, freq)) {
			pr_err("try to set the i2s_pll3clk failed!\n");
	}
#else
	#ifdef CONFIG_ARCH_SUN8IW7
		if (clk_set_rate(daudio_pll, freq)) {
			pr_err("try to set the daudio_pll rate failed!\n");
		}
	#else
	if (clk_set_rate(daudio_pll2clk, freq)) {
		pr_err("try to set the daudio_pll2clk failed!\n");
	}
	#endif
#endif
	/*enable mclk*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCLKD);
	//reg_val &= ~(0x1<<SUNXI_DAUDIOCLKD_MCLKOEN);
	reg_val |= (0x1<<8);
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCLKD);
	return 0;
}
예제 #12
0
//static struct pinctrl *daudio_pinctrl;
static int __init sunxi_daudio0_dev_probe(struct platform_device *pdev)
{
	int ret = 0;
	int reg_val = 0;
	script_item_u val;
	script_item_value_type_e  type;


	sunxi_daudio.regs = ioremap(SUNXI_DAUDIOBASE, 0x100);
	if (sunxi_daudio.regs == NULL) {
		return -ENXIO;
	}
	/*for A80 evb pin config*/
	daudio_pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
	if (IS_ERR_OR_NULL(daudio_pinctrl)) {
		dev_warn(&pdev->dev,
			"pins are not configured from the driver\n");
	}
	pin_count = script_get_pio_list (TDM_NAME, &pin_daudio0_list);
	if (pin_count == 0) {
		/* "daudio0" have no pin configuration */
		pr_err("daudio0 have no pin configuration\n");
	}

#ifdef CONFIG_ARCH_SUN9IW1
	/*daudio pll2clk*/
	daudio_pll3clk = clk_get(NULL, "pll3");
	if ((!daudio_pll3clk)||(IS_ERR(daudio_pll3clk))) {
		pr_err("try to get daudio_pll2clk failed\n");
	}
	if (clk_prepare_enable(daudio_pll3clk)) {
		pr_err("enable daudio_pll2clk failed; \n");
	}
	/*daudio module clk*/
	daudio_moduleclk = clk_get(NULL, "cpuri2s1");
	if ((!daudio_moduleclk)||(IS_ERR(daudio_moduleclk))) {
		pr_err("try to get daudio_moduleclk failed\n");
	}
	if (clk_set_parent(daudio_moduleclk, daudio_pll3clk)) {
		pr_err("try to set parent of daudio_moduleclk to daudio_pll2ck failed! line = %d\n",__LINE__);
	}
	if (clk_set_rate(daudio_pll3clk, 24576000)) {
		pr_err("set daudio_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__);
	}

	if (clk_prepare_enable(daudio_moduleclk)) {
		pr_err("open daudio_moduleclk failed! line = %d\n", __LINE__);
	}
#else
#ifdef CONFIG_ARCH_SUN8IW7
	daudio_pll = clk_get(NULL, "pll_audio");
	if ((!daudio_pll)||(IS_ERR(daudio_pll))) {
		pr_err("try to get daudio_pll failed\n");
	}
	if (clk_prepare_enable(daudio_pll)) {
		pr_err("enable daudio_pll2clk failed; \n");
	}
	/*daudio module clk*/
	daudio_moduleclk = clk_get(NULL, "i2s0");
	if ((!daudio_moduleclk)||(IS_ERR(daudio_moduleclk))) {
		pr_err("try to get daudio_moduleclk failed\n");
	}
	if (clk_set_parent(daudio_moduleclk, daudio_pll)) {
		pr_err("try to set parent of daudio_moduleclk to daudio_pll2ck failed! line = %d\n",__LINE__);
	}

	if (clk_set_rate(daudio_moduleclk, 24576000)) {
		pr_err("set daudio_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__);
	}

	if (clk_prepare_enable(daudio_moduleclk)) {
		pr_err("open daudio_moduleclk failed! line = %d\n", __LINE__);
	}
#else
	daudio_pllx8 = clk_get(NULL, "pll_audiox8");
	if ((!daudio_pllx8)||(IS_ERR(daudio_pllx8))) {
		pr_err("try to get daudio_pllx8 failed\n");
	}
	if (clk_prepare_enable(daudio_pllx8)) {
		pr_err("enable daudio_pll2clk failed; \n");
	}

	/*daudio pll2clk*/
	daudio_pll2clk = clk_get(NULL, "pll2");
	if ((!daudio_pll2clk)||(IS_ERR(daudio_pll2clk))) {
		pr_err("try to get daudio_pll2clk failed\n");
	}
	if (clk_prepare_enable(daudio_pll2clk)) {
		pr_err("enable daudio_pll2clk failed; \n");
	}
#ifdef CONFIG_ARCH_SUN8IW8
	/*daudio module clk*/
	daudio_moduleclk = clk_get(NULL, "i2s0");
#else
	//pr_debug("%s,line:%d,0xbc:%x\n",__func__,__LINE__,sunxi_smc_readl(0xf1c200bc));
	daudio_moduleclk = clk_get(NULL, "tdm");
#endif
	if ((!daudio_moduleclk)||(IS_ERR(daudio_moduleclk))) {
		pr_err("try to get daudio_moduleclk failed\n");
	}

	if (clk_set_parent(daudio_moduleclk, daudio_pll2clk)) {
		pr_err("try to set parent of daudio_moduleclk to daudio_pll2ck failed! line = %d\n",__LINE__);
	}
#if defined(CONFIG_ARCH_SUN8IW6) || defined(CONFIG_ARCH_SUN8IW8)
//#ifdef CONFIG_ARCH_SUN8IW6
	if (clk_set_rate(daudio_moduleclk, 24576000)) {
		pr_err("set daudio_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__);
	}
#else
	if (clk_set_rate(daudio_moduleclk, 24576000/8)) {
		pr_err("set daudio_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__);
	}
#endif
	if (clk_prepare_enable(daudio_moduleclk)) {
		pr_err("open daudio_moduleclk failed! line = %d\n", __LINE__);
	}
	//pr_debug("%s,line:%d,bc:%x\n",__func__,__LINE__,sunxi_smc_readl(0xf1c200bc));
#endif
#endif
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	reg_val |= SUNXI_DAUDIOCTL_GEN;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);

	type = script_get_item(TDM_NAME, "mclk_fs", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] mclk_fs type err!\n");
    }
	mclk_fs = val.val;

	type = script_get_item(TDM_NAME, "sample_resolution", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] sample_resolution type err!\n");
    }
	sample_resolution = val.val;

	type = script_get_item(TDM_NAME, "slot_width_select", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] slot_width_select type err!\n");
    }
	slot_width_select = val.val;

	type = script_get_item(TDM_NAME, "pcm_lrck_period", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] pcm_lrck_period type err!\n");
    }
	pcm_lrck_period = val.val;

	type = script_get_item(TDM_NAME, "pcm_lrckr_period", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] pcm_lrckr_period type err!\n");
    }
	pcm_lrckr_period = val.val;

	type = script_get_item(TDM_NAME, "msb_lsb_first", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] msb_lsb_first type err!\n");
    }
	msb_lsb_first = val.val;
	type = script_get_item(TDM_NAME, "sign_extend", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] sign_extend type err!\n");
    }
	sign_extend = val.val;
	type = script_get_item(TDM_NAME, "slot_index", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] slot_index type err!\n");
    }
	slot_index = val.val;
	type = script_get_item(TDM_NAME, "frame_width", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] frame_width type err!\n");
    }
	frame_width = val.val;
	type = script_get_item(TDM_NAME, "tx_data_mode", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] tx_data_mode type err!\n");
    }
	tx_data_mode = val.val;

	type = script_get_item(TDM_NAME, "rx_data_mode", &val);
	if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
        pr_err("[DAUDIO] rx_data_mode type err!\n");
    }
	rx_data_mode = val.val;

	ret = snd_soc_register_dais(&pdev->dev,sunxi_daudio_dai, ARRAY_SIZE(sunxi_daudio_dai));
	if (ret) {
		dev_err(&pdev->dev, "Failed to register DAI\n");
	}

	return 0;
}
예제 #13
0
static int sun8i_cluster_power_set(unsigned int cluster, bool enable)
{
	unsigned int value;
	int          i;
#ifdef MCPM_WITH_ARISC_DVFS_SUPPORT
	/* cluster operation must wait arisc ready */
	if (!is_arisc_ready()) {
		pr_debug("%s: arisc not ready, can't power-up cluster\n", __func__);
		return -EINVAL;
	}
#endif
	if (enable) {
		pr_debug("sun8i power-up cluster-%d\n", cluster);

		/* assert cluster cores resets */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
#if defined(CONFIG_ARCH_SUN8IW6)
		value &= (~(0xF<<0));   /* Core Reset    */
#elif defined(CONFIG_ARCH_SUN8IW9)
		value &= (~(0x7<<0));   /* Core Reset    */
#endif
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(10);

		/* assert cluster cores power-on reset */
		value = sunxi_smc_readl(sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
#if defined(CONFIG_ARCH_SUN8IW6)
		value &= (~(0xF));
#elif defined(CONFIG_ARCH_SUN8IW9)
		value &= (~(0x7));
#endif
		sunxi_smc_writel(value, sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
		udelay(10);

		/* assert cluster resets */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		value &= (~(0x1<<24));  /* SOC DBG Reset */
#if defined(CONFIG_ARCH_SUN8IW6)
		value &= (~(0xF<<20));  /* ETM Reset     */
		value &= (~(0xF<<16));  /* Debug Reset   */
#elif defined(CONFIG_ARCH_SUN8IW9)
		value &= (~(0x7<<20));  /* ETM Reset     */
		value &= (~(0x7<<16));  /* Debug Reset   */
#endif
		value &= (~(0x1<<12));  /* HReset        */
		value &= (~(0x1<<8));   /* L2 Cache Reset*/
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(10);

		/* Set L2RSTDISABLE LOW */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL0(cluster));
		value &= (~(0x1<<4));
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL0(cluster));

#ifdef MCPM_WITH_ARISC_DVFS_SUPPORT
		/* notify arisc to power-up cluster */
		arisc_dvfs_set_cpufreq(cluster_powerup_freq[cluster], cluster_pll[cluster],
		                       ARISC_MESSAGE_ATTR_SOFTSYN, NULL, NULL);
		mdelay(1);
#endif

#ifdef CONFIG_ARCH_SUN8IW6
		if (soc_version == SUN8IW6P1_REV_A)
			sun8i_cpu_power_switch_set(cluster, 0, 1);
#endif
		/* active ACINACTM */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL1(cluster));
		value |= (1<<0);
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL1(cluster));

		/* clear cluster power-off gating */
		value = sunxi_smc_readl(sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
#ifdef CONFIG_ARCH_SUN8IW6
		if (soc_version == SUN8IW6P1_REV_A)
			value &= (~(0x1<<4));
		value &= (~(0x1<<0));
#else
		value &= (~(0x1<<4));
#endif
		sunxi_smc_writel(value, sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		udelay(20);

		/* de-active ACINACTM */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL1(cluster));
		value &= (~(1<<0));
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL1(cluster));

		/* de-assert cores reset */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		value |= (0x1<<24);  /* SOC DBG Reset */
#if defined(CONFIG_ARCH_SUN8IW6)
		value |= (0xF<<20);  /* ETM Reset     */
		value |= (0xF<<16);  /* Debug Reset   */
#elif defined(CONFIG_ARCH_SUN8IW9)
		value |= (0x7<<20);  /* ETM Reset     */
		value |= (0x7<<16);  /* Debug Reset   */
#endif
		value |= (0x1<<12);  /* HReset        */
		value |= (0x1<<8);   /* L2 Cache Reset*/
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(20);
		pr_debug("sun8i power-up cluster-%d ok\n", cluster);
	} else {

		pr_debug("sun8i power-down cluster-%d\n", cluster);

		/* active ACINACTM */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL1(cluster));
		value |= (1<<0);
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL1(cluster));

		while (1) {
			if (SUN8I_L2CACHE_IS_WFI_MODE(cluster)) {
				break;
			}
			/* maybe should support timeout to avoid deadloop */
		}

		/* assert cluster cores resets */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
#if defined(CONFIG_ARCH_SUN8IW6)
		value &= (~(0xF<<0));   /* Core Reset    */
#elif defined(CONFIG_ARCH_SUN8IW9)
		value &= (~(0x7<<0));   /* Core Reset    */
#endif
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(10);

		/* assert cluster cores power-on reset */
		value = sunxi_smc_readl(sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
#if defined(CONFIG_ARCH_SUN8IW6)
		value &= (~(0xF));
#elif defined(CONFIG_ARCH_SUN8IW9)
		value &= (~(0x7));
#endif
		sunxi_smc_writel(value, sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
		udelay(10);

		/* assert cluster resets */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		value &= (~(0x1<<24));  /* SOC DBG Reset */
#if defined(CONFIG_ARCH_SUN8IW6)
		value &= (~(0xF<<20));  /* ETM Reset     */
		value &= (~(0xF<<16));  /* Debug Reset   */
#elif defined(CONFIG_ARCH_SUN8IW9)
		value &= (~(0x7<<20));  /* ETM Reset     */
		value &= (~(0x7<<16));  /* Debug Reset   */
#endif
		value &= (~(0x1<<12));  /* HReset        */
		value &= (~(0x1<<8));   /* L2 Cache Reset*/
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(10);

		/* enable cluster and cores power-off gating */
		value = sunxi_smc_readl(sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		value |= (1<<4);
#if defined(CONFIG_ARCH_SUN8IW6)
		value |= (0xF<<0);
#elif defined(CONFIG_ARCH_SUN8IW9)
		value |= (0x7<<0);
#endif
		sunxi_smc_writel(value, sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		udelay(20);

		/* disable cluster cores power switch */
		for (i = 0; i < CORES_PER_CLUSTER; i++) {
			sun8i_cpu_power_switch_set(cluster, i, 0);
		}

#ifdef MCPM_WITH_ARISC_DVFS_SUPPORT
		/* notify arisc to power-down cluster,
		 * arisc will disable cluster clock and power-off cpu power domain.
		 */
		arisc_dvfs_set_cpufreq(0, cluster_pll[cluster],
		                       ARISC_MESSAGE_ATTR_SOFTSYN, NULL, NULL);
#endif
		pr_debug("sun8i power-down cluster-%d ok\n", cluster);
	}

	return 0;
}
예제 #14
0
static void daudioregsave(void)
{
	regsave[0] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	regsave[1] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	regsave[2] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT1);
	regsave[3] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL) | (0x3<<24);
	regsave[4] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOINT);
	regsave[5] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCLKD);
	regsave[6] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_TXCHCFG);
	regsave[7] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOTX0CHSEL);
	regsave[8] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOTX0CHMAP);
	regsave[9] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIORXCHSEL);
	regsave[10] = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIORXCHMAP);
}
예제 #15
0
int sunxi_daudio0_perpare(struct snd_pcm_substream *substream,
	struct snd_soc_dai *cpu_dai)
{
	u32 reg_val;
	/* play or record */
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_TXCHCFG);
		if (substream->runtime->channels == 1) {
			reg_val &= ~(0x7<<0);
			reg_val |= (0x0)<<0;
		} else {
			reg_val &= ~(0x7<<0);
			reg_val |= (0x1)<<0;
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_TXCHCFG);
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOTX0CHSEL);
		reg_val |= (0x1<<12);
		reg_val &= ~(0xff<<4);
		reg_val &= ~(0x7<<0);
		if (substream->runtime->channels == 1) {
			reg_val |= (0x3<<4);
			reg_val	|= (0x1<<0);
		} else {
			reg_val |= (0x3<<4);
			reg_val	|= (0x1<<0);
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOTX0CHSEL);
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOTX0CHMAP);
		reg_val = 0;
		if(substream->runtime->channels == 1) {
			reg_val = 0x0;
		} else {
			reg_val = 0x10;
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOTX0CHMAP);

		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
		reg_val &= ~SUNXI_DAUDIOCTL_SDO3EN;
		reg_val &= ~SUNXI_DAUDIOCTL_SDO2EN;
		reg_val &= ~SUNXI_DAUDIOCTL_SDO1EN;
		reg_val &= ~SUNXI_DAUDIOCTL_SDO0EN;
		switch (substream->runtime->channels) {
			case 1:
			case 2:
				reg_val |= SUNXI_DAUDIOCTL_SDO0EN;
				break;
			case 3:
			case 4:
				reg_val |= SUNXI_DAUDIOCTL_SDO0EN | SUNXI_DAUDIOCTL_SDO1EN;
				break;
			case 5:
			case 6:
				reg_val |= SUNXI_DAUDIOCTL_SDO0EN | SUNXI_DAUDIOCTL_SDO1EN | SUNXI_DAUDIOCTL_SDO2EN;
				break;
			case 7:
			case 8:
				reg_val |= SUNXI_DAUDIOCTL_SDO0EN | SUNXI_DAUDIOCTL_SDO1EN | SUNXI_DAUDIOCTL_SDO2EN | SUNXI_DAUDIOCTL_SDO3EN;
				break;
			default:
				reg_val |= SUNXI_DAUDIOCTL_SDO0EN;
				break;
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
		/*clear TX counter*/
		sunxi_smc_writel(0, sunxi_daudio.regs + SUNXI_DAUDIOTXCNT);

		/* DAUDIO TX ENABLE */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
		reg_val |= SUNXI_DAUDIOCTL_TXEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	} else {
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_TXCHCFG);
		if (substream->runtime->channels == 1) {
			reg_val &= ~(0x7<<4);
			reg_val |= (0x0)<<4;
		} else {
			reg_val &= ~(0x7<<4);
			reg_val |= (0x1)<<4;
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_TXCHCFG);

		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIORXCHSEL);
		reg_val |= (0x1<<12);
		if(substream->runtime->channels == 1) {
			reg_val	&= ~(0x1<<0);
		} else {
			reg_val	|= (0x1<<0);
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIORXCHSEL);

		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIORXCHMAP);
		reg_val = 0;
		if (substream->runtime->channels == 1) {
			reg_val = 0x00;
		} else {
			reg_val = 0x10;
		}
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIORXCHMAP);
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFCTL);
		reg_val |= SUNXI_DAUDIOFCTL_RXOM;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFCTL);

		/*clear RX counter*/
		sunxi_smc_writel(0, sunxi_daudio.regs + SUNXI_DAUDIORXCNT);

		/* DAUDIO RX ENABLE */
		reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
		reg_val |= SUNXI_DAUDIOCTL_RXEN;
		sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	}
	return 0;
}
예제 #16
0
int sunxi_daudio0_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int sample_rate)
{
	u32 reg_val = 0;
	u32 mclk_div = 0;
	u32 bclk_div = 0;

	/*enable mclk*/
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCLKD);
	reg_val &= ~(0x1<<8);
	reg_val |= (0x1<<8);

	/*i2s mode*/
	if (daudio_select) {
		switch (sample_rate) {
			case 192000:
			case 96000:
			case 48000:
			case 32000:
			case 24000:
			case 12000:
			case 16000:
			case 8000:
				bclk_div = ((24576000/sample_rate)/(2*pcm_lrck_period));
				mclk_div = 1;
			break;
			default:
				bclk_div = ((22579200/sample_rate)/(2*pcm_lrck_period));
				mclk_div = 1;
			break;
		}
	} else {/*pcm mode*/
		bclk_div = ((24576000/sample_rate)/(pcm_lrck_period));
		mclk_div = 1;//((24576000/sample_rate)/mclk_fs);
	}

	switch(mclk_div)
	{
		case 1: mclk_div = 1;
				break;
		case 2: mclk_div = 2;
				break;
		case 4: mclk_div = 3;
				break;
		case 6: mclk_div = 4;
				break;
		case 8: mclk_div = 5;
				break;
		case 12: mclk_div = 6;
				 break;
		case 16: mclk_div = 7;
				 break;
		case 24: mclk_div = 8;
				 break;
		case 32: mclk_div = 9;
				 break;
		case 48: mclk_div = 10;
				 break;
		case 64: mclk_div = 11;
				 break;
		case 96: mclk_div = 12;
				 break;
		case 128: mclk_div = 13;
				 break;
		case 176: mclk_div = 14;
				 break;
		case 192: mclk_div = 15;
				 break;
	}

	reg_val &= ~(0xf<<0);
	reg_val |= mclk_div<<0;
	switch(bclk_div)
	{
		case 1: bclk_div = 1;
			break;
		case 2: bclk_div = 2;
			break;
		case 4: bclk_div = 3;
			break;
		case 6: bclk_div = 4;
			break;
		case 8: bclk_div = 5;
			break;
		case 12: bclk_div = 6;
			break;
		case 16: bclk_div = 7;
			break;
		case 24: bclk_div = 8;
			break;
		case 32: bclk_div = 9;
			break;
		case 48: bclk_div = 10;
			break;
		case 64: bclk_div = 11;
			break;
		case 96: bclk_div = 12;
			break;
		case 128: bclk_div = 13;
			break;
		case 176: bclk_div = 14;
			break;
		case 192:bclk_div = 15;
	}
	reg_val &= ~(0xf<<4);
	reg_val |= bclk_div<<4;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCLKD);
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	reg_val &= ~(0x3ff<<20);
	reg_val &= ~(0x3ff<<8);
	reg_val |= (pcm_lrck_period-1)<<8;
	reg_val |= (pcm_lrckr_period-1)<<20;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	/* slot size select */
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	sunxi_daudio.slot_width = slot_width_select;
	reg_val &= ~SUNXI_DAUDIOFAT0_SW;
	if(sunxi_daudio.slot_width == 16)
		reg_val |= (3<<0);
	else if(sunxi_daudio.slot_width == 20) 
		reg_val |= (4<<0);
	else if(sunxi_daudio.slot_width == 24)
		reg_val |= (5<<0);
	else if(sunxi_daudio.slot_width == 32)
		reg_val |= (7<<0);
	else
		reg_val |= (1<<0);

	sunxi_daudio.samp_res = sample_resolution;
	reg_val &= ~SUNXI_DAUDIOFAT0_SR;
	if(sunxi_daudio.samp_res == 16)
		reg_val |= (3<<4);
	else if(sunxi_daudio.samp_res == 20)
		reg_val |= (4<<4);
	else
		reg_val |= (5<<4);
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT1);

	sunxi_daudio.frametype = frame_width;
	if(sunxi_daudio.frametype)
		reg_val |= SUNXI_DAUDIOFAT0_LRCK_WIDTH;	

	sunxi_daudio.pcm_start_slot = slot_index;
	reg_val |=(sunxi_daudio.pcm_start_slot & 0x3)<<6;

	sunxi_daudio.pcm_lsb_first = msb_lsb_first;
	reg_val |= sunxi_daudio.pcm_lsb_first<<7;
	reg_val |= sunxi_daudio.pcm_lsb_first<<6;

	sunxi_daudio.signext = sign_extend;
	reg_val &= ~(0x3<<4);
	reg_val |= sunxi_daudio.signext<<4;

	/*linear or u/a-law*/
	reg_val &= ~(0xf<<0);
	reg_val |= (tx_data_mode)<<2;
	reg_val |= (rx_data_mode)<<0;
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOFAT1);

	return 0;
}
예제 #17
0
int sun8i_cpu_power_set(unsigned int cluster, unsigned int cpu, bool enable)
{
	unsigned int value;
	if (enable) {
		/*
		 * power-up cpu core process
		 */
		pr_debug("sun8i power-up cluster-%d cpu-%d\n", cluster, cpu);

		cpumask_set_cpu(((cluster)*4 + cpu), &cpu_power_up_state_mask);

		/* assert cpu core reset */
		value  = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		value &= (~(1<<cpu));
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(10);

		/* assert cpu power-on reset */
		value  = sunxi_smc_readl(sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
		value &= (~(1<<cpu));
		sunxi_smc_writel(value, sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
		udelay(10);

		/* L1RSTDISABLE hold low */
		value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL0(cluster));
		value &= ~(1<<cpu);
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CLUSTER_CTRL0(cluster));

		/* release power switch */
		sun8i_cpu_power_switch_set(cluster, cpu, 1);

#ifdef CONFIG_ARCH_SUN8IW6
		if (cpu == 0) {
			if (soc_version == SUN8IW6P1_REV_A) {
				/* de-assert cpu power-on reset */
				value = sunxi_smc_readl(sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
				value |= ((1<<cpu));
				sunxi_smc_writel(value, sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
				udelay(10);

				/* assert cpu core reset */
				value  = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
				value |= (1<<cpu);
				cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
				udelay(10);
				return 0;
			} else {
				/* bit4: C1_cpu0 */
				cpu = 4;
			}
		}
#endif

		/* clear power-off gating */
		value = sunxi_smc_readl(sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		value &= (~(0x1<<cpu));
		sunxi_smc_writel(value, sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		udelay(20);

#ifdef CONFIG_ARCH_SUN8IW6
		if (cpu == 4)
			cpu = 0;
#endif

		/* de-assert cpu power-on reset */
		value  = sunxi_smc_readl(sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
		value |= ((1<<cpu));
		sunxi_smc_writel(value, sun8i_cpuscfg_base + SUNXI_CLUSTER_PWRON_RESET(cluster));
		udelay(10);

		/* de-assert core reset */
		value  = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		value |= (1<<cpu);
		cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
		udelay(10);

		pr_debug("sun8i power-up cluster-%d cpu-%d already\n", cluster, cpu);
	} else {
		/*
		 * power-down cpu core process
		 */
		pr_debug("sun8i power-down cluster-%d cpu-%d\n", cluster, cpu);
#ifdef CONFIG_ARCH_SUN8IW6
		if (cpu == 0) {
			if (soc_version == SUN8IW6P1_REV_A) {
				/* assert cpu core reset */
				value = cpu_cfg_readl(sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
				value &= (~(1<<cpu));
				cpu_cfg_writel(value, sun8i_cpuxcfg_base + SUNXI_CPU_RST_CTRL(cluster));
				udelay(10);

				cpumask_clear_cpu(((cluster)*4 + cpu), &cpu_power_up_state_mask);
				return 0;
			} else {
				/* bit4: C1_cpu0 */
				cpu = 4;
			}
		}
#endif
		/* enable cpu power-off gating */
		value = sunxi_smc_readl(sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		value |= (1 << cpu);
		sunxi_smc_writel(value, sun8i_prcm_base + SUNXI_CLUSTER_PWROFF_GATING(cluster));
		udelay(20);

#ifdef CONFIG_ARCH_SUN8IW6
		if (cpu == 4)
			cpu = 0;
#endif

		/* active the power output switch */
		sun8i_cpu_power_switch_set(cluster, cpu, 0);

		cpumask_clear_cpu(((cluster)*4 + cpu), &cpu_power_up_state_mask);
		pr_debug("sun8i power-down cpu%d ok.\n", cpu);
	}
	return 0;
}
예제 #18
0
int sunxi_daudio0_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
	u32 reg_val = 0;
	u32 reg_val1 = 0;

	/* master or slave selection */
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	switch(fmt & SND_SOC_DAIFMT_MASTER_MASK){
		case SND_SOC_DAIFMT_CBM_CFM:   /* codec clk & frm master, ap is slave*/
			reg_val &= ~SUNXI_DAUDIOCTL_LRCKOUT;
			reg_val &= ~SUNXI_DAUDIOCTL_BCLKOUT;
			break;
		case SND_SOC_DAIFMT_CBS_CFS:   /* codec clk & frm slave,ap is master*/
			reg_val |= SUNXI_DAUDIOCTL_LRCKOUT;
			reg_val |= SUNXI_DAUDIOCTL_BCLKOUT;
			break;
		default:
			pr_err("unknwon master/slave format\n");
			return -EINVAL;
	}
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	/* pcm or daudio mode selection */
	reg_val = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	reg_val1 = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOTX0CHSEL);
	reg_val &= ~SUNXI_DAUDIOCTL_MODESEL;
	reg_val1 &= ~SUNXI_DAUDIOTXn_OFFSET;
	switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
		case SND_SOC_DAIFMT_I2S:        /* i2s mode */
			reg_val  |= (1<<4);
			reg_val1 |= (1<<12);
			break;
		case SND_SOC_DAIFMT_RIGHT_J:    /* Right Justified mode */
			reg_val  |= (2<<4);
			break;
		case SND_SOC_DAIFMT_LEFT_J:     /* Left Justified mode */
			reg_val  |= (1<<4);
			reg_val1  |= (0<<12);
			break;
		case SND_SOC_DAIFMT_DSP_A:      /* L data msb after FRM LRC */
			reg_val  |= (0<<4);
			reg_val1  |= (1<<12);
			break;
		case SND_SOC_DAIFMT_DSP_B:      /* L data msb during FRM LRC */
			reg_val  |= (0<<4);
			reg_val1  |= (0<<12);
			break;
		default:
			return -EINVAL;
	}
	sunxi_smc_writel(reg_val, sunxi_daudio.regs + SUNXI_DAUDIOCTL);
	sunxi_smc_writel(reg_val1, sunxi_daudio.regs + SUNXI_DAUDIOTX0CHSEL);
	/* DAI signal inversions */
	reg_val1 = sunxi_smc_readl(sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	switch(fmt & SND_SOC_DAIFMT_INV_MASK){
		case SND_SOC_DAIFMT_NB_NF:     /* normal bit clock + frame */
			reg_val1 &= ~SUNXI_DAUDIOFAT0_BCLK_POLAYITY;
			reg_val1 &= ~SUNXI_DAUDIOFAT0_LRCK_POLAYITY;
			break;
		case SND_SOC_DAIFMT_NB_IF:     /* normal bclk + inv frm */
			reg_val1 |= SUNXI_DAUDIOFAT0_LRCK_POLAYITY;
			reg_val1 &= ~SUNXI_DAUDIOFAT0_BCLK_POLAYITY;
			break;
		case SND_SOC_DAIFMT_IB_NF:     /* invert bclk + nor frm */
			reg_val1 &= ~SUNXI_DAUDIOFAT0_LRCK_POLAYITY;
			reg_val1 |= SUNXI_DAUDIOFAT0_BCLK_POLAYITY;
			break;
		case SND_SOC_DAIFMT_IB_IF:     /* invert bclk + frm */
			reg_val1 |= SUNXI_DAUDIOFAT0_LRCK_POLAYITY;
			reg_val1 |= SUNXI_DAUDIOFAT0_BCLK_POLAYITY;
			break;
	}
	sunxi_smc_writel(reg_val1, sunxi_daudio.regs + SUNXI_DAUDIOFAT0);
	return 0;
}