Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9cbb525 authored by Anomalchik's avatar Anomalchik
Browse files

sound: soc: changes for markw

parent 9661b4f8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4,6 +4,12 @@

menu "Misc devices"

config AW8736
	tristate "support aw8636 on markw"
	depends on I2C
	help
	  Say Y here if you have a markw power amplifier.

config SENSORS_LIS3LV02D
	tristate
	depends on INPUT
+1 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ obj-$(CONFIG_TI_DRV2667) += ti_drv2667.o
obj-$(CONFIG_USB_EXT_TYPE_C_PERICOM)	+= type-c-pericom.o
obj-$(CONFIG_USB_EXT_TYPE_C_TI)		+= type-c-ti.o
obj-$(CONFIG_QPNP_MISC) 	+= qpnp-misc.o
obj-$(CONFIG_AW8736) += aw8736.o
obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
obj-$(CONFIG_APDS9930)		+= apds993x.o

drivers/misc/aw8736.c

0 → 100644
+198 −0
Original line number Diff line number Diff line
/*
** =============================================================================
** Copyright (c) 2017  Nikolay Karev
**
** This program is free software; you can redistribute it and/or modify it under
** the terms of the GNU General Public License as published by the Free Software
** Foundation; version 2.
**
** 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.
**
** You should have received a copy of the GNU General Public License along with
** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
** Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
** File:
**     aw8736.c
**
** Description:
**     misc driver for Texas Instruments AW8736 High Performance 4W Smart Amplifier
**
** =============================================================================
*/


#define DEBUG
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <linux/i2c-dev.h>
#include <linux/mutex.h>



#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/string.h>


#define DRV_NAME "aw8736"

#define AW8736_MODE 5

#define EXT_CLASS_D_EN_DELAY 13000
#define EXT_CLASS_D_DIS_DELAY 4000
#define EXT_CLASS_D_DELAY_DELTA 2000

static int spk_pa_gpio = -1;
static int value = 0;
struct mutex lock;

static void amplifier_enable(void) {
  int i = 0;
  mutex_lock(&lock);
  pr_info("Enabling amplifier in kernel\n");
	/* Open external audio PA device */
	for (i = 0; i < AW8736_MODE; i++) {
		gpio_direction_output(spk_pa_gpio, false);
		gpio_direction_output(spk_pa_gpio, true);
	}
	usleep_range(EXT_CLASS_D_EN_DELAY,
	EXT_CLASS_D_EN_DELAY + EXT_CLASS_D_DELAY_DELTA);
  mutex_unlock(&lock);
}

static void amplifier_disable(void) {
  mutex_lock(&lock);
  gpio_direction_output(spk_pa_gpio, false);
  pr_info("Disabling amplifier in kernel\n");
  usleep_range(EXT_CLASS_D_DIS_DELAY,
   EXT_CLASS_D_DIS_DELAY + EXT_CLASS_D_DELAY_DELTA);
  mutex_unlock(&lock);
}

static int init_gpio(struct platform_device *pdev) {
  spk_pa_gpio = of_get_named_gpio(pdev->dev.of_node, "ext-spk-amp-gpio", 0);
	if (spk_pa_gpio < 0) {
		dev_err(&pdev->dev,
		"%s: error! spk_pa_gpio is :%d\n", __func__, spk_pa_gpio);
	} else {
		if (gpio_request_one(spk_pa_gpio, GPIOF_DIR_OUT, "spk_enable")) {
			pr_err("%s: request spk_pa_gpio  fail!\n", __func__);
		}
	}
	pr_err("%s: [hjf] request spk_pa_gpio is %d!\n", __func__, spk_pa_gpio);
  gpio_direction_output(spk_pa_gpio, 0);
  return 0;
}

static ssize_t enable_show(struct kobject *kobj,
			struct kobj_attribute *attr, char *buf)
{
	return sprintf(buf, "%d\n", value);
}

static ssize_t enable_store(struct kobject *kobj,
			struct kobj_attribute *attr, const char *buf, size_t count)
{
	sscanf(buf, "%du", &value);
  if (value) {
    amplifier_enable();
  } else {
    amplifier_disable();
  }
	return count;
}

static struct kobj_attribute enable_attr =
	__ATTR(enable, 0664, enable_show, enable_store);

static struct kobject *kobj;

static int aw8736_machine_probe(struct platform_device *pdev)
{
	int ret = init_gpio(pdev);
  if (ret) {
    pr_err("Error initializing amplifier gpio: %d\n", ret);
  }

	/* create a dir in sys/ */
	kobj = kobject_create_and_add("audio_amplifier", NULL);
	if (!kobj)
		return - ENOMEM;

	/* create a attribute file in kobj_example */
 	ret = sysfs_create_file(kobj, &enable_attr.attr);
	if (ret)
		goto attr_file_failed;
  mutex_init(&lock);
	return 0;
attr_file_failed:
	kobject_put(kobj);
	return ret;
}

static int aw8736_machine_remove(struct platform_device *pdev) {
  return 0;
}

static const struct of_device_id aw8736_machine_of_match[]  = {
	{ .compatible = "aw,aw8736", },
	{},
};
static int snd_soc_pm(struct device *dev) {
  return 0;
};

const struct dev_pm_ops pm_ops = {
	.suspend = &snd_soc_pm,
	.resume = &snd_soc_pm,
	.freeze = &snd_soc_pm,
	.thaw = &snd_soc_pm,
	.poweroff = &snd_soc_pm,
	.restore = &snd_soc_pm,
};


static struct platform_driver aw8736_machine_driver = {
	.driver = {
		.name = DRV_NAME,
		.owner = THIS_MODULE,
		.pm = &pm_ops,
		.of_match_table = aw8736_machine_of_match,
	},
	.probe = aw8736_machine_probe,
	.remove = aw8736_machine_remove,
};

static int __init aw8736_machine_init(void)
{
	return platform_driver_register(&aw8736_machine_driver);
}

late_initcall(aw8736_machine_init);

static void __exit aw8736_machine_exit(void)
{
	return platform_driver_unregister(&aw8736_machine_driver);
}

module_exit(aw8736_machine_exit);

MODULE_DESCRIPTION("aw8736 amplifier");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_DEVICE_TABLE(of, aw8736_machine_of_match);
+3 −0
Original line number Diff line number Diff line
@@ -337,6 +337,9 @@

#define KEY_MICMUTE		248	/* Mute / unmute the microphone */

#define KEY_NEXTSONG_NEW        250
#define KEY_PREVIOUSSONG_NEW    251

/* Code 255 is reserved for special needs of AT keyboard driver */

#define BTN_MISC		0x100
+71 −1
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <sound/q6afe-v2.h>
#ifdef CONFIG_MACH_XIAOMI_MARKW
#include <linux/switch.h>
#endif
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -98,7 +101,11 @@ enum {
#define SPK_PMD 2
#define SPK_PMU 3

#ifdef CONFIG_MACH_XIAOMI_MARKW
#define MICBIAS_DEFAULT_VAL 2700000
#else
#define MICBIAS_DEFAULT_VAL 1800000
#endif
#define MICBIAS_MIN_VAL 1600000
#define MICBIAS_STEP_SIZE 50000

@@ -133,7 +140,14 @@ static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
static struct snd_soc_dai_driver msm8x16_wcd_i2s_dai[];
/* By default enable the internal speaker boost */
#ifdef CONFIG_MACH_XIAOMI_MARKW
static struct switch_dev accdet_data;
static int accdet_state;

static bool spkr_boost_en;
#else
static bool spkr_boost_en = true;
#endif

#define MSM8X16_WCD_ACQUIRE_LOCK(x) \
	mutex_lock_nested(&x, SINGLE_DEPTH_NESTING)
@@ -663,9 +677,15 @@ static void msm8x16_wcd_mbhc_internal_micbias_ctrl(struct snd_soc_codec *codec,
{
	if (micbias_num == 1) {
		if (enable)
#ifdef CONFIG_MACH_XIAOMI_MARKW
			snd_soc_update_bits(codec,
				MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS,
				0x18, 0x18);
#else
			snd_soc_update_bits(codec,
				MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS,
				0x10, 0x10);
#endif
		else
			snd_soc_update_bits(codec,
				MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS,
@@ -1162,6 +1182,12 @@ static int __msm8x16_wcd_reg_read(struct snd_soc_codec *codec,
	pr_debug("%s reg = %x\n", __func__, reg);
	mutex_lock(&msm8x16_wcd->io_lock);
	pdata = snd_soc_card_get_drvdata(codec->component.card);
#ifdef CONFIG_MACH_XIAOMI_MARKW
	if (pdata == NULL) {
		mutex_unlock(&msm8x16_wcd->io_lock);
		return ret;
	}
#endif
	if (MSM8X16_WCD_IS_TOMBAK_REG(reg))
		ret = msm8x16_wcd_spmi_read(reg, 1, &temp);
	else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
@@ -1218,6 +1244,12 @@ static int __msm8x16_wcd_reg_write(struct snd_soc_codec *codec,

	mutex_lock(&msm8x16_wcd->io_lock);
	pdata = snd_soc_card_get_drvdata(codec->component.card);
#ifdef CONFIG_MACH_XIAOMI_MARKW
	if (pdata == NULL) {
		mutex_unlock(&msm8x16_wcd->io_lock);
		return ret;
	}
#endif
	if (MSM8X16_WCD_IS_TOMBAK_REG(reg))
		ret = msm8x16_wcd_spmi_write(reg, 1, &val);
	else if (MSM8X16_WCD_IS_DIGITAL_REG(reg)) {
@@ -4315,7 +4347,19 @@ static int msm8x16_wcd_hphr_dac_event(struct snd_soc_dapm_widget *w,
	}
	return 0;
}
#ifdef CONFIG_MACH_XIAOMI_MARKW
void msm8x16_wcd_codec_set_headset_state(u32 state)
{
	switch_set_state((struct switch_dev *)&accdet_data, state);
	accdet_state = state;
}
  		  
int msm8x16_wcd_codec_get_headset_state(void)
{
	pr_debug("%s accdet_state = %d\n", __func__, accdet_state);
	return accdet_state;
}
#endif
static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
			      struct snd_kcontrol *kcontrol, int event)
{
@@ -4925,10 +4969,18 @@ static int msm8x16_wcd_codec_enable_lo_pa(struct snd_soc_dapm_widget *w,
		snd_soc_update_bits(codec,
			MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0x01, 0x00);
		break;
#ifdef CONFIG_MACH_XIAOMI_MARKW
	case SND_SOC_DAPM_PRE_PMD:
		gpio_direction_output(96, false);
		snd_soc_update_bits(codec,
			MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0x01, 0x00);
		break;
#else
	case SND_SOC_DAPM_POST_PMD:
		snd_soc_update_bits(codec,
			MSM8X16_WCD_A_CDC_RX3_B6_CTL, 0x01, 0x00);
		break;
#endif
	}

	return 0;
@@ -5110,9 +5162,15 @@ static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = {
			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),

#ifdef CONFIG_MACH_XIAOMI_MARKW
	SND_SOC_DAPM_PGA_E("LINEOUT PA", MSM8X16_WCD_A_ANALOG_RX_LO_EN_CTL,
			6, 0 , NULL, 0, msm8x16_wcd_codec_enable_lo_pa,
			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
#else
	SND_SOC_DAPM_PGA_E("LINEOUT PA", MSM8X16_WCD_A_ANALOG_RX_LO_EN_CTL,
			5, 0 , NULL, 0, msm8x16_wcd_codec_enable_lo_pa,
			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
#endif

	SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
			    msm89xx_wcd_codec_enable_vdd_spkr,
@@ -5878,6 +5936,18 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
	wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
		      wcd_mbhc_registers, true);

#ifdef CONFIG_MACH_XIAOMI_MARKW
	accdet_data.name = "h2w";
	accdet_data.index = 0;
	accdet_data.state = 0;
  		  
	ret = switch_dev_register(&accdet_data);
	if (ret) {
		dev_err(codec->dev, "%s: Failed to register h2w\n", __func__);
		return -ENOMEM;
	}
#endif

	msm8x16_wcd_priv->mclk_enabled = false;
	msm8x16_wcd_priv->clock_active = false;
	msm8x16_wcd_priv->config_mode_active = false;
Loading