mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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:
parent
da5edc8231
commit
b3dc4742d9
4 changed files with 281 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
267
sound/soc/codecs/sound_control_gpl.c
Normal file
267
sound/soc/codecs/sound_control_gpl.c
Normal 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");
|
||||
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue