Exemplo n.º 1
0
static int __devinit device_gpadc_init(struct pm80x_chip *chip,
				       struct pm80x_platform_data *pdata)
{
	struct pm80x_subchip *subchip = chip->subchip;
	struct regmap *map = subchip->regmap_gpadc;
	int data = 0, mask = 0, ret = 0;

	if (!map) {
		dev_warn(chip->dev,
			 "Warning: gpadc regmap is not available!\n");
		return -EINVAL;
	}
	/*
	 * initialize GPADC without activating it turn on GPADC
	 * measurments
	 */
	ret = regmap_update_bits(map,
				 PM800_GPADC_MISC_CONFIG2,
				 PM800_GPADC_MISC_GPFSM_EN,
				 PM800_GPADC_MISC_GPFSM_EN);
	if (ret < 0)
		goto out;
	/*
	 * This function configures the ADC as requires for
	 * CP implementation.CP does not "own" the ADC configuration
	 * registers and relies on AP.
	 * Reason: enable automatic ADC measurements needed
	 * for CP to get VBAT and RF temperature readings.
	 */
	ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN1,
				 PM800_MEAS_EN1_VBAT, PM800_MEAS_EN1_VBAT);
	if (ret < 0)
		goto out;
	ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN2,
				 (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN),
				 (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN));
	if (ret < 0)
		goto out;

	/*
	 * the defult of PM800 is GPADC operates at 100Ks/s rate
	 * and Number of GPADC slots with active current bias prior
	 * to GPADC sampling = 1 slot for all GPADCs set for
	 * Temprature mesurmants
	 */
	mask = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
		PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3);

	if (pdata && (pdata->batt_det == 0))
		data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 |
			PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3);
	else
		data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN2 |
			PM800_GPADC_GP_BIAS_EN3);

	ret = regmap_update_bits(map, PM800_GP_BIAS_ENA1, mask, data);
	if (ret < 0)
		goto out;

	dev_info(chip->dev, "pm800 device_gpadc_init: Done\n");
	return 0;

out:
	dev_info(chip->dev, "pm800 device_gpadc_init: Failed!\n");
	return ret;
}
Exemplo n.º 2
0
static int max8973_init_dcdc(struct max8973_chip *max,
			     struct max8973_regulator_platform_data *pdata)
{
	int ret;
	uint8_t	control1 = 0;
	uint8_t control2 = 0;

	if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
		control1 |= MAX8973_SNS_ENABLE;

	if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE))
		control1 |= MAX8973_NFSR_ENABLE;

	if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
		control1 |= MAX8973_AD_ENABLE;

	if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
		control1 |= MAX8973_BIAS_ENABLE;

	if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
		control1 |= MAX8973_FREQSHIFT_9PER;

	/* Set ramp delay */
	if (pdata->reg_init_data &&
			pdata->reg_init_data->constraints.ramp_delay) {
		if (pdata->reg_init_data->constraints.ramp_delay < 25000)
			control1 |= MAX8973_RAMP_12mV_PER_US;
		else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
			control1 |= MAX8973_RAMP_25mV_PER_US;
		else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
			control1 |= MAX8973_RAMP_50mV_PER_US;
		else
			control1 |= MAX8973_RAMP_200mV_PER_US;
	} else {
		control1 |= MAX8973_RAMP_12mV_PER_US;
		max->desc.ramp_delay = 12500;
	}

	if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
		control2 |= MAX8973_DISCH_ENBABLE;

	/*  Clock advance trip configuration */
	switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) {
	case MAX8973_CONTROL_CLKADV_TRIP_DISABLED:
		control2 |= MAX8973_CKKADV_TRIP_DISABLE;
		break;

	case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US:
		control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US;
		break;

	case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US:
		control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US;
		break;

	case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS:
		control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS;
		break;
	}

	/* Configure inductor value */
	switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) {
	case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL:
		control2 |= MAX8973_INDUCTOR_NOMINAL;
		break;

	case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER:
		control2 |= MAX8973_INDUCTOR_MIN_30_PER;
		break;

	case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER:
		control2 |= MAX8973_INDUCTOR_PLUS_30_PER;
		break;

	case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER:
		control2 |= MAX8973_INDUCTOR_PLUS_60_PER;
		break;
	}

	ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1);
	if (ret < 0) {
		dev_err(max->dev, "register %d write failed, err = %d",
				MAX8973_CONTROL1, ret);
		return ret;
	}

	ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2);
	if (ret < 0) {
		dev_err(max->dev, "register %d write failed, err = %d",
				MAX8973_CONTROL2, ret);
		return ret;
	}

	/* If external control is enabled then disable EN bit */
	if (max->enable_external_control) {
		ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
						MAX8973_VOUT_ENABLE, 0);
		if (ret < 0)
			dev_err(max->dev, "register %d update failed, err = %d",
				MAX8973_VOUT, ret);
	}
	return ret;
}
Exemplo n.º 3
0
static int uda134x_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params,
	struct snd_soc_dai *dai)
{
	struct snd_soc_codec *codec = dai->codec;
	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
	unsigned int hw_params = 0;

	if (substream == uda134x->slave_substream) {
		pr_debug("%s ignoring hw_params for slave substream\n",
			 __func__);
		return 0;
	}

	pr_debug("%s sysclk: %d, rate:%d\n", __func__,
		 uda134x->sysclk, params_rate(params));

	/* set SYSCLK / fs ratio */
	switch (uda134x->sysclk / params_rate(params)) {
	case 512:
		break;
	case 384:
		hw_params |= (1<<4);
		break;
	case 256:
		hw_params |= (1<<5);
		break;
	default:
		printk(KERN_ERR "%s unsupported fs\n", __func__);
		return -EINVAL;
	}

	pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
		 uda134x->dai_fmt, params_format(params));

	/* set DAI format and word length */
	switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		switch (params_width(params)) {
		case 16:
			hw_params |= (1<<1);
			break;
		case 18:
			hw_params |= (1<<2);
			break;
		case 20:
			hw_params |= ((1<<2) | (1<<1));
			break;
		default:
			printk(KERN_ERR "%s unsupported format (right)\n",
			       __func__);
			return -EINVAL;
		}
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		hw_params |= (1<<3);
		break;
	default:
		printk(KERN_ERR "%s unsupported format\n", __func__);
		return -EINVAL;
	}

	return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0,
		STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params);
}
Exemplo n.º 4
0
int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask)
{
	return regmap_update_bits(sec_pmic->regmap, reg, mask, val);
}
Exemplo n.º 5
0
static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev,
				    bool tx, bool rx)
{
	int timeout = 1000;
	uint32_t syncval;
	uint32_t csreg;
	uint32_t i2s_active_state;
	bool clk_was_prepared;
	uint32_t off;
	uint32_t clr;

	off =  tx ? BCM2835_I2S_TXON : 0;
	off |= rx ? BCM2835_I2S_RXON : 0;

	clr =  tx ? BCM2835_I2S_TXCLR : 0;
	clr |= rx ? BCM2835_I2S_RXCLR : 0;

	/* Backup the current state */
	regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);
	i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON);

	/* Start clock if not running */
	clk_was_prepared = dev->clk_prepared;
	if (!clk_was_prepared)
		bcm2835_i2s_start_clock(dev);

	/* Stop I2S module */
	regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0);

	/*
	 * Clear the FIFOs
	 * Requires at least 2 PCM clock cycles to take effect
	 */
	regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, clr, clr);

	/* Wait for 2 PCM clock cycles */

	/*
	 * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back
	 * FIXME: This does not seem to work for slave mode!
	 */
	regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &syncval);
	syncval &= BCM2835_I2S_SYNC;

	regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
			BCM2835_I2S_SYNC, ~syncval);

	/* Wait for the SYNC flag changing it's state */
	while (--timeout) {
		regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);
		if ((csreg & BCM2835_I2S_SYNC) != syncval)
			break;
	}

	if (!timeout)
		dev_err(dev->dev, "I2S SYNC error!\n");

	/* Stop clock if it was not running before */
	if (!clk_was_prepared)
		bcm2835_i2s_stop_clock(dev);

	/* Restore I2S state */
	regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
			BCM2835_I2S_RXON | BCM2835_I2S_TXON, i2s_active_state);
}
Exemplo n.º 6
0
static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
	u32 xcr = 0, xccr = 0, mask;

	/* DAI mode */
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		/* Data on rising edge of bclk, frame low, 1clk before data */
		xcr |= ESAI_xCR_xFSR;
		xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		/* Data on rising edge of bclk, frame high */
		xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		/* Data on rising edge of bclk, frame high, right aligned */
		xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA;
		break;
	case SND_SOC_DAIFMT_DSP_A:
		/* Data on rising edge of bclk, frame high, 1clk before data */
		xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR;
		xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
		break;
	case SND_SOC_DAIFMT_DSP_B:
		/* Data on rising edge of bclk, frame high */
		xcr |= ESAI_xCR_xFSL;
		xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
		break;
	default:
		return -EINVAL;
	}

	/* DAI clock inversion */
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_NF:
		/* Nothing to do for both normal cases */
		break;
	case SND_SOC_DAIFMT_IB_NF:
		/* Invert bit clock */
		xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP;
		break;
	case SND_SOC_DAIFMT_NB_IF:
		/* Invert frame clock */
		xccr ^= ESAI_xCCR_xFSP;
		break;
	case SND_SOC_DAIFMT_IB_IF:
		/* Invert both clocks */
		xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP;
		break;
	default:
		return -EINVAL;
	}

	esai_priv->slave_mode = false;

	/* DAI clock master masks */
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBM_CFM:
		esai_priv->slave_mode = true;
		break;
	case SND_SOC_DAIFMT_CBS_CFM:
		xccr |= ESAI_xCCR_xCKD;
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		xccr |= ESAI_xCCR_xFSD;
		break;
	case SND_SOC_DAIFMT_CBS_CFS:
		xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD;
		break;
	default:
		return -EINVAL;
	}

	mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR;
	regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr);
	regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr);

	mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP |
		ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA;
	regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr);
	regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr);

	return 0;
}
Exemplo n.º 7
0
int arizona_set_fll(struct arizona_fll *fll, int source,
		    unsigned int Fref, unsigned int Fout)
{
	struct arizona *arizona = fll->arizona;
	struct arizona_fll_cfg cfg, sync;
	unsigned int reg, val;
	int syncsrc;
	bool ena;
	int ret;

	ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
	if (ret != 0) {
		arizona_fll_err(fll, "Failed to read current state: %d\n",
				ret);
		return ret;
	}
	ena = reg & ARIZONA_FLL1_ENA;

	if (Fout) {
		/* Do we have a 32kHz reference? */
		regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
		switch (val & ARIZONA_CLK_32K_SRC_MASK) {
		case ARIZONA_CLK_SRC_MCLK1:
		case ARIZONA_CLK_SRC_MCLK2:
			syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
			break;
		default:
			syncsrc = -1;
		}

		if (source == syncsrc)
			syncsrc = -1;

		if (syncsrc >= 0) {
			ret = arizona_calc_fll(fll, &sync, Fref, Fout);
			if (ret != 0)
				return ret;

			ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
			if (ret != 0)
				return ret;
		} else {
			ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
			if (ret != 0)
				return ret;
		}
	} else {
		regmap_update_bits(arizona->regmap, fll->base + 1,
				   ARIZONA_FLL1_ENA, 0);
		regmap_update_bits(arizona->regmap, fll->base + 0x11,
				   ARIZONA_FLL1_SYNC_ENA, 0);

		if (ena)
			pm_runtime_put_autosuspend(arizona->dev);

		return 0;
	}

	regmap_update_bits(arizona->regmap, fll->base + 5,
			   ARIZONA_FLL1_OUTDIV_MASK,
			   cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);

	if (syncsrc >= 0) {
		arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
		arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
	} else {
		arizona_apply_fll(arizona, fll->base, &cfg, source);
	}

	if (!ena)
		pm_runtime_get(arizona->dev);

	/* Clear any pending completions */
	try_wait_for_completion(&fll->ok);

	regmap_update_bits(arizona->regmap, fll->base + 1,
			   ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
	if (syncsrc >= 0)
		regmap_update_bits(arizona->regmap, fll->base + 0x11,
				   ARIZONA_FLL1_SYNC_ENA,
				   ARIZONA_FLL1_SYNC_ENA);

	ret = wait_for_completion_timeout(&fll->ok,
					  msecs_to_jiffies(25));
	if (ret == 0)
		arizona_fll_warn(fll, "Timed out waiting for lock\n");

	return 0;
}
Exemplo n.º 8
0
static int pm8xxx_read_channel_rsv(struct pm8xxx_xoadc *adc,
				   const struct pm8xxx_chan_info *ch,
				   u8 rsv, u16 *adc_code,
				   bool force_ratiometric)
{
	int ret;
	unsigned int val;
	u8 rsvmask, rsvval;
	u8 lsb, msb;

	dev_dbg(adc->dev, "read channel \"%s\", amux %d, prescale/mux: %d, rsv %d\n",
		ch->name, ch->hwchan->amux_channel, ch->hwchan->pre_scale_mux, rsv);

	mutex_lock(&adc->lock);

	/* Mux in this channel */
	val = ch->hwchan->amux_channel << ADC_AMUX_SEL_SHIFT;
	val |= ch->hwchan->pre_scale_mux << ADC_AMUX_PREMUX_SHIFT;
	ret = regmap_write(adc->map, ADC_ARB_USRP_AMUX_CNTRL, val);
	if (ret)
		goto unlock;

	/* Set up ratiometric scale value, mask off all bits except these */
	rsvmask = (ADC_ARB_USRP_RSV_RST | ADC_ARB_USRP_RSV_DTEST0 |
		   ADC_ARB_USRP_RSV_DTEST1 | ADC_ARB_USRP_RSV_OP);
	if (adc->variant->broken_ratiometric && !force_ratiometric) {
		/*
		 * Apparently the PM8058 has some kind of bug which is
		 * reflected in the vendor tree drivers/misc/pmix8058-xoadc.c
		 * which just hardcodes the RSV selector to SEL1 (0x20) for
		 * most cases and SEL0 (0x10) for the MUXOFF channel only.
		 * If we force ratiometric (currently only done when attempting
		 * to do ratiometric calibration) this doesn't seem to work
		 * very well and I suspect ratiometric conversion is simply
		 * broken or not supported on the PM8058.
		 *
		 * Maybe IO_SEL2 doesn't exist on PM8058 and bits 4 & 5 select
		 * the mode alone.
		 *
		 * Some PM8058 register documentation would be nice to get
		 * this right.
		 */
		if (ch->hwchan->amux_channel == PM8XXX_CHANNEL_MUXOFF)
			rsvval = ADC_ARB_USRP_RSV_IP_SEL0;
		else
			rsvval = ADC_ARB_USRP_RSV_IP_SEL1;
	} else {
		if (rsv == 0xff)
			rsvval = (ch->amux_ip_rsv << ADC_RSV_IP_SEL_SHIFT) |
				ADC_ARB_USRP_RSV_TRM;
		else
			rsvval = (rsv << ADC_RSV_IP_SEL_SHIFT) |
				ADC_ARB_USRP_RSV_TRM;
	}

	ret = regmap_update_bits(adc->map,
				 ADC_ARB_USRP_RSV,
				 ~rsvmask,
				 rsvval);
	if (ret)
		goto unlock;

	ret = regmap_write(adc->map, ADC_ARB_USRP_ANA_PARAM,
			   ADC_ARB_USRP_ANA_PARAM_DIS);
	if (ret)
		goto unlock;

	/* Decimation factor */
	ret = regmap_write(adc->map, ADC_ARB_USRP_DIG_PARAM,
			   ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT0 |
			   ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT1 |
			   ch->decimation << ADC_DIG_PARAM_DEC_SHIFT);
	if (ret)
		goto unlock;

	ret = regmap_write(adc->map, ADC_ARB_USRP_ANA_PARAM,
			   ADC_ARB_USRP_ANA_PARAM_EN);
	if (ret)
		goto unlock;

	/* Enable the arbiter, the Qualcomm code does it twice like this */
	ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL,
			   ADC_ARB_USRP_CNTRL_EN_ARB);
	if (ret)
		goto unlock;
	ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL,
			   ADC_ARB_USRP_CNTRL_EN_ARB);
	if (ret)
		goto unlock;


	/* Fire a request! */
	reinit_completion(&adc->complete);
	ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL,
			   ADC_ARB_USRP_CNTRL_EN_ARB |
			   ADC_ARB_USRP_CNTRL_REQ);
	if (ret)
		goto unlock;

	/* Next the interrupt occurs */
	ret = wait_for_completion_timeout(&adc->complete,
					  VADC_CONV_TIME_MAX_US);
	if (!ret) {
		dev_err(adc->dev, "conversion timed out\n");
		ret = -ETIMEDOUT;
		goto unlock;
	}

	ret = regmap_read(adc->map, ADC_ARB_USRP_DATA0, &val);
	if (ret)
		goto unlock;
	lsb = val;
	ret = regmap_read(adc->map, ADC_ARB_USRP_DATA1, &val);
	if (ret)
		goto unlock;
	msb = val;
	*adc_code = (msb << 8) | lsb;

	/* Turn off the ADC by setting the arbiter to 0 twice */
	ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL, 0);
	if (ret)
		goto unlock;
	ret = regmap_write(adc->map, ADC_ARB_USRP_CNTRL, 0);
	if (ret)
		goto unlock;

unlock:
	mutex_unlock(&adc->lock);
	return ret;
}
Exemplo n.º 9
0
static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
{
	struct samsung_usb2_phy_driver *drv = inst->drv;
	u32 rstbits = 0;
	u32 phypwr = 0;
	u32 rst;
	u32 pwr;
	u32 mode = 0;
	u32 switch_mode = 0;

	switch (inst->cfg->id) {
	case EXYNOS4x12_DEVICE:
		phypwr =	EXYNOS_4x12_UPHYPWR_PHY0;
		rstbits =	EXYNOS_4x12_URSTCON_PHY0;
		mode =		EXYNOS_4x12_MODE_SWITCH_DEVICE;
		switch_mode =	1;
		break;
	case EXYNOS4x12_HOST:
		phypwr =	EXYNOS_4x12_UPHYPWR_PHY1;
		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY;
		mode =		EXYNOS_4x12_MODE_SWITCH_HOST;
		switch_mode =	1;
		break;
	case EXYNOS4x12_HSIC0:
		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC0;
		rstbits =	EXYNOS_4x12_URSTCON_HSIC1 |
				EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
				EXYNOS_4x12_URSTCON_HOST_PHY;
		break;
	case EXYNOS4x12_HSIC1:
		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC1;
		rstbits =	EXYNOS_4x12_URSTCON_HSIC1 |
				EXYNOS_4x12_URSTCON_HOST_LINK_P1;
		break;
	};

	if (on) {
		if (switch_mode)
			regmap_update_bits(drv->reg_sys,
					   EXYNOS_4x12_MODE_SWITCH_OFFSET,
					   EXYNOS_4x12_MODE_SWITCH_MASK, mode);

		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
		pwr &= ~phypwr;
		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);

		rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
		rst |= rstbits;
		writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
		udelay(10);
		rst &= ~rstbits;
		writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
		/* The following delay is necessary for the reset sequence to be
		 * completed */
		udelay(80);
	} else {
		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
		pwr |= phypwr;
		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
	}
}
Exemplo n.º 10
0
static int rk808_rtc_probe(struct platform_device *pdev)
{
	struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
	struct rk808_rtc *rk808_rtc;
	struct rtc_time tm;
	int ret;

	rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
	if (rk808_rtc == NULL)
		return -ENOMEM;

	platform_set_drvdata(pdev, rk808_rtc);
	rk808_rtc->rk808 = rk808;

	/* start rtc running by default, and use shadowed timer. */
	ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
				 BIT_RTC_CTRL_REG_STOP_RTC_M |
				 BIT_RTC_CTRL_REG_RTC_READSEL_M,
				 BIT_RTC_CTRL_REG_RTC_READSEL_M);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to update RTC control: %d\n", ret);
		return ret;
	}

	ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
			   RTC_STATUS_MASK);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to write RTC status: %d\n", ret);
			return ret;
	}

	/* set init time */
	ret = rk808_rtc_readtime(&pdev->dev, &tm);
	if (ret) {
		dev_err(&pdev->dev, "Failed to read RTC time\n");
		return ret;
	}
	ret = rtc_valid_tm(&tm);
	if (ret)
		dev_warn(&pdev->dev, "invalid date/time\n");

	device_init_wakeup(&pdev->dev, 1);

	rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
						  &rk808_rtc_ops, THIS_MODULE);
	if (IS_ERR(rk808_rtc->rtc)) {
		ret = PTR_ERR(rk808_rtc->rtc);
		return ret;
	}

	rk808_rtc->irq = platform_get_irq(pdev, 0);
	if (rk808_rtc->irq < 0) {
		if (rk808_rtc->irq != -EPROBE_DEFER)
			dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n",
				rk808_rtc->irq);
		return rk808_rtc->irq;
	}

	/* request alarm irq of rk808 */
	ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL,
					rk808_alarm_irq, 0,
					"RTC alarm", rk808_rtc);
	if (ret) {
		dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
			rk808_rtc->irq, ret);
	}

	return ret;
}
Exemplo n.º 11
0
static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
			     unsigned long *configs, unsigned num_configs)
{
	struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
	struct meson_bank *bank;
	enum pin_config_param param;
	unsigned int reg, bit;
	int i, ret;

	ret = meson_get_bank(pc, pin, &bank);
	if (ret)
		return ret;

	for (i = 0; i < num_configs; i++) {
		param = pinconf_to_config_param(configs[i]);

		switch (param) {
		case PIN_CONFIG_BIAS_DISABLE:
			dev_dbg(pc->dev, "pin %u: disable bias\n", pin);

			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
			ret = regmap_update_bits(pc->reg_pull, reg,
						 BIT(bit), 0);
			if (ret)
				return ret;
			break;
		case PIN_CONFIG_BIAS_PULL_UP:
			dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin);

			meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
					       &reg, &bit);
			ret = regmap_update_bits(pc->reg_pullen, reg,
						 BIT(bit), BIT(bit));
			if (ret)
				return ret;

			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
			ret = regmap_update_bits(pc->reg_pull, reg,
						 BIT(bit), BIT(bit));
			if (ret)
				return ret;
			break;
		case PIN_CONFIG_BIAS_PULL_DOWN:
			dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin);

			meson_calc_reg_and_bit(bank, pin, REG_PULLEN,
					       &reg, &bit);
			ret = regmap_update_bits(pc->reg_pullen, reg,
						 BIT(bit), BIT(bit));
			if (ret)
				return ret;

			meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
			ret = regmap_update_bits(pc->reg_pull, reg,
						 BIT(bit), 0);
			if (ret)
				return ret;
			break;
		default:
			return -ENOTSUPP;
		}
	}

	return 0;
}
Exemplo n.º 12
0
static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai,
		unsigned int fmt)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
	unsigned int serictl = 0x00, seroctl = 0x00;
	bool invert_lrclk;

	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBM_CFM:
		/* master, 64-bits per sample, 1 frame per sample */
		seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16
				| ADAU1701_SEROCTL_OLF1024;
		break;
	case SND_SOC_DAIFMT_CBS_CFS:
		break;
	default:
		return -EINVAL;
	}

	/* clock inversion */
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_NF:
		invert_lrclk = false;
		break;
	case SND_SOC_DAIFMT_NB_IF:
		invert_lrclk = true;
		break;
	case SND_SOC_DAIFMT_IB_NF:
		invert_lrclk = false;
		serictl |= ADAU1701_SERICTL_INV_BCLK;
		seroctl |= ADAU1701_SEROCTL_INV_BCLK;
		break;
	case SND_SOC_DAIFMT_IB_IF:
		invert_lrclk = true;
		serictl |= ADAU1701_SERICTL_INV_BCLK;
		seroctl |= ADAU1701_SEROCTL_INV_BCLK;
		break;
	default:
		return -EINVAL;
	}

	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		serictl |= ADAU1701_SERICTL_LEFTJ;
		seroctl |= ADAU1701_SEROCTL_MSB_DEALY0;
		invert_lrclk = !invert_lrclk;
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		serictl |= ADAU1701_SERICTL_RIGHTJ_24;
		seroctl |= ADAU1701_SEROCTL_MSB_DEALY8;
		invert_lrclk = !invert_lrclk;
		break;
	default:
		return -EINVAL;
	}

	if (invert_lrclk) {
		seroctl |= ADAU1701_SEROCTL_INV_LRCLK;
		serictl |= ADAU1701_SERICTL_INV_LRCLK;
	}

	adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;

	regmap_write(adau1701->regmap, ADAU1701_SERICTL, serictl);
	regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL,
		~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl);

	return 0;
}
Exemplo n.º 13
0
static int tps65910_rtc_probe(struct platform_device *pdev)
{
	struct tps65910 *tps65910 = NULL;
	struct tps65910_rtc *tps_rtc = NULL;
	int ret;
	int irq;
	u32 rtc_reg;

	tps65910 = dev_get_drvdata(pdev->dev.parent);

	tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc),
			GFP_KERNEL);
	if (!tps_rtc)
		return -ENOMEM;

	/* Clear pending interrupts */
	ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg);
	if (ret < 0)
		return ret;

	ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg);
	if (ret < 0)
		return ret;

	dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n");

	/* Enable RTC digital power domain */
	ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL,
		DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT);
	if (ret < 0)
		return ret;

	rtc_reg = TPS65910_RTC_CTRL_STOP_RTC;
	ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg);
	if (ret < 0)
		return ret;

	platform_set_drvdata(pdev, tps_rtc);

	irq  = platform_get_irq(pdev, 0);
	if (irq <= 0) {
		dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
			irq);
		return -ENXIO;
	}

	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME,
		dev_name(&pdev->dev), &pdev->dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "IRQ is not free.\n");
		return ret;
	}
	tps_rtc->irq = irq;
	device_set_wakeup_capable(&pdev->dev, 1);

	tps_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
		&tps65910_rtc_ops, THIS_MODULE);
	if (IS_ERR(tps_rtc->rtc)) {
		ret = PTR_ERR(tps_rtc->rtc);
		dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
		return ret;
	}

	return 0;
}
static int max98504_probe(struct max98504_priv *max98504)
{
	struct max98504_pdata *pdata = max98504->pdata;
	struct max98504_cfg_data *cfg_data = &pdata->cfg_data;

	u8 regval;
	int ret;
	unsigned int value;

	msg_maxim("\n");

	max98504_reset(max98504);

	ret = regmap_read(max98504->regmap, MAX98504_REG_7FFF_REV_ID, &value);
	if (ret < 0) {
		pr_err("Failed to read device revision: %d\n",
			ret);
		goto err_access;
	}
	msg_maxim("REV ID=0x%x\n", value);

	if (!pdata) {
		pr_err("No platform data\n");
		return ret;
	}
	/* Configure Rx Mode */
	if (pdata->rx_mode == MODE_RX_PCM) {
		regval = 0;
		if (cfg_data->rx_dither_en)
			regval |= M98504_PCM_DSP_CFG_RX_DITH_EN_MASK;
		if (cfg_data->rx_flt_mode)
			regval |= M98504_PCM_DSP_CFG_RX_FLT_MODE_MASK;

		regmap_update_bits(max98504->regmap,
			MAX98504_REG_25_PCM_DSP_CONFIG,
			M98504_PCM_DSP_CFG_RX_DITH_EN_MASK|\
			M98504_PCM_DSP_CFG_RX_FLT_MODE_MASK,
			regval);
		regmap_write(max98504->regmap,
			MAX98504_REG_20_PCM_RX_ENABLES, (u8)cfg_data->rx_ch_en);
	} else if (pdata->rx_mode == MODE_RX_PDM0 || \
			pdata->rx_mode == MODE_RX_PDM1) {
		regmap_write(max98504->regmap,
			MAX98504_REG_33_PDM_RX_ENABLE, M98504_PDM_RX_EN_MASK);
	} else {
		regmap_write(max98504->regmap,
			MAX98504_REG_20_PCM_RX_ENABLES, 0);
		regmap_write(max98504->regmap,
			MAX98504_REG_33_PDM_RX_ENABLE, 0);
	}

	regmap_write(max98504->regmap,
		MAX98504_REG_35_SPEAKER_SOURCE_SELECT,
		(u8) (M98504_SPK_SRC_SEL_MASK & pdata->rx_mode));

	/* Configure Tx Mode */
	if (pdata->tx_mode == MODE_TX_PCM) {
		regval = 0;
		if (cfg_data->tx_dither_en)
			regval |= M98504_PCM_DSP_CFG_TX_DITH_EN_MASK;
		if (cfg_data->meas_dc_block_en)
			regval |= M98504_PCM_DSP_CFG_MEAS_DCBLK_EN_MASK;
		regmap_update_bits(max98504->regmap,
			MAX98504_REG_25_PCM_DSP_CONFIG,
			M98504_PCM_DSP_CFG_TX_DITH_EN_MASK|\
			M98504_PCM_DSP_CFG_MEAS_DCBLK_EN_MASK, regval);

		regmap_write(max98504->regmap,
			MAX98504_REG_21_PCM_TX_ENABLES, (u8)cfg_data->tx_ch_en);
		regmap_write(max98504->regmap,
			MAX98504_REG_22_PCM_TX_HIZ_CONTROL,
			(u8)cfg_data->tx_hiz_ch_en);
		regmap_write(max98504->regmap,
			MAX98504_REG_23_PCM_TX_CHANNEL_SOURCES,
			(u8)cfg_data->tx_ch_src);
	} else {
		regmap_write(max98504->regmap,
			MAX98504_REG_30_PDM_TX_ENABLES, (u8)cfg_data->tx_ch_en);
		regmap_write(max98504->regmap,
			MAX98504_REG_31_PDM_TX_HIZ_CONTROL,
			(u8)cfg_data->tx_hiz_ch_en);
		regmap_write(max98504->regmap,
			MAX98504_REG_32_PDM_TX_CONTROL,
			(u8)cfg_data->tx_ch_src);
	}

	regmap_write(max98504->regmap,
		MAX98504_REG_36_MEASUREMENT_ENABLES,
		M98504_MEAS_I_EN_MASK | M98504_MEAS_V_EN_MASK);

	/* Brownout Protection */
	regmap_write(max98504->regmap,
	MAX98504_REG_16_PVDD_BROWNOUT_ENABLE, 0x1);
	regmap_write(max98504->regmap,
		MAX98504_REG_17_PVDD_BROWNOUT_CONFIG_1, 0x33);
	regmap_write(max98504->regmap,
		MAX98504_REG_18_PVDD_BROWNOUT_CONFIG_2, 0x0a);
	regmap_write(max98504->regmap,
		MAX98504_REG_19_PVDD_BROWNOUT_CONFIG_3, 0xff);
	regmap_write(max98504->regmap,
		MAX98504_REG_1A_PVDD_BROWNOUT_CONFIG_4, 0xff);

	#ifdef USE_MAX98504_IRQ
	if (gpio_is_valid(pdata->irq))	{
		regmap_write(max98504->regmap,
			MAX98504_REG_03_INTERRUPT_ENABLES, 0xff);
		regmap_write(max98504->regmap,
			MAX98504_REG_10_GPIO_ENABLE, 0x01);
	}
	#endif

	return ret;

err_access:
	return ret;
}
Exemplo n.º 15
0
/**
 * This function is used to calculate the divisors of psr, pm, fp and it is
 * supposed to be called in set_dai_sysclk() and set_bclk().
 *
 * @ratio: desired overall ratio for the paticipating dividers
 * @usefp: for HCK setting, there is no need to set fp divider
 * @fp: bypass other dividers by setting fp directly if fp != 0
 * @tx: current setting is for playback or capture
 */
static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
				bool usefp, u32 fp)
{
	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
	u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j;

	maxfp = usefp ? 16 : 1;

	if (usefp && fp)
		goto out_fp;

	if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) {
		dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n",
				2 * 8 * 256 * maxfp);
		return -EINVAL;
	} else if (ratio % 2) {
		dev_err(dai->dev, "the raio must be even if using upper divider\n");
		return -EINVAL;
	}

	ratio /= 2;

	psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;

	/* Set the max fluctuation -- 0.1% of the max devisor */
	savesub = (psr ? 1 : 8)  * 256 * maxfp / 1000;

	/* Find the best value for PM */
	for (i = 1; i <= 256; i++) {
		for (j = 1; j <= maxfp; j++) {
			/* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */
			prod = (psr ? 1 : 8) * i * j;

			if (prod == ratio)
				sub = 0;
			else if (prod / ratio == 1)
				sub = prod - ratio;
			else if (ratio / prod == 1)
				sub = ratio - prod;
			else
				continue;

			/* Calculate the fraction */
			sub = sub * 1000 / ratio;
			if (sub < savesub) {
				savesub = sub;
				pm = i;
				fp = j;
			}

			/* We are lucky */
			if (savesub == 0)
				goto out;
		}
	}

	if (pm == 999) {
		dev_err(dai->dev, "failed to calculate proper divisors\n");
		return -EINVAL;
	}

out:
	regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
			   ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK,
			   psr | ESAI_xCCR_xPM(pm));

out_fp:
	/* Bypass fp if not being required */
	if (maxfp <= 1)
		return 0;

	regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
			   ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp));

	return 0;
}
Exemplo n.º 16
0
static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
{
	int ret = 0;
	unsigned int reg_val;
	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);

	imxpriv->gpr =
		syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
	if (IS_ERR(imxpriv->gpr)) {
		dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n");
		return PTR_ERR(imxpriv->gpr);
	}

	ret = clk_prepare_enable(imxpriv->sata_ref_clk);
	if (ret < 0) {
		dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret);
		return ret;
	}

	/*
	 * set PHY Paremeters, two steps to configure the GPR13,
	 * one write for rest of parameters, mask of first write
	 * is 0x07fffffd, and the other one write for setting
	 * the mpll_clk_en.
	 */
	regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
			| IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK
			| IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK
			| IMX6Q_GPR13_SATA_SPD_MODE_MASK
			| IMX6Q_GPR13_SATA_MPLL_SS_EN
			| IMX6Q_GPR13_SATA_TX_ATTEN_MASK
			| IMX6Q_GPR13_SATA_TX_BOOST_MASK
			| IMX6Q_GPR13_SATA_TX_LVL_MASK
			| IMX6Q_GPR13_SATA_TX_EDGE_RATE
			, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
			| IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
			| IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F
			| IMX6Q_GPR13_SATA_SPD_MODE_3P0G
			| IMX6Q_GPR13_SATA_MPLL_SS_EN
			| IMX6Q_GPR13_SATA_TX_ATTEN_9_16
			| IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB
			| IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
	regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
			IMX6Q_GPR13_SATA_MPLL_CLK_EN);
	usleep_range(100, 200);

	/*
	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
	 * and IP vendor specific register HOST_TIMER1MS.
	 * Configure CAP_SSS (support stagered spin up).
	 * Implement the port0.
	 * Get the ahb clock rate, and configure the TIMER1MS register.
	 */
	reg_val = readl(mmio + HOST_CAP);
	if (!(reg_val & HOST_CAP_SSS)) {
		reg_val |= HOST_CAP_SSS;
		writel(reg_val, mmio + HOST_CAP);
	}
	reg_val = readl(mmio + HOST_PORTS_IMPL);
	if (!(reg_val & 0x1)) {
		reg_val |= 0x1;
		writel(reg_val, mmio + HOST_PORTS_IMPL);
	}

	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
	writel(reg_val, mmio + HOST_TIMER1MS);

	return 0;
}
Exemplo n.º 17
0
/**
 * This function mainly configures the clock frequency of MCLK (HCKT/HCKR)
 *
 * @Parameters:
 * clk_id: The clock source of HCKT/HCKR
 *	  (Input from outside; output from inside, FSYS or EXTAL)
 * freq: The required clock rate of HCKT/HCKR
 * dir: The clock direction of HCKT/HCKR
 *
 * Note: If the direction is input, we do not care about clk_id.
 */
static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
				   unsigned int freq, int dir)
{
	struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
	struct clk *clksrc = esai_priv->extalclk;
	bool tx = clk_id <= ESAI_HCKT_EXTAL;
	bool in = dir == SND_SOC_CLOCK_IN;
	u32 ret, ratio, ecr = 0;
	unsigned long clk_rate;

	/* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
	esai_priv->sck_div[tx] = true;

	/* Set the direction of HCKT/HCKR pins */
	regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx),
			   ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD);

	if (in)
		goto out;

	switch (clk_id) {
	case ESAI_HCKT_FSYS:
	case ESAI_HCKR_FSYS:
		clksrc = esai_priv->fsysclk;
		break;
	case ESAI_HCKT_EXTAL:
		ecr |= ESAI_ECR_ETI;
	case ESAI_HCKR_EXTAL:
		ecr |= ESAI_ECR_ERI;
		break;
	default:
		return -EINVAL;
	}

	if (IS_ERR(clksrc)) {
		dev_err(dai->dev, "no assigned %s clock\n",
				clk_id % 2 ? "extal" : "fsys");
		return PTR_ERR(clksrc);
	}
	clk_rate = clk_get_rate(clksrc);

	ratio = clk_rate / freq;
	if (ratio * freq > clk_rate)
		ret = ratio * freq - clk_rate;
	else if (ratio * freq < clk_rate)
		ret = clk_rate - ratio * freq;
	else
		ret = 0;

	/* Block if clock source can not be divided into the required rate */
	if (ret != 0 && clk_rate / ret < 1000) {
		dev_err(dai->dev, "failed to derive required HCK%c rate\n",
				tx ? 'T' : 'R');
		return -EINVAL;
	}

	/* Only EXTAL source can be output directly without using PSR and PM */
	if (ratio == 1 && clksrc == esai_priv->extalclk) {
		/* Bypass all the dividers if not being needed */
		ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
		goto out;
	} else if (ratio < 2) {
		/* The ratio should be no less than 2 if using other sources */
		dev_err(dai->dev, "failed to derive required HCK%c rate\n",
				tx ? 'T' : 'R');
		return -EINVAL;
	}

	ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
	if (ret)
		return ret;

	esai_priv->sck_div[tx] = false;

out:
	esai_priv->hck_rate[tx] = freq;

	regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
			   tx ? ESAI_ECR_ETI | ESAI_ECR_ETO :
			   ESAI_ECR_ERI | ESAI_ECR_ERO, ecr);

	return 0;
}
Exemplo n.º 18
0
static int adau1977_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
	struct snd_soc_codec *codec = dai->codec;
	struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec);
	unsigned int rate = params_rate(params);
	unsigned int slot_width;
	unsigned int ctrl0, ctrl0_mask;
	unsigned int ctrl1;
	int mcs, fs;
	int ret;

	fs = adau1977_lookup_fs(rate);
	if (fs < 0)
		return fs;

	if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) {
		mcs = adau1977_lookup_mcs(adau1977, rate, fs);
		if (mcs < 0)
			return mcs;
	} else {
		mcs = 0;
	}

	ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK;
	ctrl0 = fs;

	if (adau1977->right_j) {
		switch (params_width(params)) {
		case 16:
			ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT;
			break;
		case 24:
			ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
			break;
		default:
			return -EINVAL;
		}
		ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK;
	}

	if (adau1977->master) {
		switch (params_width(params)) {
		case 16:
			ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT;
			slot_width = 16;
			break;
		case 24:
		case 32:
			ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT;
			slot_width = 32;
			break;
		default:
			return -EINVAL;
		}

		/* In TDM mode there is a fixed slot width */
		if (adau1977->slot_width)
			slot_width = adau1977->slot_width;

		if (slot_width == 16)
			ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16;
		else
			ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32;

		ret = regmap_update_bits(adau1977->regmap,
			ADAU1977_REG_SAI_CTRL1,
			ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK |
			ADAU1977_SAI_CTRL1_BCLKRATE_MASK,
			ctrl1);
		if (ret < 0)
			return ret;
	}

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
				ctrl0_mask, ctrl0);
	if (ret < 0)
		return ret;

	return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL,
				ADAU1977_PLL_MCS_MASK, mcs);
}
Exemplo n.º 19
0
static void max97236_jack_plugged(struct max97236_priv *max97236)
{
	unsigned int status_reg[3] = {0, 0, 0};
	int retries = M97236_DEFAULT_RETRIES;
	int test_number = 1;
	int force_value = 0;
	int count;

	/* Check for spurious interrupt */
	if (!max97236_jacksw_active(max97236))
		goto max97236_jack_plugged_30;

	/* Start debounce while periodically verifying jack presence */
	for (count = 0; count < 24; count++) {
		msleep(20);
		if (!max97236_jacksw_active(max97236))
			goto max97236_jack_plugged_30;
	}

max97236_jack_plugged_10:
	if (!max97236_jacksw_active(max97236))
		goto max97236_jack_plugged_30;

	max97236_begin_detect(max97236, test_number);

	count = 10;
	do {
		msleep(20);
		regmap_read(max97236->regmap, M97236_REG_00_STATUS1,
				&status_reg[0]);
	} while (((status_reg[0] & 0x40) != 0x40) && --count);

	status_reg[0] = max97236_get_detect_result(max97236);
	max97236_translate_detected(status_reg, &force_value);
	max97236_end_detect(max97236);

	if (status_reg[0] != 0) {
		regmap_write(max97236->regmap, M97236_REG_19_STATE_FORCING,
			force_value);
		regmap_update_bits(max97236->regmap,
			M97236_REG_19_STATE_FORCING, 0x20, 0x00);
		regmap_update_bits(max97236->regmap, M97236_REG_1D_ENABLE_1,
			M97236_SHDNN_MASK, M97236_SHDNN_MASK);
	} else {
		if (--retries) {
			goto max97236_jack_plugged_10;
		}
		regmap_write(max97236->regmap, M97236_REG_19_STATE_FORCING,
			force_value);
		regmap_update_bits(max97236->regmap,
			M97236_REG_19_STATE_FORCING, 0x20, 0x00);
	}

max97236_jack_plugged_20:
	max97236_report_jack_state(max97236, status_reg);
	max97236_configure_for_detection(max97236, M97236_AUTO_MODE_0);

	if (max97236->jack_state == SND_JACK_HEADSET)
#ifdef IGNORE_KEY_INT_FUNCTION_ENABLED
		max97236_ignore_key_ints(max97236);
#else
		max97236->ignore_int = 1;
#endif

	if ((max97236->jack_state == M97236_JACK_STATE_NONE) ||
		(max97236->jack_state == M97236_JACK_STATE_UNKNOWN)) {
		regmap_write(max97236->regmap,
			M97236_REG_19_STATE_FORCING, M97236_STATE_FLOAT);
	} else {
	   	if (!max97236_jacksw_active(max97236)) {
			status_reg[0] = 0;
			status_reg[1] = 0;
			goto max97236_jack_plugged_20;
		}
	}

	return;

max97236_jack_plugged_30:
	max97236_configure_for_detection(max97236, M97236_AUTO_MODE_0);
}
Exemplo n.º 20
0
static int adau1977_power_enable(struct adau1977 *adau1977)
{
	unsigned int val;
	int ret = 0;

	if (adau1977->enabled)
		return 0;

	ret = regulator_enable(adau1977->avdd_reg);
	if (ret)
		return ret;

	if (adau1977->dvdd_reg) {
		ret = regulator_enable(adau1977->dvdd_reg);
		if (ret)
			goto err_disable_avdd;
	}

	if (adau1977->reset_gpio)
		gpiod_set_value_cansleep(adau1977->reset_gpio, 1);

	regcache_cache_only(adau1977->regmap, false);

	if (adau1977->switch_mode)
		adau1977->switch_mode(adau1977->dev);

	ret = adau1977_reset(adau1977);
	if (ret)
		goto err_disable_dvdd;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER,
		ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP);
	if (ret)
		goto err_disable_dvdd;

	ret = regcache_sync(adau1977->regmap);
	if (ret)
		goto err_disable_dvdd;

	/*
	 * The PLL register is not affected by the software reset. It is
	 * possible that the value of the register was changed to the
	 * default value while we were in cache only mode. In this case
	 * regcache_sync will skip over it and we have to manually sync
	 * it.
	 */
	ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val);
	if (ret)
		goto err_disable_dvdd;

	if (val == 0x41) {
		regcache_cache_bypass(adau1977->regmap, true);
		ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL,
			0x41);
		if (ret)
			goto err_disable_dvdd;
		regcache_cache_bypass(adau1977->regmap, false);
	}

	adau1977->enabled = true;

	return ret;

err_disable_dvdd:
	if (adau1977->dvdd_reg)
		regulator_disable(adau1977->dvdd_reg);
err_disable_avdd:
		regulator_disable(adau1977->avdd_reg);
	return ret;
}
Exemplo n.º 21
0
int sec_rtc_update(struct sec_pmic_dev *sec_pmic, u8 reg, unsigned int val,
		unsigned int mask)
{
	return regmap_update_bits(sec_pmic->rtc_regmap, reg, mask, val);
}
Exemplo n.º 22
0
static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
	unsigned int rx_mask, int slots, int width)
{
	struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
	unsigned int ctrl0, ctrl1, drv;
	unsigned int slot[4];
	unsigned int i;
	int ret;

	if (slots == 0) {
		/* 0 = No fixed slot width */
		adau1977->slot_width = 0;
		adau1977->max_master_fs = 192000;
		return regmap_update_bits(adau1977->regmap,
			ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK,
			ADAU1977_SAI_CTRL0_SAI_I2S);
	}

	if (rx_mask == 0 || tx_mask != 0)
		return -EINVAL;

	drv = 0;
	for (i = 0; i < 4; i++) {
		slot[i] = __ffs(rx_mask);
		drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i);
		rx_mask &= ~(1 << slot[i]);
		if (slot[i] >= slots)
			return -EINVAL;
		if (rx_mask == 0)
			break;
	}

	if (rx_mask != 0)
		return -EINVAL;

	switch (width) {
	case 16:
		ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16;
		break;
	case 24:
		/* We can only generate 16 bit or 32 bit wide slots */
		if (adau1977->master)
			return -EINVAL;
		ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24;
		break;
	case 32:
		ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32;
		break;
	default:
		return -EINVAL;
	}

	switch (slots) {
	case 2:
		ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2;
		break;
	case 4:
		ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4;
		break;
	case 8:
		ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8;
		break;
	case 16:
		ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16;
		break;
	default:
		return -EINVAL;
	}

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP,
		ADAU1977_SAI_OVERTEMP_DRV_C(0) |
		ADAU1977_SAI_OVERTEMP_DRV_C(1) |
		ADAU1977_SAI_OVERTEMP_DRV_C(2) |
		ADAU1977_SAI_OVERTEMP_DRV_C(3), drv);
	if (ret)
		return ret;

	ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12,
		(slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) |
		(slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET));
	if (ret)
		return ret;

	ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34,
		(slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) |
		(slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET));
	if (ret)
		return ret;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
		ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0);
	if (ret)
		return ret;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1,
		ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1);
	if (ret)
		return ret;

	adau1977->slot_width = width;

	/* In master mode the maximum bitclock is 24.576 MHz */
	adau1977->max_master_fs = min(192000, 24576000 / width / slots);

	return 0;
}
Exemplo n.º 23
0
int pcm512x_probe(struct device *dev, struct regmap *regmap)
{
	struct pcm512x_priv *pcm512x;
	int i, ret;

	pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
	if (!pcm512x)
		return -ENOMEM;

	dev_set_drvdata(dev, pcm512x);
	pcm512x->regmap = regmap;

	for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
		pcm512x->supplies[i].supply = pcm512x_supply_names[i];

	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
				      pcm512x->supplies);
	if (ret != 0) {
		dev_err(dev, "Failed to get supplies: %d\n", ret);
		return ret;
	}

	pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
	pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
	pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;

	for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
		ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
						  &pcm512x->supply_nb[i]);
		if (ret != 0) {
			dev_err(dev,
				"Failed to register regulator notifier: %d\n",
				ret);
		}
	}

	ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
				    pcm512x->supplies);
	if (ret != 0) {
		dev_err(dev, "Failed to enable supplies: %d\n", ret);
		return ret;
	}

	/* Reset the device, verifying I/O in the process for I2C */
	ret = regmap_write(regmap, PCM512x_RESET,
			   PCM512x_RSTM | PCM512x_RSTR);
	if (ret != 0) {
		dev_err(dev, "Failed to reset device: %d\n", ret);
		goto err;
	}

	ret = regmap_write(regmap, PCM512x_RESET, 0);
	if (ret != 0) {
		dev_err(dev, "Failed to reset device: %d\n", ret);
		goto err;
	}

	pcm512x->sclk = devm_clk_get(dev, NULL);
	if (IS_ERR(pcm512x->sclk)) {
		if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		dev_info(dev, "No SCLK, using BCLK: %ld\n",
			 PTR_ERR(pcm512x->sclk));

		/* Disable reporting of missing SCLK as an error */
		regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
				   PCM512x_IDCH, PCM512x_IDCH);

		/* Switch PLL input to BCLK */
		regmap_update_bits(regmap, PCM512x_PLL_REF,
				   PCM512x_SREF, PCM512x_SREF);
	} else {
		ret = clk_prepare_enable(pcm512x->sclk);
		if (ret != 0) {
			dev_err(dev, "Failed to enable SCLK: %d\n", ret);
			return ret;
		}
	}

	/* Default to standby mode */
	ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
				 PCM512x_RQST, PCM512x_RQST);
	if (ret != 0) {
		dev_err(dev, "Failed to request standby: %d\n",
			ret);
		goto err_clk;
	}

	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);
	pm_runtime_idle(dev);

	ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
				    &pcm512x_dai, 1);
	if (ret != 0) {
		dev_err(dev, "Failed to register CODEC: %d\n", ret);
		goto err_pm;
	}

	return 0;

err_pm:
	pm_runtime_disable(dev);
err_clk:
	if (!IS_ERR(pcm512x->sclk))
		clk_disable_unprepare(pcm512x->sclk);
err:
	regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
				     pcm512x->supplies);
	return ret;
}
Exemplo n.º 24
0
static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec);
	unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0;
	bool invert_lrclk;
	int ret;

	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		adau1977->master = false;
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
		ctrl1 |= ADAU1977_SAI_CTRL1_MASTER;
		adau1977->master = true;
		break;
	default:
		return -EINVAL;
	}

	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_NF:
		invert_lrclk = false;
		break;
	case SND_SOC_DAIFMT_IB_NF:
		block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
		invert_lrclk = false;
		break;
	case SND_SOC_DAIFMT_NB_IF:
		invert_lrclk = true;
		break;
	case SND_SOC_DAIFMT_IB_IF:
		block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
		invert_lrclk = true;
		break;
	default:
		return -EINVAL;
	}

	adau1977->right_j = false;
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
		invert_lrclk = !invert_lrclk;
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
		adau1977->right_j = true;
		invert_lrclk = !invert_lrclk;
		break;
	case SND_SOC_DAIFMT_DSP_A:
		ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
		ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
		invert_lrclk = false;
		break;
	case SND_SOC_DAIFMT_DSP_B:
		ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
		ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
		invert_lrclk = false;
		break;
	default:
		return -EINVAL;
	}

	if (invert_lrclk)
		block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
		ADAU1977_BLOCK_POWER_SAI_LR_POL |
		ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power);
	if (ret)
		return ret;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0,
		ADAU1977_SAI_CTRL0_FMT_MASK,
		ctrl0);
	if (ret)
		return ret;

	return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1,
		ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE,
		ctrl1);
}
Exemplo n.º 25
0
static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params,
				 struct snd_soc_dai *dai)
{
	struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
	unsigned int sampling_rate = params_rate(params);
	unsigned int data_length, data_delay, bclk_ratio;
	unsigned int ch1pos, ch2pos, mode, format;
	uint32_t csreg;

	/*
	 * If a stream is already enabled,
	 * the registers are already set properly.
	 */
	regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);

	if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON))
		return 0;

	/*
	 * Adjust the data length according to the format.
	 * We prefill the half frame length with an integer
	 * divider of 2400 as explained at the clock settings.
	 * Maybe it is overwritten there, if the Integer mode
	 * does not apply.
	 */
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		data_length = 16;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		data_length = 24;
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		data_length = 32;
		break;
	default:
		return -EINVAL;
	}

	/* If bclk_ratio already set, use that one. */
	if (dev->bclk_ratio)
		bclk_ratio = dev->bclk_ratio;
	else
		/* otherwise calculate a fitting block ratio */
		bclk_ratio = 2 * data_length;

	/* Clock should only be set up here if CPU is clock master */
	switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
	case SND_SOC_DAIFMT_CBS_CFM:
		clk_set_rate(dev->clk, sampling_rate * bclk_ratio);
		break;
	default:
		break;
	}

	/* Setup the frame format */
	format = BCM2835_I2S_CHEN;

	if (data_length >= 24)
		format |= BCM2835_I2S_CHWEX;

	format |= BCM2835_I2S_CHWID((data_length-8)&0xf);

	switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		data_delay = 1;
		break;
	default:
		/*
		 * TODO
		 * Others are possible but are not implemented at the moment.
		 */
		dev_err(dev->dev, "%s:bad format\n", __func__);
		return -EINVAL;
	}

	ch1pos = data_delay;
	ch2pos = bclk_ratio / 2 + data_delay;

	switch (params_channels(params)) {
	case 2:
		format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format);
		format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos));
		format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos));
		break;
	default:
		return -EINVAL;
	}

	/*
	 * Set format for both streams.
	 * We cannot set another frame length
	 * (and therefore word length) anyway,
	 * so the format will be the same.
	 */
	regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
	regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);

	/* Setup the I2S mode */
	mode = 0;

	if (data_length <= 16) {
		/*
		 * Use frame packed mode (2 channels per 32 bit word)
		 * We cannot set another frame length in the second stream
		 * (and therefore word length) anyway,
		 * so the format will be the same.
		 */
		mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
	}

	mode |= BCM2835_I2S_FLEN(bclk_ratio - 1);
	mode |= BCM2835_I2S_FSLEN(bclk_ratio / 2);

	/* Master or slave? */
	switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		/* CPU is master */
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		/*
		 * CODEC is bit clock master
		 * CPU is frame master
		 */
		mode |= BCM2835_I2S_CLKM;
		break;
	case SND_SOC_DAIFMT_CBS_CFM:
		/*
		 * CODEC is frame master
		 * CPU is bit clock master
		 */
		mode |= BCM2835_I2S_FSM;
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
		/* CODEC is master */
		mode |= BCM2835_I2S_CLKM;
		mode |= BCM2835_I2S_FSM;
		break;
	default:
		dev_err(dev->dev, "%s:bad master\n", __func__);
		return -EINVAL;
	}

	/*
	 * Invert clocks?
	 *
	 * The BCM approach seems to be inverted to the classical I2S approach.
	 */
	switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_NF:
		/* None. Therefore, both for BCM */
		mode |= BCM2835_I2S_CLKI;
		mode |= BCM2835_I2S_FSI;
		break;
	case SND_SOC_DAIFMT_IB_IF:
		/* Both. Therefore, none for BCM */
		break;
	case SND_SOC_DAIFMT_NB_IF:
		/*
		 * Invert only frame sync. Therefore,
		 * invert only bit clock for BCM
		 */
		mode |= BCM2835_I2S_CLKI;
		break;
	case SND_SOC_DAIFMT_IB_NF:
		/*
		 * Invert only bit clock. Therefore,
		 * invert only frame sync for BCM
		 */
		mode |= BCM2835_I2S_FSI;
		break;
	default:
		return -EINVAL;
	}

	regmap_write(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, mode);

	/* Setup the DMA parameters */
	regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
			BCM2835_I2S_RXTHR(1)
			| BCM2835_I2S_TXTHR(1)
			| BCM2835_I2S_DMAEN, 0xffffffff);

	regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG,
			  BCM2835_I2S_TX_PANIC(0x10)
			| BCM2835_I2S_RX_PANIC(0x30)
			| BCM2835_I2S_TX(0x30)
			| BCM2835_I2S_RX(0x20), 0xffffffff);

	/* Clear FIFOs */
	bcm2835_i2s_clear_fifos(dev, true, true);

	return 0;
}
Exemplo n.º 26
0
int adau1977_probe(struct device *dev, struct regmap *regmap,
	enum adau1977_type type, void (*switch_mode)(struct device *dev))
{
	unsigned int power_off_mask;
	struct adau1977 *adau1977;
	int ret;

	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL);
	if (adau1977 == NULL)
		return -ENOMEM;

	adau1977->dev = dev;
	adau1977->type = type;
	adau1977->regmap = regmap;
	adau1977->switch_mode = switch_mode;
	adau1977->max_master_fs = 192000;

	adau1977->constraints.list = adau1977_rates;
	adau1977->constraints.count = ARRAY_SIZE(adau1977_rates);

	adau1977->avdd_reg = devm_regulator_get(dev, "AVDD");
	if (IS_ERR(adau1977->avdd_reg))
		return PTR_ERR(adau1977->avdd_reg);

	adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD");
	if (IS_ERR(adau1977->dvdd_reg)) {
		if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV)
			return PTR_ERR(adau1977->dvdd_reg);
		adau1977->dvdd_reg = NULL;
	}

	adau1977->reset_gpio = devm_gpiod_get(dev, "reset");
	if (IS_ERR(adau1977->reset_gpio)) {
		ret = PTR_ERR(adau1977->reset_gpio);
		if (ret != -ENOENT && ret != -ENOSYS)
			return PTR_ERR(adau1977->reset_gpio);
		adau1977->reset_gpio = NULL;
	}

	dev_set_drvdata(dev, adau1977);

	if (adau1977->reset_gpio) {
		ret = gpiod_direction_output(adau1977->reset_gpio, 0);
		if (ret)
			return ret;
		ndelay(100);
	}

	ret = adau1977_power_enable(adau1977);
	if (ret)
		return ret;

	if (type == ADAU1977) {
		ret = adau1977_setup_micbias(adau1977);
		if (ret)
			goto err_poweroff;
	}

	if (adau1977->dvdd_reg)
		power_off_mask = ~0;
	else
		power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
				power_off_mask, 0x00);
	if (ret)
		goto err_poweroff;

	ret = adau1977_power_disable(adau1977);
	if (ret)
		return ret;

	return snd_soc_register_codec(dev, &adau1977_codec_driver,
			&adau1977_dai, 1);

err_poweroff:
	adau1977_power_disable(adau1977);
	return ret;

}
Exemplo n.º 27
0
static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
                              unsigned int fmt)
{
    struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec);
    unsigned int adc_serfmt = 0;
    unsigned int adc_fmt = 0;
    unsigned int dac_fmt = 0;

    /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
     * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
     */
    switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    case SND_SOC_DAIFMT_I2S:
        adc_serfmt |= AD193X_ADC_SERFMT_TDM;
        break;
    case SND_SOC_DAIFMT_DSP_A:
        adc_serfmt |= AD193X_ADC_SERFMT_AUX;
        break;
    default:
        return -EINVAL;
    }

    switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
        break;
    case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
        adc_fmt |= AD193X_ADC_LEFT_HIGH;
        dac_fmt |= AD193X_DAC_LEFT_HIGH;
        break;
    case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
        adc_fmt |= AD193X_ADC_BCLK_INV;
        dac_fmt |= AD193X_DAC_BCLK_INV;
        break;
    case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
        adc_fmt |= AD193X_ADC_LEFT_HIGH;
        adc_fmt |= AD193X_ADC_BCLK_INV;
        dac_fmt |= AD193X_DAC_LEFT_HIGH;
        dac_fmt |= AD193X_DAC_BCLK_INV;
        break;
    default:
        return -EINVAL;
    }

    switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
        adc_fmt |= AD193X_ADC_LCR_MASTER;
        adc_fmt |= AD193X_ADC_BCLK_MASTER;
        dac_fmt |= AD193X_DAC_LCR_MASTER;
        dac_fmt |= AD193X_DAC_BCLK_MASTER;
        break;
    case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
        adc_fmt |= AD193X_ADC_LCR_MASTER;
        dac_fmt |= AD193X_DAC_LCR_MASTER;
        break;
    case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
        adc_fmt |= AD193X_ADC_BCLK_MASTER;
        dac_fmt |= AD193X_DAC_BCLK_MASTER;
        break;
    case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
        break;
    default:
        return -EINVAL;
    }

    regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
                       AD193X_ADC_SERFMT_MASK, adc_serfmt);
    regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
                       AD193X_ADC_FMT_MASK, adc_fmt);
    regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
                       AD193X_DAC_FMT_MASK, dac_fmt);

    return 0;
}
Exemplo n.º 28
0
static inline void tegra20_ac97_stop_capture(struct tegra20_ac97 *ac97)
{
	regmap_update_bits(ac97->regmap, TEGRA20_AC97_FIFO1_SCR,
			   TEGRA20_AC97_FIFO_SCR_REC_FULL_EN, 0);
}
Exemplo n.º 29
0
int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
{
	return regmap_update_bits(twl6040->regmap, reg, mask, 0);
}
Exemplo n.º 30
0
static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	struct sun8i_codec *scodec = snd_soc_codec_get_drvdata(dai->codec);
	u32 value;

	/* clock masters */
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS: /* DAI Slave */
		value = 0x0; /* Codec Master */
		break;
	case SND_SOC_DAIFMT_CBM_CFM: /* DAI Master */
		value = 0x1; /* Codec Slave */
		break;
	default:
		return -EINVAL;
	}
	regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
			   BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD),
			   value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD);

	/* clock inversion */
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_NB_NF: /* Normal */
		value = 0x0;
		break;
	case SND_SOC_DAIFMT_IB_IF: /* Inversion */
		value = 0x1;
		break;
	default:
		return -EINVAL;
	}
	regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
			   BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV),
			   value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV);
	regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
			   BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV),
			   value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV);

	/* DAI format */
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		value = 0x0;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		value = 0x1;
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		value = 0x2;
		break;
	case SND_SOC_DAIFMT_DSP_A:
	case SND_SOC_DAIFMT_DSP_B:
		value = 0x3;
		break;
	default:
		return -EINVAL;
	}
	regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
			   BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT),
			   value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);

	return 0;
}