Sound Control: Sound control for WCD93xx codec

Fully GPL'ed version.

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

Conflicts:
	sound/soc/codecs/Kconfig
	sound/soc/codecs/Makefile
Signed-off-by: flar2 <asegaert@gmail.com>
This commit is contained in:
faux123 2013-03-09 16:30:29 -06:00 committed by followmsi
parent da5edc8231
commit b3dc4742d9
4 changed files with 281 additions and 0 deletions

View file

@ -454,3 +454,9 @@ config SND_SOC_TPA2028D
default n
help
Texas Instruments 3W Mono Class-D Audio Amplifier
config SOUND_CONTROL_HAX_GPL
tristate "wcd93xx sound control hax"
default y
help
FauxSound WCD93xx chipset sound control hacks

View file

@ -213,3 +213,6 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
obj-$(CONFIG_SND_SOC_TPA2028D) += tpa2028d.o
# Hack
obj-$(CONFIG_SOUND_CONTROL_HAX_GPL) += sound_control_gpl.o

View file

@ -0,0 +1,267 @@
/*
* Author: Paul Reioux aka Faux123 <reioux@gmail.com>
*
* WCD93xx sound control module
* Copyright 2013 Paul Reioux
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/kallsyms.h>
#include <sound/control.h>
#include <sound/soc.h>
extern struct snd_kcontrol_new *gpl_faux_snd_controls_ptr;
#define SOUND_CONTROL_MAJOR_VERSION 2
#define SOUND_CONTROL_MINOR_VERSION 0
#define CAMCORDER_MIC_OFFSET 20
#define HANDSET_MIC_OFFSET 21
#define SPEAKER_OFFSET 10
#define HEADPHONE_L_OFFSET 8
#define HEADPHONE_R_OFFSET 9
static ssize_t cam_mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct soc_mixer_control *l_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[CAMCORDER_MIC_OFFSET].
private_value;
return sprintf(buf, "%d", l_mixer_ptr->max);
}
static ssize_t cam_mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
int l_max;
int l_delta;
struct soc_mixer_control *l_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[CAMCORDER_MIC_OFFSET].
private_value;
sscanf(buf, "%d", &l_max);
// limit the max gain
l_delta = l_max - l_mixer_ptr->platform_max;
l_mixer_ptr->platform_max = l_max;
l_mixer_ptr->max = l_max;
l_mixer_ptr->min += l_delta;
return (count);
}
static ssize_t mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct soc_mixer_control *l_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET].
private_value;
return sprintf(buf, "%d", l_mixer_ptr->max);
}
static ssize_t mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
int l_max;
int l_delta;
struct soc_mixer_control *l_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET].
private_value;
sscanf(buf, "%d", &l_max);
l_delta = l_max - l_mixer_ptr->platform_max;
l_mixer_ptr->platform_max = l_max;
l_mixer_ptr->max = l_max;
l_mixer_ptr->min += l_delta;
return (count);
}
static ssize_t speaker_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct soc_mixer_control *l_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET].
private_value;
return sprintf(buf, "%d", l_mixer_ptr->max);
}
static ssize_t speaker_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
int l_max;
int l_delta;
struct soc_mixer_control *l_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET].
private_value;
sscanf(buf, "%d", &l_max);
l_delta = l_max - l_mixer_ptr->platform_max;
l_mixer_ptr->platform_max = l_max;
l_mixer_ptr->max = l_max;
l_mixer_ptr->min += l_delta;
return (count);
}
static ssize_t headphone_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET].
private_value;
r_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET].
private_value;
return sprintf(buf, "%d %d",
l_mixer_ptr->max,
r_mixer_ptr->max);
}
static ssize_t headphone_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
int l_max, r_max;
int l_delta, r_delta;
struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr;
l_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET].
private_value;
r_mixer_ptr =
(struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET].
private_value;
sscanf(buf, "%d %d", &l_max, &r_max);
l_delta = l_max - l_mixer_ptr->platform_max;
l_mixer_ptr->platform_max = l_max;
l_mixer_ptr->max = l_max;
l_mixer_ptr->min += l_delta;
r_delta = r_max - r_mixer_ptr->platform_max;
r_mixer_ptr->platform_max = r_max;
r_mixer_ptr->max = r_max;
r_mixer_ptr->min += r_delta;
return count;
}
static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "version: %u.%u\n",
SOUND_CONTROL_MAJOR_VERSION,
SOUND_CONTROL_MINOR_VERSION);
}
static struct kobj_attribute cam_mic_gain_attribute =
__ATTR(gpl_cam_mic_gain,
0666,
cam_mic_gain_show,
cam_mic_gain_store);
static struct kobj_attribute mic_gain_attribute =
__ATTR(gpl_mic_gain,
0666,
mic_gain_show,
mic_gain_store);
static struct kobj_attribute speaker_gain_attribute =
__ATTR(gpl_speaker_gain,
0666,
speaker_gain_show,
speaker_gain_store);
static struct kobj_attribute headphone_gain_attribute =
__ATTR(gpl_headphone_gain,
0666,
headphone_gain_show,
headphone_gain_store);
static struct kobj_attribute sound_control_version_attribute =
__ATTR(gpl_sound_control_version,
0444,
sound_control_version_show, NULL);
static struct attribute *sound_control_attrs[] =
{
&cam_mic_gain_attribute.attr,
&mic_gain_attribute.attr,
&speaker_gain_attribute.attr,
&headphone_gain_attribute.attr,
&sound_control_version_attribute.attr,
NULL,
};
static struct attribute_group sound_control_attr_group =
{
.attrs = sound_control_attrs,
};
static struct kobject *sound_control_kobj;
static int sound_control_init(void)
{
int sysfs_result;
if (gpl_faux_snd_controls_ptr == NULL) {
pr_err("%s sound_controls_ptr is NULL!\n", __FUNCTION__);
return -1;
}
sound_control_kobj =
kobject_create_and_add("sound_control", kernel_kobj);
if (!sound_control_kobj) {
pr_err("%s sound_control_kobj create failed!\n",
__FUNCTION__);
return -ENOMEM;
}
sysfs_result = sysfs_create_group(sound_control_kobj,
&sound_control_attr_group);
if (sysfs_result) {
pr_info("%s sysfs create failed!\n", __FUNCTION__);
kobject_put(sound_control_kobj);
}
return sysfs_result;
}
static void sound_control_exit(void)
{
if (sound_control_kobj != NULL)
kobject_put(sound_control_kobj);
}
module_init(sound_control_init);
module_exit(sound_control_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul Reioux <reioux@gmail.com>");
MODULE_DESCRIPTION("Sound Control Module GPL Edition");

View file

@ -8408,6 +8408,11 @@ static const struct file_operations codec_mbhc_debug_ops = {
};
#endif
#ifdef CONFIG_SOUND_CONTROL_HAX_GPL
struct snd_kcontrol_new *gpl_faux_snd_controls_ptr =
(struct snd_kcontrol_new *)tabla_snd_controls;
#endif
static int tabla_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;