static int wm8994_device_suspend(struct device *dev)
{
	struct wm8994 *wm8994 = dev_get_drvdata(dev);
	int ret;

	/* GPIO configuration state is saved here since we may be configuring
	 * the GPIO alternate functions even if we're not using the gpiolib
	 * driver for them.
	 */
	ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
			  &wm8994->gpio_regs);
	if (ret < 0)
		dev_err(dev, "Failed to save GPIO registers: %d\n", ret);

	/* For similar reasons we also stash the regulator states */
	ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
			  &wm8994->ldo_regs);
	if (ret < 0)
		dev_err(dev, "Failed to save LDO registers: %d\n", ret);

	ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
				     wm8994->supplies);
	if (ret != 0) {
		dev_err(dev, "Failed to disable supplies: %d\n", ret);
		return ret;
	}

	return 0;
}
Ejemplo n.º 2
0
static void set_headphones(void)
{
	unsigned int val;

	/* get current headphones level value and force setting it, soundlevel mod will be handled on wm8994.c */
	val = wm8994_read(soundlevel_codec, WM8994_LEFT_OUTPUT_VOLUME);
        wm8994_write(soundlevel_codec, WM8994_LEFT_OUTPUT_VOLUME, val);

	val = wm8994_read(soundlevel_codec, WM8994_RIGHT_OUTPUT_VOLUME);
        wm8994_write(soundlevel_codec, WM8994_RIGHT_OUTPUT_VOLUME, val | WM8994_HPOUT1_VU); /* Set the update flag to actually apply the new setting */

}
Ejemplo n.º 3
0
static void set_speaker(void)
{
	unsigned int val;

	/* get current headphones level value and force setting it, soundlevel mod will be handled on wm8994.c */
	val = wm8994_read(soundlevel_codec, WM8994_SPEAKER_VOLUME_LEFT);
        wm8994_write(soundlevel_codec, WM8994_SPEAKER_VOLUME_LEFT, val);

	val = wm8994_read(soundlevel_codec, WM8994_SPEAKER_VOLUME_RIGHT);
        wm8994_write(soundlevel_codec, WM8994_SPEAKER_VOLUME_RIGHT, val | WM8994_SPKOUT_VU); /* Set the update flag to actually apply the new setting */

}
Ejemplo n.º 4
0
void update_fm_radio_headset_restore_freqs(bool with_mute)
{
	unsigned short val;
	DECLARE_WM8994(codec);

	bypass_write_extension = true;
	// apply only when FM radio is active
	if (wm8994->fmradio_path == FMR_OFF)
		return;

	if (with_mute) {
		wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1,
			     WM8994_AIF2DAC_MUTE |
			     WM8994_AIF2DAC_MUTERATE |
			     WM8994_AIF2DAC_UNMUTE_RAMP |
			     WM8994_AIF2DAC_DEEMP_MASK);
		msleep(180);
	}

	if (fm_radio_headset_restore_bass) {
		// disable Sidetone high-pass filter
		// was designed for voice and not FM radio
		wm8994_write(codec, WM8994_SIDETONE, 0x0000);
		// disable 4FS ultrasonic mode and
		// restore the hi-fi <4Hz hi pass filter
		wm8994_write(codec, WM8994_AIF2_ADC_FILTERS,
			     WM8994_AIF2ADCL_HPF |
			     WM8994_AIF2ADCR_HPF);
	} else {
		// default settings in GT-I9000 Froyo XXJPX kernel sources
		wm8994_write(codec, WM8994_SIDETONE, 0x01c0);
		wm8994_write(codec, WM8994_AIF2_ADC_FILTERS, 0xF800);
	}

	if (fm_radio_headset_restore_highs) {
		val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1);
		val &= ~(WM8994_AIF2DAC_DEEMP_MASK);
		wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val);
	} else {
		wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0036);
	}

	// un-mute
	if (with_mute) {
		val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1);
		val &= ~(WM8994_AIF2DAC_MUTE_MASK);
		wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val);
	}
	bypass_write_extension = false;
}
Ejemplo n.º 5
0
void update_fm_radio_headset_restore_freqs(bool with_mute)
{
	unsigned short val;

	// apply only when FM radio is active
	DECLARE_WM8994(codec_)
	if (wm8994->fmradio_path == FMR_OFF)
		return;

	if (with_mute)
	{
		wm8994_write(codec_, WM8994_AIF2_DAC_FILTERS_1, 0x236);
		msleep(180);
	}

	if (fm_radio_headset_restore_bass)
	{
		// disable Sidetone high-pass filter designed for voice and not FM radio
		// Sidetone(621H): 0000  ST_HPF_CUT=000, ST_HPF=0, ST2_SEL=0, ST1_SEL=0
		wm8994_write(codec_, WM8994_SIDETONE, 0x0000);
		// disable 4FS ultrasonic mode and restore the hi-fi <4Hz hi pass filter
		// AIF2 ADC Filters(510H): 1800 AIF2ADC_4FS=0, AIF2ADC_HPF_CUT=00, AIF2ADCL_HPF=1, AIF2ADCR_HPF=1
		wm8994_write(codec_, WM8994_AIF2_ADC_FILTERS, 0x1800);
	}
	else
	{
		// default settings in GT-I9000 Froyo XXJPX kernel sources
		wm8994_write(codec_, WM8994_SIDETONE, 0x01c0);
		wm8994_write(codec_, WM8994_AIF2_ADC_FILTERS, 0xF800);
	}

	if (fm_radio_headset_restore_highs)
	{
		val = wm8994_read(codec_, WM8994_AIF2_DAC_FILTERS_1);
		val &= ~(WM8994_AIF2DAC_DEEMP_MASK);
		wm8994_write(codec_, WM8994_AIF2_DAC_FILTERS_1, val);
	}
	else
		wm8994_write(codec_, WM8994_AIF2_DAC_FILTERS_1, 0x0036);

	// un-mute
	if (with_mute)
	{
		val = wm8994_read(codec_, WM8994_AIF2_DAC_FILTERS_1);
		val &= ~(WM8994_AIF2DAC_MUTE_MASK);
		wm8994_write(codec_, WM8994_AIF2_DAC_FILTERS_1, val);
	}
}
Ejemplo n.º 6
0
/**
 * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
 *
 * @wm8994: Device to write to.
 * @reg: Register to write to.
 * @mask: Mask of bits to set.
 * @val: Value to set (unshifted)
 */
int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
		    unsigned short mask, unsigned short val)
{
	int ret;
	u16 r;

	mutex_lock(&wm8994->io_lock);

	ret = wm8994_read(wm8994, reg, 2, &r);
	if (ret < 0)
		goto out;

	r = be16_to_cpu(r);

	r &= ~mask;
	r |= val;

	r = cpu_to_be16(r);

	ret = wm8994_write(wm8994, reg, 2, &r);

out:
	mutex_unlock(&wm8994->io_lock);

	return ret;
}
Ejemplo n.º 7
0
void update_osr128(bool with_mute)
{
	unsigned short val;
	val = osr128_get_value(wm8994_read(codec, WM8994_OVERSAMPLING));
	bypass_write_hook = true;
	wm8994_write(codec, WM8994_OVERSAMPLING, val);
	bypass_write_hook = false;
}
Ejemplo n.º 8
0
static int wm8994_suspend(struct device *dev)
{
	struct wm8994 *wm8994 = dev_get_drvdata(dev);
	int ret;

	/* Don't actually go through with the suspend if the CODEC is
	 * still active (eg, for audio passthrough from CP. */
	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
	if (ret < 0) {
		dev_err(dev, "Failed to read power status: %d\n", ret);
	} else if (ret & WM8994_VMID_SEL_MASK) {
		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
		return 0;
	}

	/* GPIO configuration state is saved here since we may be configuring
	 * the GPIO alternate functions even if we're not using the gpiolib
	 * driver for them.
	 */
	ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
			  &wm8994->gpio_regs);
	if (ret < 0)
		dev_err(dev, "Failed to save GPIO registers: %d\n", ret);

	/* For similar reasons we also stash the regulator states */
	ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
			  &wm8994->ldo_regs);
	if (ret < 0)
		dev_err(dev, "Failed to save LDO registers: %d\n", ret);

	/* Explicitly put the device into reset in case regulators
	 * don't get disabled in order to ensure consistent restart.
	 */
	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);

	wm8994->suspended = true;

	ret = regulator_bulk_disable(wm8994->num_supplies,
				     wm8994->supplies);
	if (ret != 0) {
		dev_err(dev, "Failed to disable supplies: %d\n", ret);
		return ret;
	}

	return 0;
}
Ejemplo n.º 9
0
/**
 * wm8994_bulk_read: Read multiple WM8994 registers
 *
 * @wm8994: Device to read from
 * @reg: First register
 * @count: Number of registers
 * @buf: Buffer to fill.  The data will be returned big endian.
 */
int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
		     int count, u16 *buf)
{
	int ret;

	mutex_lock(&wm8994->io_lock);

	ret = wm8994_read(wm8994, reg, count * 2, buf);

	mutex_unlock(&wm8994->io_lock);

	return ret;
}
Ejemplo n.º 10
0
/**
 * wm8994_reg_read: Read a single WM8994 register.
 *
 * @wm8994: Device to read from.
 * @reg: Register to read.
 */
int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
{
	unsigned short val;
	int ret;

	mutex_lock(&wm8994->io_lock);

	ret = wm8994_read(wm8994, reg, 2, &val);

	mutex_unlock(&wm8994->io_lock);

	if (ret < 0)
		return ret;
	else
		return be16_to_cpu(val);
}
/**
 * wm8994_reg_read: Read a single WM8994 register.
 *
 * @wm8994: Device to read from.
 * @reg: Register to read.
 */
int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
{
	unsigned short val;
	int ret;

	mutex_lock(&wm8994->io_lock);

	ret = wm8994_read(wm8994, reg, 2, &val);

	mutex_unlock(&wm8994->io_lock);

#if 1
	dev_vdbg(wm8994->dev, "wm8994_reg_read ADRESS is %x, VALUE is %x\n", reg, val);
#else
	printk("wm8994_reg_read ADRESS is %x, VALUE is %x\n", reg, val);
#endif
	if (ret < 0)
		return ret;
	else
		return val;
}
Ejemplo n.º 12
0
void update_hpvol(bool with_fade)
{
	unsigned short val;
	unsigned short i;
	short steps;
	int hp_level_old[2];
	unsigned short hp_level_registers[2] = { WM8994_LEFT_OUTPUT_VOLUME,
						 WM8994_RIGHT_OUTPUT_VOLUME };

	DECLARE_WM8994(codec);

	// don't affect headphone amplifier volume
	// when not on heapdhones or if call is active
	if (!is_path(HEADPHONES)
	    || (wm8994->codec_state & CALL_ACTIVE))
		return;


	if (!with_fade) {
		bypass_write_extension = true;
		write_hpvol(hpvol(0), hpvol(1));
		bypass_write_extension = false;
		return;
	}

	// read previous levels
	for (i = 0; i < 2; i++) {
		val = wm8994_read(codec, hp_level_registers[i]);
		val &= ~(WM8994_HPOUT1_VU_MASK);
		val &= ~(WM8994_HPOUT1L_ZC_MASK);
		val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
		hp_level_old[i] = val + (digital_gain / 1000);

		if (hp_level_old[i] < 0)
			hp_level_old[i] = 0;

		if (debug_log(LOG_INFOS))
			printk("wm8994_extensions: previous hp_level[%hu]: %d\n",
			       i, hp_level_old[i]);
	}

	// calculate number of steps for volume fade
	steps = hp_level[0] - hp_level_old[0];
	if (debug_log(LOG_INFOS))
		printk("wm8994_extensions: volume change steps: %hd "
		       "start: %hu, end: %hu\n",
		       steps,
		       hp_level_old[0],
		       hp_level[0]);

	while (steps != 0) {
		if (hp_level[0] < hp_level_old[0])
			steps++;
		else
			steps--;

		if (debug_log(LOG_INFOS))
			printk("wm8994_extensions: volume: %hu\n",
			       (hpvol(0) - steps));

		bypass_write_extension = true;
		write_hpvol(hpvol(0) - steps, hpvol(1) - steps);
		bypass_write_extension = false;

		if (steps != 0)
			udelay(1000);
	}

}
static int wm8994_device_suspend(struct device *dev)
{
	struct wm8994 *wm8994 = dev_get_drvdata(dev);
	int ret;

	/* Don't actually go through with the suspend if the CODEC is
	 * still active (eg, for audio passthrough from CP. */
	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
	if (ret < 0) {
		dev_err(dev, "Failed to read power status: %d\n", ret);
	} else if (ret & WM8994_VMID_SEL_MASK) {
		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
		return 0;
	}

	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
	if (ret < 0) {
		dev_err(dev, "Failed to read power status: %d\n", ret);
	} else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
			  WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
			  WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
		return 0;
	}

	ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
	if (ret < 0) {
		dev_err(dev, "Failed to read power status: %d\n", ret);
	} else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
			  WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
			  WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
		dev_dbg(dev, "CODEC still active, ignoring suspend\n");
		return 0;
	}

	switch (wm8994->type) {
	case WM8958:
	case WM1811:
		ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1);
		if (ret < 0) {
			dev_err(dev, "Failed to read power status: %d\n", ret);
		} else if (ret & WM8958_MICD_ENA) {
			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
			return 0;
		}
		break;
	default:
		break;
	}

	switch (wm8994->type) {
	case WM1811:
		ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
		if (ret < 0) {
			dev_err(dev, "Failed to read jackdet: %d\n", ret);
		} else if (ret & WM1811_JACKDET_MODE_MASK) {
			dev_dbg(dev, "CODEC still active, ignoring suspend\n");
			return 0;
		}
		break;
	default:
		break;
	}

	/* Disable LDO pulldowns while the device is suspended if we
	 * don't know that something will be driving them. */
	if (!wm8994->ldo_ena_always_driven)
		wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);

	/* GPIO configuration state is saved here since we may be configuring
	 * the GPIO alternate functions even if we're not using the gpiolib
	 * driver for them.
	 */
	ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
			  &wm8994->gpio_regs);
	if (ret < 0)
		dev_err(dev, "Failed to save GPIO registers: %d\n", ret);

	/* For similar reasons we also stash the regulator states */
	ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
			  &wm8994->ldo_regs);
	if (ret < 0)
		dev_err(dev, "Failed to save LDO registers: %d\n", ret);

	/* Explicitly put the device into reset in case regulators
	 * don't get disabled in order to ensure consistent restart.
	 */
	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);

	wm8994->suspended = true;

	ret = regulator_bulk_disable(wm8994->num_supplies,
				     wm8994->supplies);
	if (ret != 0) {
		dev_err(dev, "Failed to disable supplies: %d\n", ret);
		return ret;
	}

	set_mclk(0);

	return 0;
}