Sound Control: (Optional) work around for WCD93xx audio issues

(Use this only for devices with audio reset issues)

Also bump version to 3.1

Signed-off-by: Paul Reioux <reioux@gmail.com>

wcd9xxx-core: add register write without mutex protection

This is assuming the calling function will take care of the mutex.

Signed-off-by: Paul Reioux <reioux@gmail.com>
Signed-off-by: flar2 <asegaert@gmail.com>
This commit is contained in:
Paul Reioux 2013-11-30 12:14:40 -06:00 committed by followmsi
parent 468de4793b
commit b5feb08ab6
4 changed files with 125 additions and 30 deletions

View File

@ -82,6 +82,22 @@ int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
}
EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
int wcd9xxx_reg_read_safe(struct wcd9xxx *wcd9xxx, unsigned short reg)
{
u8 val;
int ret;
ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
if (ret < 0)
return ret;
else
return val;
}
EXPORT_SYMBOL_GPL(wcd9xxx_reg_read_safe);
#endif
static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
int bytes, void *src, bool interface_reg)
{

View File

@ -161,6 +161,9 @@ struct wcd9xxx {
};
int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
int wcd9xxx_reg_read_safe(struct wcd9xxx *wcd9xxx, unsigned short reg);
#endif
int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
u8 val);
int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);

View File

@ -22,14 +22,48 @@
#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
#define SOUND_CONTROL_MAJOR_VERSION 3
#define SOUND_CONTROL_MINOR_VERSION 0
#define SOUND_CONTROL_MINOR_VERSION 1
extern struct snd_soc_codec *fauxsound_codec_ptr;
static int snd_ctrl_locked = 0;
unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg);
int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value);
int reg_access(unsigned int reg)
{
int ret = 1;
switch (reg) {
case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL:
case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL:
case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL:
case TABLA_A_CDC_RX4_VOL_CTL_B2_CTL:
case TABLA_A_CDC_RX5_VOL_CTL_B2_CTL:
case TABLA_A_CDC_RX6_VOL_CTL_B2_CTL:
case TABLA_A_CDC_RX7_VOL_CTL_B2_CTL:
case TABLA_A_CDC_TX1_VOL_CTL_GAIN:
case TABLA_A_CDC_TX2_VOL_CTL_GAIN:
case TABLA_A_CDC_TX3_VOL_CTL_GAIN:
case TABLA_A_CDC_TX4_VOL_CTL_GAIN:
case TABLA_A_CDC_TX5_VOL_CTL_GAIN:
case TABLA_A_CDC_TX6_VOL_CTL_GAIN:
case TABLA_A_CDC_TX7_VOL_CTL_GAIN:
case TABLA_A_CDC_TX8_VOL_CTL_GAIN:
case TABLA_A_CDC_TX9_VOL_CTL_GAIN:
case TABLA_A_CDC_TX10_VOL_CTL_GAIN:
if (snd_ctrl_locked)
ret = 0;
break;
default:
break;
}
return ret;
}
EXPORT_SYMBOL(reg_access);
static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c)
{
unsigned char chksum = 0;
@ -46,7 +80,7 @@ static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c)
static ssize_t cam_mic_gain_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%u",
return sprintf(buf, "%u\n",
tabla_read(fauxsound_codec_ptr,
TABLA_A_CDC_TX6_VOL_CTL_GAIN));
@ -69,7 +103,7 @@ static ssize_t cam_mic_gain_store(struct kobject *kobj,
static ssize_t mic_gain_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%u",
return sprintf(buf, "%u\n",
tabla_read(fauxsound_codec_ptr,
TABLA_A_CDC_TX7_VOL_CTL_GAIN));
}
@ -92,7 +126,7 @@ static ssize_t mic_gain_store(struct kobject *kobj,
static ssize_t speaker_gain_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%u %u",
return sprintf(buf, "%u %u\n",
tabla_read(fauxsound_codec_ptr,
TABLA_A_CDC_RX3_VOL_CTL_B2_CTL),
tabla_read(fauxsound_codec_ptr,
@ -119,7 +153,7 @@ static ssize_t speaker_gain_store(struct kobject *kobj,
static ssize_t headphone_gain_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%u %u",
return sprintf(buf, "%u %u\n",
tabla_read(fauxsound_codec_ptr,
TABLA_A_CDC_RX1_VOL_CTL_B2_CTL),
tabla_read(fauxsound_codec_ptr,
@ -145,7 +179,7 @@ static ssize_t headphone_gain_store(struct kobject *kobj,
static ssize_t headphone_pa_gain_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%u %u",
return sprintf(buf, "%u %u\n",
tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN),
tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN));
}
@ -186,6 +220,26 @@ static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attr
SOUND_CONTROL_MINOR_VERSION);
}
static ssize_t sound_control_locked_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
int inp;
sscanf(buf, "%d", &inp);
if (inp == 0)
snd_ctrl_locked = 0;
else
snd_ctrl_locked = 1;
return count;
}
static ssize_t sound_control_locked_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", snd_ctrl_locked);
}
static struct kobj_attribute cam_mic_gain_attribute =
__ATTR(gpl_cam_mic_gain,
0666,
@ -216,6 +270,12 @@ static struct kobj_attribute headphone_pa_gain_attribute =
headphone_pa_gain_show,
headphone_pa_gain_store);
static struct kobj_attribute sound_control_locked_attribute =
__ATTR(gpl_sound_control_locked,
0666,
sound_control_locked_show,
sound_control_locked_store);
static struct kobj_attribute sound_control_version_attribute =
__ATTR(gpl_sound_control_version,
0444,
@ -228,6 +288,7 @@ static struct attribute *sound_control_attrs[] =
&speaker_gain_attribute.attr,
&headphone_gain_attribute.attr,
&headphone_pa_gain_attribute.attr,
&sound_control_locked_attribute.attr,
&sound_control_version_attribute.attr,
NULL,
};

View File

@ -3935,31 +3935,13 @@ static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg)
return 0;
}
#define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
#ifndef CONFIG_SOUND_CONTROL_HAX_GPL
static
#endif
int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
int ret;
BUG_ON(reg > TABLA_MAX_REGISTER);
if (!tabla_volatile(codec, reg)) {
ret = snd_soc_cache_write(codec, reg, value);
if (ret != 0)
dev_err(codec->dev, "Cache write to %x failed: %d\n",
reg, ret);
}
return wcd9xxx_reg_write(codec->control_data, reg, value);
}
#ifdef CONFIG_SOUND_CONTROL_HAX_GPL
EXPORT_SYMBOL(tabla_write);
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
extern int reg_access(unsigned int reg);
#endif
#ifndef CONFIG_SOUND_CONTROL_HAX_GPL
#ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL
static
#endif
unsigned int tabla_read(struct snd_soc_codec *codec,
@ -3983,10 +3965,43 @@ unsigned int tabla_read(struct snd_soc_codec *codec,
val = wcd9xxx_reg_read(codec->control_data, reg);
return val;
}
#ifdef CONFIG_SOUND_CONTROL_HAX_GPL
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
EXPORT_SYMBOL(tabla_read);
#endif
#ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL
static
#endif
int tabla_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
int ret;
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
int val;
#endif
BUG_ON(reg > TABLA_MAX_REGISTER);
if (!tabla_volatile(codec, reg)) {
ret = snd_soc_cache_write(codec, reg, value);
if (ret != 0)
dev_err(codec->dev, "Cache write to %x failed: %d\n",
reg, ret);
}
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
if (!reg_access(reg))
val = wcd9xxx_reg_read_safe(codec->control_data, reg);
else
val = value;
return wcd9xxx_reg_write(codec->control_data, reg, val);
#else
return wcd9xxx_reg_write(codec->control_data, reg, value);
#endif
}
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
EXPORT_SYMBOL(tabla_write);
#endif
static s16 tabla_get_current_v_ins(struct tabla_priv *tabla, bool hu)
{
s16 v_ins;
@ -8422,7 +8437,7 @@ static const struct file_operations codec_mbhc_debug_ops = {
};
#endif
#ifdef CONFIG_SOUND_CONTROL_HAX_GPL
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
struct snd_kcontrol_new *gpl_faux_snd_controls_ptr =
(struct snd_kcontrol_new *)tabla_snd_controls;
struct snd_soc_codec *fauxsound_codec_ptr;
@ -8438,7 +8453,7 @@ static int tabla_codec_probe(struct snd_soc_codec *codec)
int i;
int ch_cnt;
#ifdef CONFIG_SOUND_CONTROL_HAX_GPL
#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL
pr_info("tabla codec probe...\n");
fauxsound_codec_ptr = codec;
#endif