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

Commit 26c023bb authored by Yeleswarapu, Nagaradhesh's avatar Yeleswarapu, Nagaradhesh Committed by Michael Bohan
Browse files

ASoC: wcd: 8x16 mbhc driver



mbhc driver for 8x16 to detect insertion/removal
of cable and to differentiate whether the cable
is headset/headphone/extension-cable

Change-Id: I42ef043acfd984945a8a0e5324c2dfcf789ecec2
Signed-off-by: default avatarYeleswarapu, Nagaradhesh <nagaradh@codeaurora.org>
parent 6a76f269
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ snd-soc-wcd9320-objs := wcd9320.o wcd9320-tables.o
snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o
snd-soc-wcd9xxx-objs := wcd9xxx-resmgr.o wcd9xxx-mbhc.o wcd9xxx-common.o
snd-soc-msm8x10-wcd-objs := msm8x10-wcd.o msm8x10-wcd-tables.o wcd9xxx-common.o
snd-soc-msm8x16-wcd-objs := msm8x16-wcd.o msm8x16-wcd-tables.o
snd-soc-msm8x16-wcd-objs := msm8x16-wcd.o msm8x16-wcd-tables.o wcd-mbhc-v2.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm-adsp-objs := wm_adsp.o
snd-soc-wm0010-objs := wm0010.o
+38 −12
Original line number Diff line number Diff line
@@ -132,10 +132,8 @@ struct msm8x16_wcd_priv {
	bool clock_active;
	bool config_mode_active;
	struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];
	/* resmgr module */
	/*struct wcd9xxx_resmgr resmgr;*/
	/* mbhc module */
	/*struct wcd9xxx_mbhc mbhc; */
	struct wcd_mbhc mbhc;
};

static unsigned long rx_digital_gain_reg[] = {
@@ -160,6 +158,15 @@ struct msm8x16_wcd_spmi {
	int base;
};

static const struct wcd_mbhc_intr intr_ids = {
	.mbhc_sw_intr =  MSM8X16_WCD_IRQ_MBHC_HS_DET,
	.mbhc_btn_press_intr = MSM8X16_WCD_IRQ_MBHC_INSREM_DET,
	.mbhc_btn_release_intr = MSM8X16_WCD_IRQ_MBHC_PRESS,
	.mbhc_hs_ins_rem_intr = MSM8X16_WCD_IRQ_MBHC_RELEASE,
	.hph_left_ocp = MSM8X16_WCD_IRQ_HPHL_OCP,
	.hph_right_ocp = MSM8X16_WCD_IRQ_HPHR_OCP,
};

static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
	struct msm8x16_wcd_regulator *vreg,
	const char *vreg_name, bool ondemand);
@@ -1761,8 +1768,6 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		/* Let MBHC module know PA is turning on
		wcd9xxx_resmgr_notifier_call(&msm8x16_wcd->resmgr, e_pre_on); */
		break;

	case SND_SOC_DAPM_POST_PMU:
@@ -1797,9 +1802,6 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
		break;
	case SND_SOC_DAPM_POST_PMD:
		usleep_range(4000, 4100);
		/* Let MBHC module know PA turned off
		wcd9xxx_resmgr_notifier_call(&msm8x16_wcd->resmgr,
					e_post_off); */

		snd_soc_update_bits(codec,
			MSM8X16_WCD_A_ANALOG_NCP_EN, 0x11, 0x10);
@@ -2498,13 +2500,15 @@ static void msm8x16_wcd_update_reg_defaults(struct snd_soc_codec *codec)

static const struct msm8x16_wcd_reg_mask_val
	msm8x16_wcd_codec_reg_init_val[] = {
/*
	* Initialize current threshold to 350MA

	/* Initialize current threshold to 350MA
	 * number of wait and run cycles to 4096
	 *
	 */
	{MSM8X16_WCD_A_ANALOG_RX_COM_OCP_CTL, 0xE1, 0x61},
	{MSM8X16_WCD_A_ANALOG_RX_COM_OCP_COUNT, 0xFF, 0xFF},

	{MSM8X16_WCD_A_ANALOG_RX_HPH_L_TEST, 0x40, 0x40},
	{MSM8X16_WCD_A_ANALOG_RX_HPH_R_TEST, 0x40, 0x40},
/*
	* Initialize gain registers to use register gain *

	*enable HPF filter for TX paths *
@@ -2556,6 +2560,7 @@ static struct regulator *wcd8x16_wcd_codec_find_regulator(
	dev_err(msm8x16->dev, "Error: regulator not found\n");
	return NULL;
}

static int msm8x16_wcd_device_down(struct snd_soc_codec *codec)
{
	dev_dbg(codec->dev, "%s: device down!\n", __func__);
@@ -2626,6 +2631,25 @@ static struct notifier_block modem_state_notifier_block = {
	.priority = -INT_MAX,
};

int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
		    struct wcd_mbhc_config *mbhc_cfg)
{
	struct msm8x16_wcd_priv *msm8x16_wcd_priv =
		snd_soc_codec_get_drvdata(codec);

	return wcd_mbhc_start(&msm8x16_wcd_priv->mbhc, mbhc_cfg);
}
EXPORT_SYMBOL(msm8x16_wcd_hs_detect);

void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec)
{
	struct msm8x16_wcd_priv *msm8x16_wcd_priv =
		snd_soc_codec_get_drvdata(codec);

	wcd_mbhc_stop(&msm8x16_wcd_priv->mbhc);
}
EXPORT_SYMBOL(msm8x16_wcd_hs_detect_exit);

static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
{
	struct msm8x16_wcd_priv *msm8x16_wcd_priv;
@@ -2666,6 +2690,8 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
				on_demand_supply_name[ON_DEMAND_MICBIAS]);
	atomic_set(&msm8x16_wcd_priv->on_demand_list[ON_DEMAND_MICBIAS].ref, 0);

	wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &intr_ids, false);

	msm8x16_wcd_priv->mclk_enabled = false;
	msm8x16_wcd_priv->clock_active = false;
	msm8x16_wcd_priv->config_mode_active = false;
+6 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <sound/soc.h>
#include <sound/jack.h>
#include <linux/mfd/wcd9xxx/pdata.h>
#include "wcd-mbhc-v2.h"

#define MSM8X16_WCD_NUM_REGISTERS	0x6FF
#define MSM8X16_WCD_MAX_REGISTER	(MSM8X16_WCD_NUM_REGISTERS-1)
@@ -153,5 +154,10 @@ struct msm8x16_wcd {
extern int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
			     bool dapm);

extern int msm8x16_wcd_hs_detect(struct snd_soc_codec *codec,
		    struct wcd_mbhc_config *mbhc_cfg);

extern void msm8x16_wcd_hs_detect_exit(struct snd_soc_codec *codec);

#endif
+737 −0

File added.

Preview size limit exceeded, changes collapsed.

+71 −0
Original line number Diff line number Diff line
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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.
 */
#ifndef __WCD_MBHC_V2_H__
#define __WCD_MBHC_V2_H__

#include <linux/wait.h>

enum wcd_mbhc_plug_type {
	PLUG_TYPE_INVALID = -1,
	PLUG_TYPE_NONE,
	PLUG_TYPE_HEADSET,
	PLUG_TYPE_HEADPHONE,
	PLUG_TYPE_HIGH_HPH,
	PLUG_TYPE_GND_MIC_SWAP,
};

struct wcd_mbhc_config {
	bool read_fw_bin;
	void *calibration;
	bool detect_extn_cable;
};

struct wcd_mbhc_intr {
	int mbhc_sw_intr;
	int mbhc_btn_press_intr;
	int mbhc_btn_release_intr;
	int mbhc_hs_ins_rem_intr;
	int hph_left_ocp;
	int hph_right_ocp;
};

struct wcd_mbhc {
	int buttons_pressed;
	struct wcd_mbhc_config *mbhc_cfg;

	u32 hph_status; /* track headhpone status */
	u8 hphlocp_cnt; /* headphone left ocp retry */
	u8 hphrocp_cnt; /* headphone right ocp retry */

	wait_queue_head_t wait_btn_press;
	bool is_btn_press;
	u8 current_plug;

	bool in_swch_irq_handler;

	struct snd_soc_codec *codec;

	struct snd_soc_jack headset_jack;
	struct snd_soc_jack button_jack;
	struct mutex codec_resource_lock;

	/* Holds codec specific interrupt mapping */
	const struct wcd_mbhc_intr *intr_ids;
};
int wcd_mbhc_start(struct wcd_mbhc *mbhc,
		       struct wcd_mbhc_config *mbhc_cfg);
void wcd_mbhc_stop(struct wcd_mbhc *mbhc);
int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
		      bool impedance_det_en);
void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);
#endif /* __WCD_MBHC_V2_H__ */
Loading