All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Cox <alan@lxorguk.ukuu.org.uk>
To: greg@kroah.com, linux-kernel@vger.kernel.org
Subject: [PATCH 07/23] intel_sst: DMIC routing
Date: Tue, 03 May 2011 17:33:01 +0100	[thread overview]
Message-ID: <20110503163300.24853.62800.stgit@bob.linux.org.uk> (raw)
In-Reply-To: <20110503162919.24853.58699.stgit@bob.linux.org.uk>

From: Sitanshu Nanavati <sitanshu.nanavati@intel.com>

This patch adds support for configuring and routing the
DMICs (assigned HW route to DMICs)

Signed-off-by: Sitanshu Nanavati <sitanshu.nanavati@intel.com>
Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intel_sst.h             |    4 
 drivers/staging/intel_sst/intel_sst_stream.c      |    2 
 drivers/staging/intel_sst/intelmid.h              |   11 +
 drivers/staging/intel_sst/intelmid_ctrl.c         |  198 +++++++++++++++++++++
 drivers/staging/intel_sst/intelmid_msic_control.c |   58 ++++++
 5 files changed, 270 insertions(+), 3 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
index ea6cd97..c0d3156 100644
--- a/drivers/staging/intel_sst/intel_sst.h
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -33,6 +33,7 @@
 
 #define SST_CARD_NAMES "intel_mid_card"
 
+#define MFLD_MAX_HW_CH 4
 /* control list Pmic & Lpe */
 /* Input controls */
 enum port_status {
@@ -108,6 +109,9 @@ struct snd_pmic_ops {
 	int (*power_down_pmic_pb) (unsigned int device);
 	int (*power_down_pmic_cp) (unsigned int device);
 	int (*power_down_pmic) (void);
+	unsigned int hw_dmic_map[MFLD_MAX_HW_CH];
+	unsigned int available_dmics;
+	int (*set_hw_dmic_route) (u8 index);
 };
 
 struct intel_sst_pcm_control {
diff --git a/drivers/staging/intel_sst/intel_sst_stream.c b/drivers/staging/intel_sst/intel_sst_stream.c
index dd9c530..be4565e 100644
--- a/drivers/staging/intel_sst/intel_sst_stream.c
+++ b/drivers/staging/intel_sst/intel_sst_stream.c
@@ -48,7 +48,7 @@
  */
 int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
 {
-	if (device > MAX_NUM_STREAMS_MFLD) {
+	if (device >= MAX_NUM_STREAMS_MFLD) {
 		pr_debug("device type invalid %d\n", device);
 		return -EINVAL;
 	}
diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
index 4ed4a94..7b3dbf6 100644
--- a/drivers/staging/intel_sst/intelmid.h
+++ b/drivers/staging/intel_sst/intelmid.h
@@ -28,6 +28,7 @@
 #define __INTELMID_H
 
 #include <linux/time.h>
+#include <sound/jack.h>
 
 #define DRIVER_NAME_MFLD "msic_audio"
 #define DRIVER_NAME_MRST "pmic_audio"
@@ -43,7 +44,7 @@
 #define MAX_BUFFER		(800*1024) /* for PCM */
 #define MIN_BUFFER		(800*1024)
 #define MAX_PERIODS		(1024*2)
-#define MIN_PERIODS		1
+#define MIN_PERIODS		2
 #define MAX_PERIOD_BYTES MAX_BUFFER
 #define MIN_PERIOD_BYTES 32
 /*#define MIN_PERIOD_BYTES 160*/
@@ -57,7 +58,7 @@
 #define FIFO_SIZE		0 /* fifo not being used */
 #define INTEL_MAD		"Intel MAD"
 #define MAX_CTRL_MRST		7
-#define MAX_CTRL_MFLD		3
+#define MAX_CTRL_MFLD		7
 #define MAX_CTRL		7
 #define MAX_VENDORS		4
 /* TODO +6 db */
@@ -167,6 +168,12 @@ enum _widget_ctrl {
 enum _widget_ctrl_mfld {
 	LINEOUT_SEL_MFLD = 3,
 };
+enum hw_chs {
+	HW_CH0 = 0,
+	HW_CH1,
+	HW_CH2,
+	HW_CH3
+};
 
 void period_elapsed(void *mad_substream);
 int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream);
diff --git a/drivers/staging/intel_sst/intelmid_ctrl.c b/drivers/staging/intel_sst/intelmid_ctrl.c
index 3036928..dbe29c3 100644
--- a/drivers/staging/intel_sst/intelmid_ctrl.c
+++ b/drivers/staging/intel_sst/intelmid_ctrl.c
@@ -35,6 +35,22 @@
 #include "intelmid_snd_control.h"
 #include "intelmid.h"
 
+#define HW_CH_BASE 4
+
+
+#define HW_CH_0	"Hw1"
+#define HW_CH_1	"Hw2"
+#define HW_CH_2	"Hw3"
+#define HW_CH_3	"Hw4"
+
+static char *router_dmics[] = {	"DMIC1",
+				"DMIC2",
+				"DMIC3",
+				"DMIC4",
+				"DMIC5",
+				"DMIC6"
+				};
+
 static char *out_names_mrst[] = {"Headphones",
 				"Internal speakers"};
 static char *in_names_mrst[] = {"AMIC",
@@ -574,6 +590,152 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
 	return ret_val;
 }
 
+static int snd_intelmad_device_dmic_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *uval)
+{
+	struct snd_intelmad *intelmaddata;
+	struct snd_pmic_ops *scard_ops;
+
+	WARN_ON(!uval);
+	WARN_ON(!kcontrol);
+
+	intelmaddata = kcontrol->private_data;
+	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
+
+	if (scard_ops->input_dev_id != DMIC) {
+		pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
+		return 0;
+	}
+
+	if (intelmaddata->cpu_id == CPU_CHIP_PENWELL)
+		uval->value.enumerated.item[0] = kcontrol->private_value;
+	else
+		pr_debug(" CPU id = 0x%xis invalid.\n",
+			intelmaddata->cpu_id);
+	return 0;
+}
+
+void msic_set_bit(u8 index, unsigned int *available_dmics)
+{
+	*available_dmics |= (1 << index);
+}
+
+void msic_clear_bit(u8 index, unsigned int *available_dmics)
+{
+	*available_dmics &= ~(1 << index);
+}
+
+int msic_is_set_bit(u8 index, unsigned int *available_dmics)
+{
+	int ret_val;
+
+	ret_val = (*available_dmics & (1 << index));
+	return ret_val;
+}
+
+static int snd_intelmad_device_dmic_set(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *uval)
+{
+	struct snd_intelmad *intelmaddata;
+	struct snd_pmic_ops *scard_ops;
+	int i, dmic_index;
+	unsigned int available_dmics;
+	int jump_count;
+	int max_dmics = ARRAY_SIZE(router_dmics);
+
+	WARN_ON(!uval);
+	WARN_ON(!kcontrol);
+
+	intelmaddata = kcontrol->private_data;
+	WARN_ON(!intelmaddata->sstdrv_ops);
+
+	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
+	WARN_ON(!scard_ops);
+
+	if (scard_ops->input_dev_id != DMIC) {
+		pr_debug("input dev = 0x%x\n", scard_ops->input_dev_id);
+		return 0;
+	}
+
+	available_dmics = scard_ops->available_dmics;
+
+	if (kcontrol->private_value > uval->value.enumerated.item[0]) {
+		pr_debug("jump count -1.\n");
+		jump_count = -1;
+	} else {
+		pr_debug("jump count 1.\n");
+		jump_count = 1;
+	}
+
+	dmic_index =  uval->value.enumerated.item[0];
+	pr_debug("set function. dmic_index = %d, avl_dmic = 0x%x\n",
+			 dmic_index, available_dmics);
+	for (i = 0; i < max_dmics; i++) {
+		pr_debug("set function. loop index = 0x%x.  dmic_index = 0x%x\n",
+			 i, dmic_index);
+		if (!msic_is_set_bit(dmic_index, &available_dmics)) {
+			msic_clear_bit(kcontrol->private_value,
+						&available_dmics);
+			msic_set_bit(dmic_index, &available_dmics);
+			kcontrol->private_value = dmic_index;
+			scard_ops->available_dmics = available_dmics;
+			scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
+				kcontrol->private_value;
+			scard_ops->set_hw_dmic_route
+				(kcontrol->id.numid-HW_CH_BASE);
+			return 0;
+		}
+
+		dmic_index += jump_count;
+
+		if (dmic_index > (max_dmics - 1) && jump_count == 1) {
+			pr_debug("Resettingthe dmic index to 0.\n");
+			dmic_index = 0;
+		} else if (dmic_index == -1 && jump_count == -1) {
+			pr_debug("Resetting the dmic index to 5.\n");
+			dmic_index = max_dmics - 1;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int snd_intelmad_device_dmic_info_mfld(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	struct snd_intelmad *intelmaddata;
+	struct snd_pmic_ops *scard_ops;
+
+	uinfo->count                  = MONO_CNTL;
+	uinfo->type                   = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->value.enumerated.items = ARRAY_SIZE(router_dmics);
+
+	intelmaddata = kcontrol->private_data;
+	WARN_ON(!intelmaddata->sstdrv_ops);
+
+	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
+	WARN_ON(!scard_ops);
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+			uinfo->value.enumerated.items - 1;
+
+	strncpy(uinfo->value.enumerated.name,
+	router_dmics[uinfo->value.enumerated.item],
+	sizeof(uinfo->value.enumerated.name)-1);
+
+
+	msic_set_bit(kcontrol->private_value, &scard_ops->available_dmics);
+	pr_debug("info function. avl_dmic = 0x%x",
+		scard_ops->available_dmics);
+
+	scard_ops->hw_dmic_map[kcontrol->id.numid-HW_CH_BASE] =
+		kcontrol->private_value;
+
+	return 0;
+}
+
+
 struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
 {
 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -669,5 +831,41 @@ snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
 	.put		=	snd_intelmad_device_set,
 	.private_value	=	0,
 },
+{
+	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name		=	HW_CH_0,
+	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info		=	snd_intelmad_device_dmic_info_mfld,
+	.get		=	snd_intelmad_device_dmic_get,
+	.put		=	snd_intelmad_device_dmic_set,
+	.private_value	=	0
+},
+{
+	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name		=	HW_CH_1,
+	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info		=	snd_intelmad_device_dmic_info_mfld,
+	.get		=	snd_intelmad_device_dmic_get,
+	.put		=	snd_intelmad_device_dmic_set,
+	.private_value	=	1
+},
+{
+	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name		=	HW_CH_2,
+	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info		=	snd_intelmad_device_dmic_info_mfld,
+	.get		=	snd_intelmad_device_dmic_get,
+	.put		=	snd_intelmad_device_dmic_set,
+	.private_value	=	2
+},
+{
+	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name		=	HW_CH_3,
+	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info		=	snd_intelmad_device_dmic_info_mfld,
+	.get		=	snd_intelmad_device_dmic_get,
+	.put		=	snd_intelmad_device_dmic_set,
+	.private_value	=	3
+}
 };
 
diff --git a/drivers/staging/intel_sst/intelmid_msic_control.c b/drivers/staging/intel_sst/intelmid_msic_control.c
index 10073c5..976091b 100644
--- a/drivers/staging/intel_sst/intelmid_msic_control.c
+++ b/drivers/staging/intel_sst/intelmid_msic_control.c
@@ -29,8 +29,14 @@
 #include <linux/pci.h>
 #include <linux/file.h>
 #include <linux/delay.h>
+#include <sound/control.h>
 #include "intel_sst.h"
+#include <linux/input.h>
 #include "intelmid_snd_control.h"
+#include "intelmid.h"
+
+#define AUDIOMUX12  0x24c
+#define AUDIOMUX34  0x24d
 
 static int msic_init_card(void)
 {
@@ -680,6 +686,57 @@ static int msic_set_selected_input_dev(u8 value)
 	return retval;
 }
 
+static int msic_set_hw_dmic_route(u8 hw_ch_index)
+{
+	struct sc_reg_access sc_access_router;
+	int    retval = -EINVAL;
+
+	switch (hw_ch_index) {
+	case HW_CH0:
+		sc_access_router.reg_addr = AUDIOMUX12;
+		sc_access_router.value    = snd_msic_ops.hw_dmic_map[0];
+		sc_access_router.mask     = (MASK2 | MASK1 | MASK0);
+		pr_debug("hw_ch0.  value = 0x%x\n",
+				sc_access_router.value);
+		retval = sst_sc_reg_access(&sc_access_router,
+				PMIC_READ_MODIFY, 1);
+		break;
+
+	case HW_CH1:
+		sc_access_router.reg_addr = AUDIOMUX12;
+		sc_access_router.value    = (snd_msic_ops.hw_dmic_map[1]) << 4;
+		sc_access_router.mask     = (MASK6 | MASK5 | MASK4);
+		pr_debug("### hw_ch1.  value = 0x%x\n",
+				sc_access_router.value);
+		retval = sst_sc_reg_access(&sc_access_router,
+				PMIC_READ_MODIFY, 1);
+		break;
+
+	case HW_CH2:
+		sc_access_router.reg_addr = AUDIOMUX34;
+		sc_access_router.value    = snd_msic_ops.hw_dmic_map[2];
+		sc_access_router.mask     = (MASK2 | MASK1 | MASK0);
+		pr_debug("hw_ch2.  value = 0x%x\n",
+				sc_access_router.value);
+		retval = sst_sc_reg_access(&sc_access_router,
+				PMIC_READ_MODIFY, 1);
+		break;
+
+	case HW_CH3:
+		sc_access_router.reg_addr = AUDIOMUX34;
+		sc_access_router.value    = (snd_msic_ops.hw_dmic_map[3]) << 4;
+		sc_access_router.mask     = (MASK6 | MASK5 | MASK4);
+		pr_debug("hw_ch3.  value = 0x%x\n",
+				sc_access_router.value);
+		retval = sst_sc_reg_access(&sc_access_router,
+				PMIC_READ_MODIFY, 1);
+		break;
+	}
+
+	return retval;
+}
+
+
 static int msic_set_pcm_voice_params(void)
 {
 	return 0;
@@ -724,6 +781,7 @@ struct snd_pmic_ops snd_msic_ops = {
 	.set_input_dev	=	msic_set_selected_input_dev,
 	.set_output_dev =	msic_set_selected_output_dev,
 	.set_lineout_dev =	msic_set_selected_lineout_dev,
+	.set_hw_dmic_route =    msic_set_hw_dmic_route,
 	.set_mute	=	msic_set_mute,
 	.get_mute	=	msic_get_mute,
 	.set_vol	=	msic_set_vol,


  parent reply	other threads:[~2011-05-03 17:53 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
2011-05-03 16:31 ` [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield Alan Cox
2011-05-03 17:42   ` Greg KH
2011-05-03 21:29     ` Alan Cox
2011-05-03 21:39       ` Mark Brown
2011-05-03 21:53         ` Alan Cox
2011-05-03 22:02           ` Greg KH
2011-05-03 22:26             ` Mark Brown
2011-05-03 22:32               ` Greg KH
2011-05-03 22:59                 ` Alan Cox
2011-05-03 23:06                   ` Greg KH
2011-05-04  8:57                     ` Mark Brown
2011-05-10 20:01                       ` Greg KH
2011-05-03 16:32 ` [PATCH 02/23] intel_sst: MSIC codec power optimisation Alan Cox
2011-05-03 16:58   ` Mark Brown
2011-05-03 17:02     ` Alan Cox
2011-05-03 17:02       ` Mark Brown
2011-05-03 16:32 ` [PATCH 03/23] intel_sst: fix unload bugs Alan Cox
2011-05-03 16:32 ` [PATCH 04/23] intel_sst: ignore IRQ when suspended Alan Cox
2011-05-03 16:32 ` [PATCH 05/23] intel_sst: Line out support Alan Cox
2011-05-03 16:32 ` [PATCH 06/23] intel_sst: parameter tuning ioctl Alan Cox
2011-05-03 16:33 ` Alan Cox [this message]
2011-05-03 16:33 ` [PATCH 08/23] intel_sst: rework jack implementation Alan Cox
2011-05-03 16:33 ` [PATCH 09/23] intel_sst: Set de-bounce time Alan Cox
2011-05-03 16:33 ` [PATCH 10/23] intel_sst: Enable recording via HS_MIC Alan Cox
2011-05-03 16:33 ` [PATCH 11/23] intel_sst: Enable recording via DMIC Alan Cox
2011-05-03 16:34 ` [PATCH 12/23] intel_sst: Headphone Automute support Alan Cox
2011-05-03 16:34 ` [PATCH 13/23] intel_sst: move jack detection related configs to init time Alan Cox
2011-05-03 16:34 ` [PATCH 14/23] sst: return correct output/input device id Alan Cox
2011-05-03 16:34 ` [PATCH 15/23] intel_sst: make sure the sst_drop_stream() get called when needed Alan Cox
2011-05-03 16:35 ` [PATCH 16/23] intel_sst: MRST can only do mono recording Alan Cox
2011-05-03 16:35 ` [PATCH 17/23] intel_sst: MRST can only do 16bit recording Alan Cox
2011-05-03 16:35 ` [PATCH 18/23] intel_sst: intelmid_v2_control: correct jack event type Alan Cox
2011-05-03 16:37 ` [PATCH 19/23] intel_sst: fix runtime pm issue Alan Cox
2011-05-03 16:38 ` [PATCH 20/23] sst: set default output and input device Alan Cox
2011-05-03 16:38 ` [PATCH 21/23] intel_sst: add Master Volume Alan Cox
2011-05-03 16:43 ` [PATCH 22/23] sst: internal speaker needs setting a GPIO line Alan Cox
2011-05-03 16:43 ` [PATCH 23/23] intel_sst: fix output noises when it's not in playback Alan Cox
2011-05-03 17:15 ` [PATCH 00/23] Intel SST driver update Mark Brown
2011-05-03 18:36   ` Alan Cox
2011-05-03 18:40     ` Mark Brown
2011-05-03 20:27       ` Alan Cox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110503163300.24853.62800.stgit@bob.linux.org.uk \
    --to=alan@lxorguk.ukuu.org.uk \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.