summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/ab8500_audio.c63
-rw-r--r--sound/soc/codecs/ab8500_audio.h4
-rw-r--r--sound/soc/ux500/ux500_ab8500.c34
3 files changed, 95 insertions, 6 deletions
diff --git a/sound/soc/codecs/ab8500_audio.c b/sound/soc/codecs/ab8500_audio.c
index 7a87890507c..f65ebe5b786 100644
--- a/sound/soc/codecs/ab8500_audio.c
+++ b/sound/soc/codecs/ab8500_audio.c
@@ -46,13 +46,10 @@
#define GPIO27_DIR_OUTPUT 0x04
#define GPIO29_DIR_OUTPUT 0x10
#define GPIO31_DIR_OUTPUT 0x40
-#define GPIO35_DIR_OUTPUT 0x04
/* Macrocell register definitions */
#define AB8500_CTRL3_REG 0x0200
#define AB8500_GPIO_DIR4_REG 0x1013
-#define AB8500_GPIO_DIR5_REG 0x1014
-#define AB8500_GPIO_OUT5_REG 0x1024
/*
* AB8500 register cache & default register settings
@@ -1856,7 +1853,65 @@ void ab8500_audio_power_control(bool power_on)
}
}
-/* Extended interface for codec-driver */
+void ab8500_audio_pwm_vibra(unsigned char speed_left_pos,
+ unsigned char speed_left_neg,
+ unsigned char speed_right_pos,
+ unsigned char speed_right_neg)
+{
+ unsigned int clear_mask, set_mask;
+ bool vibra_on;
+
+ if (ab8500_codec == NULL) {
+ pr_err("%s: ERROR: AB8500 ASoC-driver not yet probed!\n", __func__);
+ return;
+ }
+
+ vibra_on = speed_left_pos | speed_left_neg | speed_right_pos | speed_right_neg;
+ if (!vibra_on) {
+ clear_mask = BMASK(REG_ANACONF4_ENVIB1) | BMASK(REG_ANACONF4_ENVIB2);
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_ANACONF4, clear_mask, 0x00);
+ speed_left_pos = 0;
+ speed_left_neg = 0;
+ speed_right_pos = 0;
+ speed_right_neg = 0;
+ }
+
+ pr_debug("%s: PWM-vibra (%d, %d, %d, %d).\n",
+ __func__,
+ speed_left_pos,
+ speed_left_neg,
+ speed_right_pos,
+ speed_right_neg);
+
+ set_mask = BMASK(REG_PWMGENCONF1_PWMTOVIB1) |
+ BMASK(REG_PWMGENCONF1_PWMTOVIB2) |
+ BMASK(REG_PWMGENCONF1_PWM1CTRL) |
+ BMASK(REG_PWMGENCONF1_PWM2CTRL) |
+ BMASK(REG_PWMGENCONF1_PWM1NCTRL) |
+ BMASK(REG_PWMGENCONF1_PWM1PCTRL) |
+ BMASK(REG_PWMGENCONF1_PWM2NCTRL) |
+ BMASK(REG_PWMGENCONF1_PWM2PCTRL);
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF1, 0x00, set_mask);
+
+ if (speed_left_pos > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX)
+ speed_left_pos = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX;
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF3, REG_MASK_ALL, speed_left_pos);
+
+ if (speed_left_neg > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX)
+ speed_left_neg = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX;
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF2, REG_MASK_ALL, speed_left_neg);
+
+ if (speed_right_pos > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX)
+ speed_right_pos = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX;
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF5, REG_MASK_ALL, speed_right_pos);
+
+ if (speed_right_neg > REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX)
+ speed_right_neg = REG_PWMGENCONFX_PWMVIBXDUTCYC_MAX;
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_PWMGENCONF4, REG_MASK_ALL, speed_right_neg);
+
+ set_mask = BMASK(REG_ANACONF4_ENVIB1) | BMASK(REG_ANACONF4_ENVIB2);
+ ab8500_codec_update_reg_audio(ab8500_codec, REG_ANACONF4, 0x00, set_mask);
+}
int ab8500_audio_set_word_length(struct snd_soc_dai *dai, unsigned int wl)
{
diff --git a/sound/soc/codecs/ab8500_audio.h b/sound/soc/codecs/ab8500_audio.h
index 7cfdd1cc13a..c3b24bbc754 100644
--- a/sound/soc/codecs/ab8500_audio.h
+++ b/sound/soc/codecs/ab8500_audio.h
@@ -25,6 +25,10 @@ extern struct snd_soc_codec_driver soc_codec_dev_ab8500;
/* Extended interface for codec-driver */
void ab8500_audio_power_control(bool power_on);
+void ab8500_audio_pwm_vibra(unsigned char speed_left_pos,
+ unsigned char speed_left_neg,
+ unsigned char speed_right_pos,
+ unsigned char speed_right_neg);
int ab8500_audio_set_word_length(struct snd_soc_dai *dai, unsigned int wl);
int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai, unsigned int delay);
int ab8500_audio_setup_if1(struct snd_soc_codec *codec,
diff --git a/sound/soc/ux500/ux500_ab8500.c b/sound/soc/ux500/ux500_ab8500.c
index be647daeeed..805c26448d3 100644
--- a/sound/soc/ux500/ux500_ab8500.c
+++ b/sound/soc/ux500/ux500_ab8500.c
@@ -24,7 +24,6 @@
#include <sound/pcm.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
-#include <sound/soc-dapm.h>
#include <mach/hardware.h>
#include "ux500_pcm.h"
#include "ux500_msp_dai.h"
@@ -44,6 +43,7 @@
#define DRIVERMODE_CODEC_ONLY 1
static struct snd_soc_jack jack;
+static bool vibra_on;
/* Power-control */
static DEFINE_MUTEX(power_lock);
@@ -58,7 +58,7 @@ static struct clk *clk_ptr_sysclk;
static struct clk *clk_ptr_ulpclk;
/* Regulators */
-static enum regulator_idx {
+enum regulator_idx {
REGULATOR_AUDIO,
REGULATOR_DMIC,
REGULATOR_AMIC1,
@@ -531,6 +531,8 @@ int ux500_ab8500_soc_machine_drv_init(void)
return status;
}
+ vibra_on = false;
+
return 0;
}
@@ -552,6 +554,34 @@ void ux500_ab8500_soc_machine_drv_cleanup(void)
/* Extended interface */
+void ux500_ab8500_audio_pwm_vibra(unsigned char speed_left_pos,
+ unsigned char speed_left_neg,
+ unsigned char speed_right_pos,
+ unsigned char speed_right_neg)
+{
+ bool vibra_on_new;
+
+ vibra_on_new = speed_left_pos | speed_left_neg | speed_right_pos | speed_right_neg;
+ if ((!vibra_on_new) && (vibra_on)) {
+ pr_debug("%s: PWM-vibra off.\n", __func__);
+ vibra_on = false;
+
+ ux500_ab8500_power_control_dec();
+ }
+
+ if ((vibra_on_new) && (!vibra_on)) {
+ pr_debug("%s: PWM-vibra on.\n", __func__);
+ vibra_on = true;
+
+ ux500_ab8500_power_control_inc();
+ }
+
+ ab8500_audio_pwm_vibra(speed_left_pos,
+ speed_left_neg,
+ speed_right_pos,
+ speed_right_neg);
+}
+
void ux500_ab8500_jack_report(int value)
{
if (jack.jack)