All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/23] Intel SST driver update
@ 2011-05-03 16:31 Alan Cox
  2011-05-03 16:31 ` [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield Alan Cox
                   ` (23 more replies)
  0 siblings, 24 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:31 UTC (permalink / raw)
  To: greg, linux-kernel

This is a forward port of various further Intel work on the SST driver in
staging. This keeps the staging driver up to date while the ALSA driver
development continues.

Alan



---

Andy CH Lin (1):
      intel_sst: intelmid_v2_control: correct jack event type

Chandramouli Narayanan (1):
      intel_sst: fix runtime pm issue

Dharageswari R (1):
      intel_sst: Line out support

Feng Tang (1):
      intel_sst: make sure the sst_drop_stream() get called when needed

Lu Guanqun (9):
      intel_sst: fix output noises when it's not in playback
      sst: internal speaker needs setting a GPIO line
      intel_sst: add Master Volume
      sst: set default output and input device
      sst: return correct output/input device id
      intel_sst: move jack detection related configs to init time
      intel_sst: Enable recording via DMIC
      intel_sst: Enable recording via HS_MIC
      intel_sst: Set de-bounce time

Ramesh Babu K V (1):
      intel_sst: rework jack implementation

Sitanshu Nanavati (1):
      intel_sst: DMIC routing

Vinod Koul (5):
      intel_sst: parameter tuning ioctl
      intel_sst: ignore IRQ when suspended
      intel_sst: fix unload bugs
      intel_sst: MSIC codec power optimisation
      intel_sst: Save audio state across D3 on Medfield

Wu Fengguang (2):
      intel_sst: MRST can only do 16bit recording
      intel_sst: MRST can only do mono recording

xingchao (1):
      intel_sst: Headphone Automute support


 drivers/staging/intel_sst/intel_sst.c              |  129 +++
 drivers/staging/intel_sst/intel_sst.h              |   33 +
 .../staging/intel_sst/intel_sst_app_interface.c    |   37 +
 drivers/staging/intel_sst/intel_sst_common.h       |    9 
 .../staging/intel_sst/intel_sst_drv_interface.c    |   23 -
 drivers/staging/intel_sst/intel_sst_dsp.c          |   14 
 drivers/staging/intel_sst/intel_sst_fw_ipc.h       |    7 
 drivers/staging/intel_sst/intel_sst_ioctl.h        |    8 
 drivers/staging/intel_sst/intel_sst_ipc.c          |   74 ++
 drivers/staging/intel_sst/intel_sst_stream.c       |   15 
 .../staging/intel_sst/intel_sst_stream_encoded.c   |    8 
 drivers/staging/intel_sst/intelmid.c               |  473 +++--------
 drivers/staging/intel_sst/intelmid.h               |   38 +
 drivers/staging/intel_sst/intelmid_adc_control.h   |  193 +++++
 drivers/staging/intel_sst/intelmid_ctrl.c          |  304 +++++++
 drivers/staging/intel_sst/intelmid_msic_control.c  |  833 ++++++++++++++++++--
 drivers/staging/intel_sst/intelmid_pvt.c           |    1 
 drivers/staging/intel_sst/intelmid_snd_control.h   |    9 
 drivers/staging/intel_sst/intelmid_v0_control.c    |  109 ++-
 drivers/staging/intel_sst/intelmid_v1_control.c    |  141 +++
 drivers/staging/intel_sst/intelmid_v2_control.c    |  219 ++++-
 drivers/staging/intel_sst/jack.h                   |   10 
 22 files changed, 2125 insertions(+), 562 deletions(-)
 create mode 100644 drivers/staging/intel_sst/intelmid_adc_control.h
 delete mode 100644 drivers/staging/intel_sst/jack.h

-- 
	"Policy is a poor man's substitute for common sense."
			-- David Woodhouse


^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
@ 2011-05-03 16:31 ` Alan Cox
  2011-05-03 17:42   ` Greg KH
  2011-05-03 16:32 ` [PATCH 02/23] intel_sst: MSIC codec power optimisation Alan Cox
                   ` (22 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:31 UTC (permalink / raw)
  To: greg, linux-kernel

From: Vinod Koul <vinod.koul@intel.com>

During suspend and runtime_suspend audio dsp will be in D3 state
and will loose its context.

This patch adds support in driver to save the dsp context
and restore this context during resume

Signed-off-by: Vinod Koul <vinod.koul@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.c              |   67 +++++++++++++++++++-
 drivers/staging/intel_sst/intel_sst_common.h       |    9 ++-
 .../staging/intel_sst/intel_sst_drv_interface.c    |    2 +
 drivers/staging/intel_sst/intel_sst_dsp.c          |   14 +++-
 drivers/staging/intel_sst/intel_sst_fw_ipc.h       |    6 ++
 drivers/staging/intel_sst/intel_sst_ipc.c          |   56 ++++++++++++++++-
 drivers/staging/intel_sst/intel_sst_stream.c       |   11 ++-
 .../staging/intel_sst/intel_sst_stream_encoded.c   |    8 +-
 drivers/staging/intel_sst/intelmid.c               |    2 -
 9 files changed, 148 insertions(+), 27 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
index 81c24d1..2f21f42 100644
--- a/drivers/staging/intel_sst/intel_sst.c
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -316,9 +316,25 @@ static int __devinit intel_sst_probe(struct pci_dev *pci,
 	if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
 		ret = misc_register(&lpe_dev);
 		if (ret) {
- 			pr_err("couldn't register misc driver\n");
+			pr_err("couldn't register LPE device\n");
 			goto do_free_misc;
  		}
+	} else if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
+		u32 csr;
+
+		/*allocate mem for fw context save during suspend*/
+		sst_drv_ctx->fw_cntx = kzalloc(FW_CONTEXT_MEM, GFP_KERNEL);
+		if (!sst_drv_ctx->fw_cntx) {
+			ret = -ENOMEM;
+			goto do_free_misc;
+		}
+		/*setting zero as that is valid mem to restore*/
+		sst_drv_ctx->fw_cntx_size = 0;
+
+		/*set lpe start clock and ram size*/
+		csr = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+		csr |= 0x30060; /*remove the clock ratio after fw fix*/
+		sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr);
 	}
 	sst_drv_ctx->lpe_stalled = 0;
 	pm_runtime_set_active(&pci->dev);
@@ -374,16 +390,17 @@ static void __devexit intel_sst_remove(struct pci_dev *pci)
 	sst_drv_ctx->sst_state = SST_UN_INIT;
 	mutex_unlock(&sst_drv_ctx->sst_lock);
 	misc_deregister(&lpe_ctrl);
-	if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
-		misc_deregister(&lpe_dev);
 	free_irq(pci->irq, sst_drv_ctx);
 	iounmap(sst_drv_ctx->dram);
 	iounmap(sst_drv_ctx->iram);
 	iounmap(sst_drv_ctx->mailbox);
 	iounmap(sst_drv_ctx->shim);
 	sst_drv_ctx->pmic_state = SND_MAD_UN_INIT;
-	if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID)
+	if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
+		misc_deregister(&lpe_dev);
 		kfree(sst_drv_ctx->mmap_mem);
+	} else
+		kfree(sst_drv_ctx->fw_cntx);
 	flush_scheduled_work();
 	destroy_workqueue(sst_drv_ctx->process_reply_wq);
 	destroy_workqueue(sst_drv_ctx->process_msg_wq);
@@ -398,6 +415,46 @@ static void __devexit intel_sst_remove(struct pci_dev *pci)
 	pci_set_drvdata(pci, NULL);
 }
 
+void sst_save_dsp_context(void)
+{
+	struct snd_sst_ctxt_params fw_context;
+	unsigned int pvt_id, i;
+	struct ipc_post *msg = NULL;
+
+	/*check cpu type*/
+	if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID)
+		return;
+		/*not supported for rest*/
+	if (sst_drv_ctx->sst_state != SST_FW_RUNNING) {
+		pr_debug("fw not running no context save ...\n");
+		return;
+	}
+
+	/*send msg to fw*/
+	if (sst_create_large_msg(&msg))
+		return;
+	pvt_id = sst_assign_pvt_id(sst_drv_ctx);
+	i = sst_get_block_stream(sst_drv_ctx);
+	sst_drv_ctx->alloc_block[i].sst_id = pvt_id;
+	sst_fill_header(&msg->header, IPC_IA_GET_FW_CTXT, 1, pvt_id);
+	msg->header.part.data = sizeof(fw_context) + sizeof(u32);
+	fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx);
+	fw_context.size = FW_CONTEXT_MEM;
+	memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
+	memcpy(msg->mailbox_data + sizeof(u32),
+				&fw_context, sizeof(fw_context));
+	spin_lock(&sst_drv_ctx->list_spin_lock);
+	list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
+	spin_unlock(&sst_drv_ctx->list_spin_lock);
+	sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
+	/*wait for reply*/
+	if (sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]))
+		pr_debug("err fw context save timeout  ...\n");
+	sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT;
+	pr_debug("fw context saved  ...\n");
+	return;
+}
+
 /* Power Management */
 /*
 * intel_sst_suspend - PCI suspend function
@@ -417,6 +474,8 @@ int intel_sst_suspend(struct pci_dev *pci, pm_message_t state)
 		pr_err("active streams,not able to suspend\n");
 		return -EBUSY;
 	}
+	/*save fw context*/
+	sst_save_dsp_context();
 	/*Assert RESET on LPE Processor*/
 	csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
 	csr.full = csr.full | 0x2;
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
index 0a60e86..0f48838 100644
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -28,8 +28,8 @@
  *  Common private declarations for SST
  */
 
-#define SST_DRIVER_VERSION "1.2.09"
-#define SST_VERSION_NUM 0x1209
+#define SST_DRIVER_VERSION "1.2.11"
+#define SST_VERSION_NUM 0x1211
 
 /* driver names */
 #define SST_DRV_NAME "intel_sst_driver"
@@ -37,6 +37,7 @@
 #define SST_MFLD_PCI_ID 0x082F
 #define PCI_ID_LENGTH 4
 #define SST_SUSPEND_DELAY 2000
+#define FW_CONTEXT_MEM (64*1024)
 
 enum sst_states {
 	SST_FW_LOADED = 1,
@@ -94,7 +95,7 @@ enum sst_ram_type {
 /* SST shim registers to structure mapping  */
 union config_status_reg {
 	struct {
-		u32 rsvd0:1;
+		u32 mfld_strb:1;
 		u32 sst_reset:1;
 		u32 hw_rsvd:3;
 		u32 sst_clk:2;
@@ -417,6 +418,8 @@ struct intel_sst_drv {
 	unsigned int		audio_start;
 	dev_t			devt_d, devt_c;
 	unsigned int		max_streams;
+	unsigned int		*fw_cntx;
+	unsigned int		fw_cntx_size;
 };
 
 extern struct intel_sst_drv *sst_drv_ctx;
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
index 971588c..78ee44d 100644
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -508,6 +508,7 @@ int register_sst_card(struct intel_sst_card_ops *card)
 			sst_drv_ctx->pmic_state = SND_MAD_INIT_DONE;
 			sst_drv_ctx->rx_time_slot_status = 0; /*default AMIC*/
 			card->pcm_control = sst_pmic_ops.pcm_control;
+			sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
 			return 0;
 		} else {
 			pr_err("strcmp fail %s\n", card->module_name);
@@ -519,6 +520,7 @@ int register_sst_card(struct intel_sst_card_ops *card)
 		pr_err("Repeat for registration..denied\n");
 		return -EBADRQC;
 	}
+	sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(register_sst_card);
diff --git a/drivers/staging/intel_sst/intel_sst_dsp.c b/drivers/staging/intel_sst/intel_sst_dsp.c
index bffe4c6..a89e1ad 100644
--- a/drivers/staging/intel_sst/intel_sst_dsp.c
+++ b/drivers/staging/intel_sst/intel_sst_dsp.c
@@ -73,7 +73,8 @@ static int intel_sst_reset_dsp_medfield(void)
 	union config_status_reg csr;
 
 	pr_debug("Resetting the DSP in medfield\n");
-	csr.full = 0x048303E2;
+	csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+	csr.full |= 0x382;
 	sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
 
 	return 0;
@@ -109,11 +110,16 @@ static int sst_start_medfield(void)
 {
 	union config_status_reg csr;
 
-	csr.full = 0x04830062;
+	csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+	csr.part.bypass = 0;
 	sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-	csr.full = 0x04830063;
+	csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+	csr.part.mfld_strb = 1;
 	sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-	csr.full = 0x04830061;
+	csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+	csr.part.run_stall = 0;
+	csr.part.sst_reset = 0;
+	pr_debug("Starting the DSP_medfld %x\n", csr.full);
 	sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
 	pr_debug("Starting the DSP_medfld\n");
 
diff --git a/drivers/staging/intel_sst/intel_sst_fw_ipc.h b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
index 0f0c5bb..8628a8a 100644
--- a/drivers/staging/intel_sst/intel_sst_fw_ipc.h
+++ b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
@@ -56,6 +56,8 @@
 #define IPC_IA_GET_FW_VERSION 0x04
 #define IPC_IA_GET_FW_BUILD_INF 0x05
 #define IPC_IA_GET_FW_INFO 0x06
+#define IPC_IA_GET_FW_CTXT 0x07
+#define IPC_IA_SET_FW_CTXT 0x08
 
 /* I2L Codec Config/control msgs */
 #define IPC_IA_SET_CODEC_PARAMS 0x10
@@ -406,4 +408,8 @@ struct ipc_post {
 	char *mailbox_data;
 };
 
+struct snd_sst_ctxt_params {
+	u32 address; /* Physical Address in DDR where the context is stored */
+	u32 size; /* size of the context */
+};
 #endif /* __INTEL_SST_FW_IPC_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_ipc.c b/drivers/staging/intel_sst/intel_sst_ipc.c
index 0742dde..878b19d 100644
--- a/drivers/staging/intel_sst/intel_sst_ipc.c
+++ b/drivers/staging/intel_sst/intel_sst_ipc.c
@@ -154,6 +154,37 @@ void sst_clear_interrupt(void)
 	sst_shim_write(sst_drv_ctx->shim, SST_IMRX, imr.full);
 }
 
+void sst_restore_fw_context(void)
+{
+	struct snd_sst_ctxt_params fw_context;
+	struct ipc_post *msg = NULL;
+
+	pr_debug("restore_fw_context\n");
+	/*check cpu type*/
+	if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID)
+		return;
+		/*not supported for rest*/
+	if (!sst_drv_ctx->fw_cntx_size)
+		return;
+		/*nothing to restore*/
+	pr_debug("restoring context......\n");
+	/*send msg to fw*/
+	if (sst_create_large_msg(&msg))
+		return;
+
+	sst_fill_header(&msg->header, IPC_IA_SET_FW_CTXT, 1, 0);
+	msg->header.part.data = sizeof(fw_context) + sizeof(u32);
+	fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx);
+	fw_context.size = sst_drv_ctx->fw_cntx_size;
+	memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
+	memcpy(msg->mailbox_data + sizeof(u32),
+				&fw_context, sizeof(fw_context));
+	spin_lock(&sst_drv_ctx->list_spin_lock);
+	list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
+	spin_unlock(&sst_drv_ctx->list_spin_lock);
+	sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
+	return;
+}
 /*
  * process_fw_init - process the FW init msg
  *
@@ -184,13 +215,13 @@ int process_fw_init(struct sst_ipc_msg_wq *msg)
 	sst_drv_ctx->sst_state = SST_FW_RUNNING;
 	sst_drv_ctx->lpe_stalled = 0;
 	mutex_unlock(&sst_drv_ctx->sst_lock);
-	pr_debug("FW Version %x.%x\n",
-			init->fw_version.major, init->fw_version.minor);
-	pr_debug("Build No %x Type %x\n",
-			init->fw_version.build, init->fw_version.type);
+	pr_debug("FW Version %02x.%02x.%02x\n", init->fw_version.major,
+			init->fw_version.minor, init->fw_version.build);
+	pr_debug("Build Type %x\n", init->fw_version.type);
 	pr_debug(" Build date %s Time %s\n",
 			init->build_info.date, init->build_info.time);
 	sst_wake_up_alloc_block(sst_drv_ctx, FW_DWNL_ID, retval, NULL);
+	sst_restore_fw_context();
 	return retval;
 }
 /**
@@ -615,12 +646,18 @@ void sst_process_reply(struct work_struct *work)
 		break;
 
 	case IPC_IA_FREE_STREAM:
+		str_info = &sst_drv_ctx->streams[str_id];
 		if (!msg->header.part.data) {
 			pr_debug("Stream %d freed\n", str_id);
 		} else {
 			pr_err("Free for %d ret error %x\n",
 				       str_id, msg->header.part.data);
 		}
+		if (str_info->ctrl_blk.on == true) {
+			str_info->ctrl_blk.on = false;
+			str_info->ctrl_blk.condition = true;
+			wake_up(&sst_drv_ctx->wait_queue);
+		}
 		break;
 	case IPC_IA_ALLOC_STREAM: {
 		/* map to stream, call play */
@@ -699,6 +736,17 @@ void sst_process_reply(struct work_struct *work)
 	case IPC_IA_START_STREAM:
 		pr_debug("reply for START STREAM %x\n", msg->header.full);
 		break;
+
+	case IPC_IA_GET_FW_CTXT:
+		pr_debug("reply for get fw ctxt  %x\n", msg->header.full);
+		if (msg->header.part.data)
+			sst_drv_ctx->fw_cntx_size = 0;
+		else
+			sst_drv_ctx->fw_cntx_size = *sst_drv_ctx->fw_cntx;
+		pr_debug("fw copied data %x\n", sst_drv_ctx->fw_cntx_size);
+		sst_wake_up_alloc_block(
+			sst_drv_ctx, str_id, msg->header.part.data, NULL);
+		break;
 	default:
 		/* Illegal case */
 		pr_err("process reply:default = %x\n", msg->header.full);
diff --git a/drivers/staging/intel_sst/intel_sst_stream.c b/drivers/staging/intel_sst/intel_sst_stream.c
index dd58be5..55a561c 100644
--- a/drivers/staging/intel_sst/intel_sst_stream.c
+++ b/drivers/staging/intel_sst/intel_sst_stream.c
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/firmware.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 #include "intel_sst_ioctl.h"
 #include "intel_sst.h"
 #include "intel_sst_fw_ipc.h"
@@ -519,10 +520,6 @@ int sst_drain_stream(int str_id)
 	str_info->data_blk.on = true;
 	retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
 	str_info->need_draining = false;
-	if (retval == -SST_ERR_INVALID_STREAM_ID) {
-		retval = -EINVAL;
-		sst_clean_stream(str_info);
-	}
 	return retval;
 }
 
@@ -563,6 +560,12 @@ int sst_free_stream(int str_id)
 			str_info->data_blk.ret_code = 0;
 			wake_up(&sst_drv_ctx->wait_queue);
 		}
+		str_info->data_blk.on = true;
+		str_info->data_blk.condition = false;
+		retval = sst_wait_interruptible_timeout(sst_drv_ctx,
+				&str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
+		pr_debug("wait for free returned %d\n", retval);
+		msleep(100);
 		mutex_lock(&sst_drv_ctx->stream_lock);
 		sst_clean_stream(str_info);
 		mutex_unlock(&sst_drv_ctx->stream_lock);
diff --git a/drivers/staging/intel_sst/intel_sst_stream_encoded.c b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
index d5f07b8..2be58c5 100644
--- a/drivers/staging/intel_sst/intel_sst_stream_encoded.c
+++ b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
@@ -363,7 +363,6 @@ int sst_parse_target(struct snd_sst_slot_info *slot)
 				pr_err("SST_Activate_target_fail\n");
 			else
 				pr_err("SST_Activate_target_pass\n");
-		return retval;
 	} else if (slot->action == SND_SST_PORT_PREPARE &&
 			slot->device_type == SND_SST_DEVICE_PCM) {
 				retval = sst_prepare_target(slot);
@@ -371,12 +370,11 @@ int sst_parse_target(struct snd_sst_slot_info *slot)
 				pr_err("SST_prepare_target_fail\n");
 			else
 				pr_err("SST_prepare_target_pass\n");
-			return retval;
 	} else {
 		pr_err("slot_action : %d, device_type: %d\n",
 				slot->action, slot->device_type);
-		return retval;
 	}
+	return retval;
 }
 
 int sst_send_target(struct snd_sst_target_device *target)
@@ -886,8 +884,7 @@ static int sst_prepare_input_buffers_rar(struct stream_info *str_info,
 			int *input_index, int *in_copied,
 			int *input_index_valid_size, int *new_entry_flag)
 {
-	int retval = 0;
-	int i;
+	int retval = 0, i;
 
 	if (str_info->ops == STREAM_OPS_PLAYBACK_DRM) {
 		struct RAR_buffer rar_buffers;
@@ -924,7 +921,6 @@ static int sst_prepare_input_buffers_rar(struct stream_info *str_info,
 	return retval;
 }
 #endif
-
 /*This function is used to prepare the kernel input buffers with contents
 before sending for decode*/
 static int sst_prepare_input_buffers(struct stream_info *str_info,
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index ebb6d03..0925a88 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -805,8 +805,6 @@ static int __devinit snd_intelmad_sst_register(
 		pr_err("sst card registration failed\n");
 		return ret_val;
 	}
-	sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
-
 	sst_card_vendor_id = intelmaddata->sstdrv_ops->vendor_id;
 	intelmaddata->pmic_status = PMIC_UNINIT;
 	return ret_val;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 02/23] intel_sst: MSIC codec power optimisation
  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 16:32 ` Alan Cox
  2011-05-03 16:58   ` Mark Brown
  2011-05-03 16:32 ` [PATCH 03/23] intel_sst: fix unload bugs Alan Cox
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:32 UTC (permalink / raw)
  To: greg, linux-kernel

From: Vinod Koul <vinod.koul@intel.com>

This patch adds power optimization for the msic codec and ensure
codec is completely powered off when codec is idle.

Signed-off-by: Vinod Koul <vinod.koul@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 
 .../staging/intel_sst/intel_sst_drv_interface.c    |   10 -
 drivers/staging/intel_sst/intelmid_msic_control.c  |  275 ++++++++++++++------
 drivers/staging/intel_sst/intelmid_v0_control.c    |    4 
 drivers/staging/intel_sst/intelmid_v1_control.c    |    4 
 drivers/staging/intel_sst/intelmid_v2_control.c    |    4 
 6 files changed, 201 insertions(+), 100 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
index cb03ff7..bf0f9e2 100644
--- a/drivers/staging/intel_sst/intel_sst.h
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -103,8 +103,8 @@ struct snd_pmic_ops {
 
 	int (*power_up_pmic_pb) (unsigned int port);
 	int (*power_up_pmic_cp) (unsigned int port);
-	int (*power_down_pmic_pb) (void);
-	int (*power_down_pmic_cp) (void);
+	int (*power_down_pmic_pb) (unsigned int device);
+	int (*power_down_pmic_cp) (unsigned int device);
 	int (*power_down_pmic) (void);
 };
 
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
index 78ee44d..a47e382 100644
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -105,21 +105,23 @@ void free_stream_context(unsigned int str_id)
 	if (!sst_validate_strid(str_id)) {
 		/* str_id is valid, so stream is alloacted */
 		stream = &sst_drv_ctx->streams[str_id];
+		if (sst_free_stream(str_id))
+			sst_clean_stream(&sst_drv_ctx->streams[str_id]);
 		if (stream->ops == STREAM_OPS_PLAYBACK ||
 				stream->ops == STREAM_OPS_PLAYBACK_DRM) {
 			sst_drv_ctx->pb_streams--;
 			if (sst_drv_ctx->pb_streams == 0)
-				sst_drv_ctx->scard_ops->power_down_pmic_pb();
+				sst_drv_ctx->scard_ops->power_down_pmic_pb(
+						stream->device);
 		} else if (stream->ops == STREAM_OPS_CAPTURE) {
 			sst_drv_ctx->cp_streams--;
 			if (sst_drv_ctx->cp_streams == 0)
-				sst_drv_ctx->scard_ops->power_down_pmic_cp();
+				sst_drv_ctx->scard_ops->power_down_pmic_cp(
+						stream->device);
 		}
 		if (sst_drv_ctx->pb_streams == 0
 				&& sst_drv_ctx->cp_streams == 0)
 			sst_drv_ctx->scard_ops->power_down_pmic();
-		if (sst_free_stream(str_id))
-			sst_clean_stream(&sst_drv_ctx->streams[str_id]);
 	}
 }
 
diff --git a/drivers/staging/intel_sst/intelmid_msic_control.c b/drivers/staging/intel_sst/intelmid_msic_control.c
index da093ed..bbe9ab2 100644
--- a/drivers/staging/intel_sst/intelmid_msic_control.c
+++ b/drivers/staging/intel_sst/intelmid_msic_control.c
@@ -28,8 +28,8 @@
 
 #include <linux/pci.h>
 #include <linux/file.h>
+#include <linux/delay.h>
 #include "intel_sst.h"
-#include "intel_sst_ioctl.h"
 #include "intelmid_snd_control.h"
 
 static int msic_init_card(void)
@@ -64,17 +64,17 @@ static int msic_init_card(void)
 		{0x27B, 0x01, 0},
 		{0x27C, 0x0a, 0},
 		/* Set vol HSLRVOLCTRL, IHFVOL */
-		{0x259, 0x04, 0},
-		{0x25A, 0x04, 0},
-		{0x25B, 0x04, 0},
-		{0x25C, 0x04, 0},
+		{0x259, 0x08, 0},
+		{0x25A, 0x08, 0},
+		{0x25B, 0x08, 0},
+		{0x25C, 0x08, 0},
 		/* HSEPRXCTRL  Enable the headset left and right FIR filters  */
 		{0x250, 0x30, 0},
 		/* HSMIXER */
 		{0x256, 0x11, 0},
 		/* amic configuration */
-		{0x249, 0x09, 0x0},
-		{0x24A, 0x09, 0x0},
+		{0x249, 0x01, 0x0},
+		{0x24A, 0x01, 0x0},
 		/* unmask ocaudio/accdet interrupts */
 		{0x1d, 0x00, 0x00},
 		{0x1e, 0x00, 0x00},
@@ -91,79 +91,84 @@ static int msic_init_card(void)
 
 static int msic_power_up_pb(unsigned int device)
 {
-	struct sc_reg_access sc_access1[] = {
+	struct sc_reg_access vaud[] = {
 		/* turn on the audio power supplies */
-		{0x0DB, 0x05, 0},
+		{0x0DB, 0x07, 0},
+	};
+	struct sc_reg_access pll[] = {
+		/* turn on PLL */
+		{0x240, 0x20, 0},
+	};
+	struct sc_reg_access vhs[] = {
 		/*  VHSP */
 		{0x0DC, 0xFF, 0},
 		/*  VHSN */
 		{0x0DD, 0x3F, 0},
-		/* turn on PLL */
-		{0x240, 0x21, 0},
 	};
-	struct sc_reg_access sc_access2[] = {
+	struct sc_reg_access hsdac[] = {
 		/*  disable driver */
 		{0x25D, 0x0, 0x43},
 		/* DAC CONFIG ; both HP, LP on */
 		{0x257, 0x03, 0x03},
 	};
-	struct sc_reg_access sc_access3[] = {
+	struct sc_reg_access hs_filter[] = {
 		/* HSEPRXCTRL  Enable the headset left and right FIR filters  */
 		{0x250, 0x30, 0},
 		/* HSMIXER */
 		{0x256, 0x11, 0},
 	};
-	struct sc_reg_access sc_access4[] = {
+	struct sc_reg_access hs_enable[] = {
 		/* enable driver */
 		{0x25D, 0x3, 0x3},
+		{0x26C, 0x0, 0x2},
 		/* unmute the headset */
 		{ 0x259, 0x80, 0x80},
 		{ 0x25A, 0x80, 0x80},
 	};
-	struct sc_reg_access sc_access_vihf[] = {
+	struct sc_reg_access vihf[] = {
 		/*  VIHF ON */
-		{0x0C9, 0x2D, 0x00},
+		{0x0C9, 0x27, 0x00},
 	};
-	struct sc_reg_access sc_access22[] = {
+	struct sc_reg_access ihf_filter[] = {
 		/*  disable driver */
 		{0x25D, 0x00, 0x0C},
 		/*Filer DAC enable*/
 		{0x251, 0x03, 0x03},
 		{0x257, 0x0C, 0x0C},
 	};
-	struct sc_reg_access sc_access32[] = {
+	struct sc_reg_access ihf_en[] = {
 		/*enable drv*/
 		{0x25D, 0x0C, 0x0c},
 	};
-	struct sc_reg_access sc_access42[] = {
+	struct sc_reg_access ihf_unmute[] = {
 		/*unmute headset*/
 		{0x25B, 0x80, 0x80},
 		{0x25C, 0x80, 0x80},
 	};
-	struct sc_reg_access sc_access23[] = {
+	struct sc_reg_access epdac[] = {
 		/*  disable driver */
 		{0x25D, 0x0, 0x43},
 		/* DAC CONFIG ; both HP, LP on */
 		{0x257, 0x03, 0x03},
 	};
-	struct sc_reg_access sc_access43[] = {
+	struct sc_reg_access ep_enable[] = {
 		/* enable driver */
 		{0x25D, 0x40, 0x40},
 		/* unmute the headset */
 		{ 0x259, 0x80, 0x80},
 		{ 0x25A, 0x80, 0x80},
 	};
-	struct sc_reg_access sc_access_vib[] = {
+	struct sc_reg_access vib1_en[] = {
 		/* enable driver, ADC */
 		{0x25D, 0x10, 0x10},
 		{0x264, 0x02, 0x02},
 	};
-	struct sc_reg_access sc_access_hap[] = {
+	struct sc_reg_access vib2_en[] = {
 		/* enable driver, ADC */
 		{0x25D, 0x20, 0x20},
 		{0x26A, 0x02, 0x02},
 	};
-	struct sc_reg_access sc_access_pcm2[] = {
+	struct sc_reg_access pcm2_en[] = {
 		/* enable pcm 2 */
 		{0x27C, 0x1, 0x1},
 	};
@@ -176,89 +181,84 @@ static int msic_power_up_pb(unsigned int device)
 	}
 
 	pr_debug("powering up pb.... Device %d\n", device);
-	sst_sc_reg_access(sc_access1, PMIC_WRITE, 4);
+	sst_sc_reg_access(vaud, PMIC_WRITE, 1);
+	msleep(1);
+	sst_sc_reg_access(pll, PMIC_WRITE, 1);
+	msleep(1);
 	switch (device) {
 	case SND_SST_DEVICE_HEADSET:
 		if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) {
-			sst_sc_reg_access(sc_access2, PMIC_READ_MODIFY, 2);
-			sst_sc_reg_access(sc_access3, PMIC_WRITE, 2);
-			sst_sc_reg_access(sc_access4, PMIC_READ_MODIFY, 3);
+			sst_sc_reg_access(vhs, PMIC_WRITE, 2);
+			sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 2);
+			sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
+			sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 4);
 		} else {
-			sst_sc_reg_access(sc_access23, PMIC_READ_MODIFY, 2);
-			sst_sc_reg_access(sc_access3, PMIC_WRITE, 2);
-			sst_sc_reg_access(sc_access43, PMIC_READ_MODIFY, 3);
+			sst_sc_reg_access(epdac, PMIC_READ_MODIFY, 2);
+			sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
+			sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3);
 		}
 		snd_msic_ops.pb_on = 1;
 		break;
 
 	case SND_SST_DEVICE_IHF:
-		sst_sc_reg_access(sc_access_vihf, PMIC_WRITE, 1);
-		sst_sc_reg_access(sc_access22, PMIC_READ_MODIFY, 3);
-		sst_sc_reg_access(sc_access32, PMIC_READ_MODIFY, 1);
-		sst_sc_reg_access(sc_access42, PMIC_READ_MODIFY, 2);
+		sst_sc_reg_access(vihf, PMIC_WRITE, 1);
+		sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3);
+		sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1);
+		sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2);
 		break;
 
 	case SND_SST_DEVICE_VIBRA:
-		sst_sc_reg_access(sc_access_vib, PMIC_READ_MODIFY, 2);
+		sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2);
 		break;
 
 	case SND_SST_DEVICE_HAPTIC:
-		sst_sc_reg_access(sc_access_hap, PMIC_READ_MODIFY, 2);
+		sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2);
 		break;
 
 	default:
 		pr_warn("Wrong Device %d, selected %d\n",
 			       device, snd_msic_ops.output_dev_id);
 	}
-	return sst_sc_reg_access(sc_access_pcm2, PMIC_READ_MODIFY, 1);
+	return sst_sc_reg_access(pcm2_en, PMIC_READ_MODIFY, 1);
 }
 
 static int msic_power_up_cp(unsigned int device)
 {
-	struct sc_reg_access sc_access[] = {
+	struct sc_reg_access vaud[] = {
 		/* turn on the audio power supplies */
-		{0x0DB, 0x05, 0},
-		/*  VHSP */
-		{0x0DC, 0xFF, 0},
-		/*  VHSN */
-		{0x0DD, 0x3F, 0},
+		{0x0DB, 0x07, 0},
+	};
+	struct sc_reg_access pll[] = {
 		/* turn on PLL */
-		{0x240, 0x21, 0},
-
-		/*  Turn on DMIC supply  */
-		{0x247, 0xA0, 0x0},
-		{0x240, 0x21, 0x0},
-		{0x24C, 0x10, 0x0},
-
+		{0x240, 0x20, 0},
+	};
+	struct sc_reg_access dmic_bias[] = {
+		/*  Turn on AMIC supply  */
+		{0x247, 0xA0, 0xA0},
+	};
+	struct sc_reg_access dmic[] = {
 		/* mic demux enable */
-		{0x245, 0x3F, 0x0},
-		{0x246, 0x7, 0x0},
+		{0x245, 0x3F, 0x3F},
+		{0x246, 0x07, 0x07},
 
 	};
-	struct sc_reg_access sc_access_amic[] = {
-		/* turn on the audio power supplies */
-		{0x0DB, 0x05, 0},
-		/*  VHSP */
-		{0x0DC, 0xFF, 0},
-		/*  VHSN */
-		{0x0DD, 0x3F, 0},
-		/* turn on PLL */
-		{0x240, 0x21, 0},
-		/*ADC EN*/
-		{0x248, 0x05, 0x0},
-		{0x24C, 0x76, 0x0},
-		/*MIC EN*/
-		{0x249, 0x09, 0x0},
-		{0x24A, 0x09, 0x0},
+	struct sc_reg_access amic_bias[] = {
 		/*  Turn on AMIC supply  */
-		{0x247, 0xFC, 0x0},
+		{0x247, 0xFC, 0xFC},
+	};
+	struct sc_reg_access amic[] = {
+		/*MIC EN*/
+		{0x249, 0x01, 0x01},
+		{0x24A, 0x01, 0x01},
+		/*ADC EN*/
+		{0x248, 0x05, 0x0F},
 
 	};
-	struct sc_reg_access sc_access2[] = {
+	struct sc_reg_access pcm2[] = {
 		/* enable pcm 2 */
 		{0x27C, 0x1, 0x1},
 	};
-	struct sc_reg_access sc_access3[] = {
+	struct sc_reg_access tx_on[] = {
 		/*wait for mic to stabalize before turning on audio channels*/
 		{0x24F, 0x3C, 0x0},
 	};
@@ -271,42 +271,141 @@ static int msic_power_up_cp(unsigned int device)
 	}
 
 	pr_debug("powering up cp....%d\n", snd_msic_ops.input_dev_id);
-	sst_sc_reg_access(sc_access2, PMIC_READ_MODIFY, 1);
+	sst_sc_reg_access(vaud, PMIC_WRITE, 1);
+	msleep(500);/*FIXME need optimzed value here*/
+	sst_sc_reg_access(pll, PMIC_WRITE, 1);
+	msleep(1);
 	snd_msic_ops.cap_on = 1;
-	if (snd_msic_ops.input_dev_id == AMIC)
-		sst_sc_reg_access(sc_access_amic, PMIC_WRITE, 9);
-	else
-		sst_sc_reg_access(sc_access, PMIC_WRITE, 9);
-	return sst_sc_reg_access(sc_access3, PMIC_WRITE, 1);
-
+	if (snd_msic_ops.input_dev_id == AMIC) {
+		sst_sc_reg_access(amic_bias, PMIC_READ_MODIFY, 1);
+		msleep(1);
+		sst_sc_reg_access(amic, PMIC_READ_MODIFY, 3);
+	} else {
+		sst_sc_reg_access(dmic_bias, PMIC_READ_MODIFY, 1);
+		msleep(1);
+		sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 2);
+	}
+	msleep(1);
+	sst_sc_reg_access(tx_on, PMIC_WRITE, 1);
+	return sst_sc_reg_access(pcm2, PMIC_READ_MODIFY, 1);
 }
 
 static int msic_power_down(void)
 {
-	int retval = 0;
+	struct sc_reg_access power_dn[] = {
+		/*  VHSP */
+		{0x0DC, 0xC4, 0},
+		/*  VHSN */
+		{0x0DD, 0x04, 0},
+		/*  VIHF */
+		{0x0C9, 0x24, 0},
+	};
+	struct sc_reg_access pll[] = {
+		/* turn off PLL*/
+		{0x240, 0x00, 0x0},
+	};
+	struct sc_reg_access vaud[] = {
+		/* turn off VAUD*/
+		{0x0DB, 0x04, 0},
+	};
 
 	pr_debug("powering dn msic\n");
 	snd_msic_ops.pb_on = 0;
 	snd_msic_ops.cap_on = 0;
-	return retval;
+	sst_sc_reg_access(power_dn, PMIC_WRITE, 3);
+	msleep(1);
+	sst_sc_reg_access(pll, PMIC_WRITE, 1);
+	msleep(1);
+	sst_sc_reg_access(vaud, PMIC_WRITE, 1);
+	return 0;
 }
 
-static int msic_power_down_pb(void)
+static int msic_power_down_pb(unsigned int device)
 {
-	int retval = 0;
+	struct sc_reg_access drv_enable[] = {
+		{0x25D, 0x00, 0x00},
+	};
+	struct sc_reg_access hs_mute[] = {
+		{0x259, 0x80, 0x80},
+		{0x25A, 0x80, 0x80},
+		{0x26C, 0x02, 0x02},
+	};
+	struct sc_reg_access hs_off[] = {
+		{0x257, 0x00, 0x03},
+		{0x250, 0x00, 0x30},
+	};
+	struct sc_reg_access ihf_mute[] = {
+		{0x25B, 0x80, 0x80},
+		{0x25C, 0x80, 0x80},
+	};
+	struct sc_reg_access ihf_off[] = {
+		{0x257, 0x00, 0x0C},
+		{0x251, 0x00, 0x03},
+	};
+	struct sc_reg_access vib1_off[] = {
+		{0x264, 0x00, 0x82},
+	};
+	struct sc_reg_access vib2_off[] = {
+		{0x26A, 0x00, 0x82},
+	};
 
-	pr_debug("powering dn pb....\n");
-	snd_msic_ops.pb_on = 0;
-	return retval;
+	pr_debug("powering dn pb for device %d\n", device);
+	switch (device) {
+	case SND_SST_DEVICE_HEADSET:
+		snd_msic_ops.pb_on = 0;
+		sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3);
+		drv_enable[0].mask = 0x43;
+		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+		sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 2);
+		break;
+
+	case SND_SST_DEVICE_IHF:
+		sst_sc_reg_access(ihf_mute, PMIC_READ_MODIFY, 2);
+		drv_enable[0].mask = 0x0C;
+		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+		sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2);
+		break;
+
+	case SND_SST_DEVICE_VIBRA:
+		sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 2);
+		drv_enable[0].mask = 0x10;
+		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+		break;
+
+	case SND_SST_DEVICE_HAPTIC:
+		sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 2);
+		drv_enable[0].mask = 0x20;
+		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+		break;
+	}
+	return 0;
 }
 
-static int msic_power_down_cp(void)
+static int msic_power_down_cp(unsigned int device)
 {
-	int retval = 0;
+	struct sc_reg_access dmic[] = {
+		{0x247, 0x00, 0xA0},
+		{0x245, 0x00, 0x38},
+		{0x246, 0x00, 0x07},
+	};
+	struct sc_reg_access amic[] = {
+		{0x248, 0x00, 0x05},
+		{0x249, 0x00, 0x01},
+		{0x24A, 0x00, 0x01},
+		{0x247, 0x00, 0xA3},
+	};
+	struct sc_reg_access tx_off[] = {
+		{0x24F, 0x00, 0x3C},
+	};
 
 	pr_debug("powering dn cp....\n");
 	snd_msic_ops.cap_on = 0;
-	return retval;
+	sst_sc_reg_access(tx_off, PMIC_READ_MODIFY, 1);
+	if (snd_msic_ops.input_dev_id == DMIC)
+		sst_sc_reg_access(dmic, PMIC_READ_MODIFY, 3);
+	else
+		sst_sc_reg_access(amic, PMIC_READ_MODIFY, 4);
+	return 0;
 }
 
 static int msic_set_selected_output_dev(u8 value)
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
index 7756f8f..6cf5901 100644
--- a/drivers/staging/intel_sst/intelmid_v0_control.c
+++ b/drivers/staging/intel_sst/intelmid_v0_control.c
@@ -157,7 +157,7 @@ static int fs_power_up_pb(unsigned int port)
 	return fs_enable_audiodac(UNMUTE);
 }
 
-static int fs_power_down_pb(void)
+static int fs_power_down_pb(unsigned int device)
 {
 	struct sc_reg_access sc_access[] = {
 		{POWERCTRL1, 0x00, 0xC6},
@@ -195,7 +195,7 @@ static int fs_power_up_cp(unsigned int port)
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
 }
 
-static int fs_power_down_cp(void)
+static int fs_power_down_cp(unsigned int device)
 {
 	struct sc_reg_access sc_access[] = {
 		{POWERCTRL2, 0x00, 0x03},
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c
index 1ea8142..445e0fb 100644
--- a/drivers/staging/intel_sst/intelmid_v1_control.c
+++ b/drivers/staging/intel_sst/intelmid_v1_control.c
@@ -212,7 +212,7 @@ static int mx_power_up_pb(unsigned int port)
 	return mx_enable_audiodac(UNMUTE);
 }
 
-static int mx_power_down_pb(void)
+static int mx_power_down_pb(unsigned int device)
 {
 	struct sc_reg_access sc_access[3];
 	int retval = 0;
@@ -255,7 +255,7 @@ static int mx_power_up_cp(unsigned int port)
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2);
 }
 
-static int mx_power_down_cp(void)
+static int mx_power_down_cp(unsigned int device)
 {
 	struct sc_reg_access sc_access[] = {
 		{ENABLE_OPDEV_CTRL, 0x00, MASK1|MASK0},
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 3c6b3ab..28754a5 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -316,7 +316,7 @@ static int nc_power_down(void)
 	return nc_enable_audiodac(UNMUTE);
 }
 
-static int nc_power_down_pb(void)
+static int nc_power_down_pb(unsigned int device)
 {
 
 	int retval = 0;
@@ -360,7 +360,7 @@ static int nc_power_down_pb(void)
 
 }
 
-static int nc_power_down_cp(void)
+static int nc_power_down_cp(unsigned int device)
 {
 	struct sc_reg_access sc_access[] = {
 		{POWERCTRL1, 0x00, 0xBE},


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 03/23] intel_sst: fix unload bugs
  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 16:32 ` [PATCH 02/23] intel_sst: MSIC codec power optimisation Alan Cox
@ 2011-05-03 16:32 ` Alan Cox
  2011-05-03 16:32 ` [PATCH 04/23] intel_sst: ignore IRQ when suspended Alan Cox
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:32 UTC (permalink / raw)
  To: greg, linux-kernel

From: Vinod Koul <vinod.koul@intel.com>

The current driver remove was erroneous and causes
errors when unloading or loading second time

This patch fixes both of these issues

Signed-off-by: Vinod Koul <vinod.koul@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.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
index 2f21f42..c40e00a 100644
--- a/drivers/staging/intel_sst/intel_sst.c
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -371,7 +371,8 @@ free_mad_wq:
 	destroy_workqueue(sst_drv_ctx->mad_wq);
 do_free_drv_ctx:
 	kfree(sst_drv_ctx);
-	pr_err("Probe failed with 0x%x\n", ret);
+	sst_drv_ctx = NULL;
+	pr_err("Probe failed with %d\n", ret);
 	return ret;
 }
 
@@ -407,11 +408,9 @@ static void __devexit intel_sst_remove(struct pci_dev *pci)
 	destroy_workqueue(sst_drv_ctx->post_msg_wq);
 	destroy_workqueue(sst_drv_ctx->mad_wq);
 	kfree(sst_drv_ctx);
-	pci_release_region(pci, 1);
-	pci_release_region(pci, 2);
-	pci_release_region(pci, 3);
-	pci_release_region(pci, 4);
-	pci_release_region(pci, 5);
+	sst_drv_ctx = NULL;
+	pci_release_regions(pci);
+	pci_disable_device(pci);
 	pci_set_drvdata(pci, NULL);
 }
 
@@ -604,6 +603,7 @@ static void __exit intel_sst_exit(void)
 	pci_unregister_driver(&driver);
 
 	pr_debug("driver unloaded\n");
+	sst_drv_ctx = NULL;
 	return;
 }
 


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 04/23] intel_sst: ignore IRQ when suspended
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (2 preceding siblings ...)
  2011-05-03 16:32 ` [PATCH 03/23] intel_sst: fix unload bugs Alan Cox
@ 2011-05-03 16:32 ` Alan Cox
  2011-05-03 16:32 ` [PATCH 05/23] intel_sst: Line out support Alan Cox
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:32 UTC (permalink / raw)
  To: greg, linux-kernel

From: Vinod Koul <vinod.koul@intel.com>

The irq for audio is shared, so when device is supended driver should
not the read register and ignore the interrupt.

This patch ignores interrupts when device is suspended.

Signed-off-by: Vinod Koul <vinod.koul@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.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
index c40e00a..e7c2617 100644
--- a/drivers/staging/intel_sst/intel_sst.c
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -107,6 +107,9 @@ static irqreturn_t intel_sst_interrupt(int irq, void *context)
 	unsigned int size = 0, str_id;
 	struct stream_info *stream ;
 
+	/* Do not handle interrupt in suspended state */
+	if (drv->sst_state == SST_SUSPENDED)
+		return IRQ_NONE;
 	/* Interrupt arrived, check src */
 	isr.full = sst_shim_read(drv->shim, SST_ISRX);
 


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 05/23] intel_sst: Line out support
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (3 preceding siblings ...)
  2011-05-03 16:32 ` [PATCH 04/23] intel_sst: ignore IRQ when suspended Alan Cox
@ 2011-05-03 16:32 ` Alan Cox
  2011-05-03 16:32 ` [PATCH 06/23] intel_sst: parameter tuning ioctl Alan Cox
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:32 UTC (permalink / raw)
  To: greg, linux-kernel

From: Dharageswari R <dharageswari.r@intel.com>

This patch adds the support for lineout. The
lineout input can be selected as any input channel
by using a new alsa mixer kcontrol.

Signed-off-by: Dharageswari R <dharageswari.r@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              |    6 
 drivers/staging/intel_sst/intel_sst_common.h       |    4 
 .../staging/intel_sst/intel_sst_drv_interface.c    |    7 -
 drivers/staging/intel_sst/intel_sst_stream.c       |    2 
 drivers/staging/intel_sst/intelmid.c               |    3 
 drivers/staging/intel_sst/intelmid.h               |    8 -
 drivers/staging/intel_sst/intelmid_ctrl.c          |   46 +++-
 drivers/staging/intel_sst/intelmid_msic_control.c  |  254 +++++++++++++++++++-
 drivers/staging/intel_sst/intelmid_snd_control.h   |    7 +
 drivers/staging/intel_sst/intelmid_v0_control.c    |    6 
 drivers/staging/intel_sst/intelmid_v1_control.c    |    5 
 drivers/staging/intel_sst/intelmid_v2_control.c    |    6 
 12 files changed, 330 insertions(+), 24 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
index bf0f9e2..ea6cd97 100644
--- a/drivers/staging/intel_sst/intel_sst.h
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -82,12 +82,14 @@ struct snd_pmic_ops {
 	int num_channel;
 	int input_dev_id;
 	int mute_status;
-	int pb_on;
+	int pb_on, pbhs_on;
 	int cap_on;
 	int output_dev_id;
+	int lineout_dev_id, line_out_names_cnt;
+	int prev_lineout_dev_id;
 	int (*set_input_dev) (u8 value);
 	int (*set_output_dev) (u8 value);
-
+	int (*set_lineout_dev) (u8 value);
 	int (*set_mute) (int dev_id, u8 value);
 	int (*get_mute) (int dev_id, u8 *value);
 
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
index 0f48838..9aff1a3 100644
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -28,8 +28,8 @@
  *  Common private declarations for SST
  */
 
-#define SST_DRIVER_VERSION "1.2.11"
-#define SST_VERSION_NUM 0x1211
+#define SST_DRIVER_VERSION "1.2.14"
+#define SST_VERSION_NUM 0x1214
 
 /* driver names */
 #define SST_DRV_NAME "intel_sst_driver"
diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
index a47e382..1e8c056 100644
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -110,9 +110,14 @@ void free_stream_context(unsigned int str_id)
 		if (stream->ops == STREAM_OPS_PLAYBACK ||
 				stream->ops == STREAM_OPS_PLAYBACK_DRM) {
 			sst_drv_ctx->pb_streams--;
-			if (sst_drv_ctx->pb_streams == 0)
+			if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID)
 				sst_drv_ctx->scard_ops->power_down_pmic_pb(
 						stream->device);
+			else {
+				if (sst_drv_ctx->pb_streams == 0)
+					sst_drv_ctx->scard_ops->
+					power_down_pmic_pb(stream->device);
+			}
 		} else if (stream->ops == STREAM_OPS_CAPTURE) {
 			sst_drv_ctx->cp_streams--;
 			if (sst_drv_ctx->cp_streams == 0)
diff --git a/drivers/staging/intel_sst/intel_sst_stream.c b/drivers/staging/intel_sst/intel_sst_stream.c
index 55a561c..dd9c530 100644
--- a/drivers/staging/intel_sst/intel_sst_stream.c
+++ b/drivers/staging/intel_sst/intel_sst_stream.c
@@ -73,6 +73,8 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
 			*pcm_slot = 0x07;
 		else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4)
 			*pcm_slot = 0x0F;
+		else if (device == SND_SST_DEVICE_CAPTURE && num_chan > 4)
+			*pcm_slot = 0x1F;
 		else {
 			pr_debug("No condition satisfied.. ret err\n");
 			return -EINVAL;
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index 0925a88..ee070e3 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -187,7 +187,7 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream)
 		return ret_val;
 	}
 
-	 ret_val = snd_intelmad_alloc_stream(substream);
+	ret_val = snd_intelmad_alloc_stream(substream);
 	if (ret_val < 0)
 		return ret_val;
 	stream->dbg_cum_bytes = 0;
@@ -797,6 +797,7 @@ static int __devinit snd_intelmad_sst_register(
 		intelmaddata->sstdrv_ops->scard_ops->input_dev_id = DMIC;
 		intelmaddata->sstdrv_ops->scard_ops->output_dev_id =
 							STEREO_HEADPHONE;
+		intelmaddata->sstdrv_ops->scard_ops->lineout_dev_id = NONE;
 	}
 
 	/* registering with SST driver to get access to SST APIs to use */
diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
index e77da87..4ed4a94 100644
--- a/drivers/staging/intel_sst/intelmid.h
+++ b/drivers/staging/intel_sst/intelmid.h
@@ -53,11 +53,11 @@
 #define STEREO_CNTL		2
 #define MIN_CHANNEL		1
 #define MAX_CHANNEL_AMIC	2
-#define MAX_CHANNEL_DMIC	4
+#define MAX_CHANNEL_DMIC	5
 #define FIFO_SIZE		0 /* fifo not being used */
 #define INTEL_MAD		"Intel MAD"
 #define MAX_CTRL_MRST		7
-#define MAX_CTRL_MFLD		2
+#define MAX_CTRL_MFLD		3
 #define MAX_CTRL		7
 #define MAX_VENDORS		4
 /* TODO +6 db */
@@ -116,6 +116,7 @@ struct snd_intelmad {
 	void __iomem *int_base;
 	int output_sel;
 	int input_sel;
+	int lineout_sel;
 	int master_mute;
 	struct mad_jack jack[4];
 	int playback_cnt;
@@ -163,6 +164,9 @@ enum _widget_ctrl {
 	CAPTURE_MUTE,
 	MASTER_MUTE
 };
+enum _widget_ctrl_mfld {
+	LINEOUT_SEL_MFLD = 3,
+};
 
 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 69af070..3036928 100644
--- a/drivers/staging/intel_sst/intelmid_ctrl.c
+++ b/drivers/staging/intel_sst/intelmid_ctrl.c
@@ -40,6 +40,11 @@ static char *out_names_mrst[] = {"Headphones",
 static char *in_names_mrst[] = {"AMIC",
 				"DMIC",
 				"HS_MIC"};
+static char *line_out_names_mfld[] = {"Headset",
+				"IHF    ",
+				"Vibra1 ",
+				"Vibra2 ",
+				"NONE   "};
 static char *out_names_mfld[] = {"Headset ",
 				"EarPiece  "};
 static char *in_names_mfld[] = {"AMIC",
@@ -179,13 +184,27 @@ static int snd_intelmad_device_info_mrst(struct snd_kcontrol *kcontrol,
 static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_info *uinfo)
 {
+	struct snd_pmic_ops *scard_ops;
+	struct snd_intelmad *intelmaddata;
+
 	WARN_ON(!kcontrol);
 	WARN_ON(!uinfo);
+
+	intelmaddata = kcontrol->private_data;
+
+	WARN_ON(!intelmaddata->sstdrv_ops);
+
+	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 	/* setup device select as drop down controls with different values */
 	if (kcontrol->id.numid == OUTPUT_SEL)
 		uinfo->value.enumerated.items = ARRAY_SIZE(out_names_mfld);
-	else
+	else if (kcontrol->id.numid == INPUT_SEL)
 		uinfo->value.enumerated.items = ARRAY_SIZE(in_names_mfld);
+	else if (kcontrol->id.numid == LINEOUT_SEL_MFLD) {
+		uinfo->value.enumerated.items = ARRAY_SIZE(line_out_names_mfld);
+		scard_ops->line_out_names_cnt = uinfo->value.enumerated.items;
+	} else
+		return -EINVAL;
 	uinfo->count = MONO_CNTL;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 
@@ -195,10 +214,16 @@ static int snd_intelmad_device_info_mfld(struct snd_kcontrol *kcontrol,
 		strncpy(uinfo->value.enumerated.name,
 			out_names_mfld[uinfo->value.enumerated.item],
 			sizeof(uinfo->value.enumerated.name)-1);
-	else
+	else if (kcontrol->id.numid == INPUT_SEL)
 		strncpy(uinfo->value.enumerated.name,
 			in_names_mfld[uinfo->value.enumerated.item],
 			sizeof(uinfo->value.enumerated.name)-1);
+	else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
+		strncpy(uinfo->value.enumerated.name,
+			line_out_names_mfld[uinfo->value.enumerated.item],
+			sizeof(uinfo->value.enumerated.name)-1);
+	else
+		return -EINVAL;
 	return 0;
 }
 
@@ -472,6 +497,9 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
 		else if (kcontrol->id.numid == INPUT_SEL)
 			uval->value.enumerated.item[0] =
 					scard_ops->input_dev_id;
+		else if (kcontrol->id.numid == LINEOUT_SEL_MFLD)
+			uval->value.enumerated.item[0] =
+					scard_ops->lineout_dev_id;
 		else
 			return -EINVAL;
 	} else
@@ -534,6 +562,11 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol,
 				uval->value.enumerated.item[0]);
 		intelmaddata->input_sel = uval->value.enumerated.item[0];
 		break;
+	case LINEOUT_SEL_MFLD:
+		ret_val = scard_ops->set_lineout_dev(
+					uval->value.enumerated.item[0]);
+		intelmaddata->lineout_sel = uval->value.enumerated.item[0];
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -627,5 +660,14 @@ snd_intelmad_controls_mfld[MAX_CTRL_MFLD] __devinitdata = {
 	.put		=	snd_intelmad_device_set,
 	.private_value	=	0,
 },
+{
+	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name		=	"Line out",
+	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info		=	snd_intelmad_device_info_mfld,
+	.get		=	snd_intelmad_device_get,
+	.put		=	snd_intelmad_device_set,
+	.private_value	=	0,
+},
 };
 
diff --git a/drivers/staging/intel_sst/intelmid_msic_control.c b/drivers/staging/intel_sst/intelmid_msic_control.c
index bbe9ab2..10073c5 100644
--- a/drivers/staging/intel_sst/intelmid_msic_control.c
+++ b/drivers/staging/intel_sst/intelmid_msic_control.c
@@ -54,11 +54,8 @@ static int msic_init_card(void)
 		/*TI vibra w/a settings*/
 		{0x384, 0x80, 0},
 		{0x385, 0x80, 0},
-		/*vibra settings*/
 		{0x267, 0x00, 0},
-		{0x26A, 0x10, 0},
 		{0x261, 0x00, 0},
-		{0x264, 0x10, 0},
 		/* pcm port setting */
 		{0x278, 0x00, 0},
 		{0x27B, 0x01, 0},
@@ -80,14 +77,221 @@ static int msic_init_card(void)
 		{0x1e, 0x00, 0x00},
 	};
 	snd_msic_ops.card_status = SND_CARD_INIT_DONE;
-	sst_sc_reg_access(sc_access, PMIC_WRITE, 30);
+	sst_sc_reg_access(sc_access, PMIC_WRITE, 28);
 	snd_msic_ops.pb_on = 0;
+	snd_msic_ops.pbhs_on = 0;
 	snd_msic_ops.cap_on = 0;
 	snd_msic_ops.input_dev_id = DMIC; /*def dev*/
 	snd_msic_ops.output_dev_id = STEREO_HEADPHONE;
 	pr_debug("msic init complete!!\n");
 	return 0;
 }
+static int msic_line_out_restore(u8 value)
+{
+	struct sc_reg_access hs_drv_en[] = {
+		{0x25d, 0x03, 0x03},
+	};
+	struct sc_reg_access ep_drv_en[] = {
+		{0x25d, 0x40, 0x40},
+	};
+	struct sc_reg_access ihf_drv_en[] = {
+		{0x25d, 0x0c, 0x0c},
+	};
+	struct sc_reg_access vib1_drv_en[] = {
+		{0x25d, 0x10, 0x10},
+	};
+	struct sc_reg_access vib2_drv_en[] = {
+		{0x25d, 0x20, 0x20},
+	};
+	int retval = 0;
+
+	pr_debug("msic_lineout_restore_lineout_dev:%d\n", value);
+
+	switch (value) {
+	case HEADSET:
+		pr_debug("Selecting Lineout-HEADSET-restore\n");
+		if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE)
+			retval = sst_sc_reg_access(hs_drv_en,
+							PMIC_READ_MODIFY, 1);
+		else
+			retval = sst_sc_reg_access(ep_drv_en,
+							PMIC_READ_MODIFY, 1);
+		break;
+	case IHF:
+		pr_debug("Selecting Lineout-IHF-restore\n");
+		retval = sst_sc_reg_access(ihf_drv_en, PMIC_READ_MODIFY, 1);
+		break;
+	case VIBRA1:
+		pr_debug("Selecting Lineout-Vibra1-restore\n");
+		retval = sst_sc_reg_access(vib1_drv_en, PMIC_READ_MODIFY, 1);
+		break;
+	case VIBRA2:
+		pr_debug("Selecting Lineout-VIBRA2-restore\n");
+		retval = sst_sc_reg_access(vib2_drv_en, PMIC_READ_MODIFY, 1);
+		break;
+	case NONE:
+		pr_debug("Selecting Lineout-NONE-restore\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+	return retval;
+}
+static int msic_get_lineout_prvstate(void)
+{
+	struct sc_reg_access hs_ihf_drv[2] = {
+		{0x257, 0x0, 0x0},
+		{0x25d, 0x0, 0x0},
+	};
+	struct sc_reg_access vib1drv[2] = {
+		{0x264, 0x0, 0x0},
+		{0x25D, 0x0, 0x0},
+	};
+	struct sc_reg_access vib2drv[2] = {
+		{0x26A, 0x0, 0x0},
+		{0x25D, 0x0, 0x0},
+	};
+	int retval = 0, drv_en, dac_en, dev_id, mask;
+	for (dev_id = 0; dev_id < snd_msic_ops.line_out_names_cnt; dev_id++) {
+		switch (dev_id) {
+		case HEADSET:
+			pr_debug("msic_get_lineout_prvs_state: HEADSET\n");
+			sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
+
+			mask = (MASK0|MASK1);
+			dac_en = (hs_ihf_drv[0].value) & mask;
+
+			mask = ((MASK0|MASK1)|MASK6);
+			drv_en = (hs_ihf_drv[1].value) & mask;
+
+			if (dac_en && (!drv_en)) {
+				snd_msic_ops.prev_lineout_dev_id = HEADSET;
+				return retval;
+			}
+			break;
+		case IHF:
+			pr_debug("msic_get_lineout_prvstate: IHF\n");
+			sst_sc_reg_access(hs_ihf_drv, PMIC_READ, 2);
+
+			mask = (MASK2 | MASK3);
+			dac_en = (hs_ihf_drv[0].value) & mask;
+
+			mask = (MASK2 | MASK3);
+			drv_en = (hs_ihf_drv[1].value) & mask;
+
+			if (dac_en && (!drv_en)) {
+				snd_msic_ops.prev_lineout_dev_id = IHF;
+				return retval;
+			}
+			break;
+		case VIBRA1:
+			pr_debug("msic_get_lineout_prvstate: vibra1\n");
+			sst_sc_reg_access(vib1drv, PMIC_READ, 2);
+
+			mask = MASK1;
+			dac_en = (vib1drv[0].value) & mask;
+
+			mask = MASK4;
+			drv_en = (vib1drv[1].value) & mask;
+
+			if (dac_en && (!drv_en)) {
+				snd_msic_ops.prev_lineout_dev_id = VIBRA1;
+				return retval;
+			}
+			break;
+		case VIBRA2:
+			pr_debug("msic_get_lineout_prvstate: vibra2\n");
+			sst_sc_reg_access(vib2drv, PMIC_READ, 2);
+
+			mask = MASK1;
+			dac_en = (vib2drv[0].value) & mask;
+
+			mask = MASK5;
+			drv_en = ((vib2drv[1].value) & mask);
+
+			if (dac_en && (!drv_en)) {
+				snd_msic_ops.prev_lineout_dev_id = VIBRA2;
+				return retval;
+			}
+			break;
+		case NONE:
+			pr_debug("msic_get_lineout_prvstate: NONE\n");
+			snd_msic_ops.prev_lineout_dev_id = NONE;
+			return retval;
+		default:
+			pr_debug("Invalid device id\n");
+			snd_msic_ops.prev_lineout_dev_id = NONE;
+			return -EINVAL;
+		}
+	}
+	return retval;
+}
+static int msic_set_selected_lineout_dev(u8 value)
+{
+	struct sc_reg_access lout_hs[] = {
+		{0x25e, 0x33, 0xFF},
+		{0x25d, 0x0, 0x43},
+	};
+	struct sc_reg_access lout_ihf[] = {
+		{0x25e, 0x55, 0xff},
+		{0x25d, 0x0, 0x0c},
+	};
+	struct sc_reg_access lout_vibra1[] = {
+
+		{0x25e, 0x61, 0xff},
+		{0x25d, 0x0, 0x10},
+	};
+	struct sc_reg_access lout_vibra2[] = {
+
+		{0x25e, 0x16, 0xff},
+		{0x25d, 0x0, 0x20},
+	};
+	struct sc_reg_access lout_def[] = {
+		{0x25e, 0x66, 0x0},
+	};
+	int retval = 0;
+
+	pr_debug("msic_set_selected_lineout_dev:%d\n", value);
+	msic_get_lineout_prvstate();
+	msic_line_out_restore(snd_msic_ops.prev_lineout_dev_id);
+	snd_msic_ops.lineout_dev_id = value;
+
+	switch (value) {
+	case HEADSET:
+		pr_debug("Selecting Lineout-HEADSET\n");
+		if (snd_msic_ops.pb_on)
+			retval = sst_sc_reg_access(lout_hs,
+					PMIC_READ_MODIFY, 2);
+		break;
+	case IHF:
+		pr_debug("Selecting Lineout-IHF\n");
+		if (snd_msic_ops.pb_on)
+			retval = sst_sc_reg_access(lout_ihf,
+							PMIC_READ_MODIFY, 2);
+		break;
+	case VIBRA1:
+		pr_debug("Selecting Lineout-Vibra1\n");
+		if (snd_msic_ops.pb_on)
+			retval = sst_sc_reg_access(lout_vibra1,
+							PMIC_READ_MODIFY, 2);
+		break;
+	case VIBRA2:
+		pr_debug("Selecting Lineout-VIBRA2\n");
+		if (snd_msic_ops.pb_on)
+			retval = sst_sc_reg_access(lout_vibra2,
+							PMIC_READ_MODIFY, 2);
+		break;
+	case NONE:
+		pr_debug("Selecting Lineout-NONE\n");
+			retval = sst_sc_reg_access(lout_def,
+							PMIC_WRITE, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return retval;
+}
+
 
 static int msic_power_up_pb(unsigned int device)
 {
@@ -161,12 +365,12 @@ static int msic_power_up_pb(unsigned int device)
 	struct sc_reg_access vib1_en[] = {
 		/* enable driver, ADC */
 		{0x25D, 0x10, 0x10},
-		{0x264, 0x02, 0x02},
+		{0x264, 0x02, 0x82},
 	};
 	struct sc_reg_access vib2_en[] = {
 		/* enable driver, ADC */
 		{0x25D, 0x20, 0x20},
-		{0x26A, 0x02, 0x02},
+		{0x26A, 0x02, 0x82},
 	};
 	struct sc_reg_access pcm2_en[] = {
 		/* enable pcm 2 */
@@ -187,6 +391,8 @@ static int msic_power_up_pb(unsigned int device)
 	msleep(1);
 	switch (device) {
 	case SND_SST_DEVICE_HEADSET:
+		snd_msic_ops.pb_on = 1;
+		snd_msic_ops.pbhs_on = 1;
 		if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) {
 			sst_sc_reg_access(vhs, PMIC_WRITE, 2);
 			sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 2);
@@ -197,22 +403,31 @@ static int msic_power_up_pb(unsigned int device)
 			sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
 			sst_sc_reg_access(ep_enable, PMIC_READ_MODIFY, 3);
 		}
-		snd_msic_ops.pb_on = 1;
+		if (snd_msic_ops.lineout_dev_id == HEADSET)
+			msic_set_selected_lineout_dev(HEADSET);
 		break;
-
 	case SND_SST_DEVICE_IHF:
+		snd_msic_ops.pb_on = 1;
 		sst_sc_reg_access(vihf, PMIC_WRITE, 1);
 		sst_sc_reg_access(ihf_filter, PMIC_READ_MODIFY, 3);
 		sst_sc_reg_access(ihf_en, PMIC_READ_MODIFY, 1);
 		sst_sc_reg_access(ihf_unmute, PMIC_READ_MODIFY, 2);
+		if (snd_msic_ops.lineout_dev_id == IHF)
+			msic_set_selected_lineout_dev(IHF);
 		break;
 
 	case SND_SST_DEVICE_VIBRA:
+		snd_msic_ops.pb_on = 1;
 		sst_sc_reg_access(vib1_en, PMIC_READ_MODIFY, 2);
+		if (snd_msic_ops.lineout_dev_id == VIBRA1)
+			msic_set_selected_lineout_dev(VIBRA1);
 		break;
 
 	case SND_SST_DEVICE_HAPTIC:
+		snd_msic_ops.pb_on = 1;
 		sst_sc_reg_access(vib2_en, PMIC_READ_MODIFY, 2);
+		if (snd_msic_ops.lineout_dev_id == VIBRA2)
+			msic_set_selected_lineout_dev(VIBRA2);
 		break;
 
 	default:
@@ -310,6 +525,7 @@ static int msic_power_down(void)
 	};
 
 	pr_debug("powering dn msic\n");
+	snd_msic_ops.pbhs_on = 0;
 	snd_msic_ops.pb_on = 0;
 	snd_msic_ops.cap_on = 0;
 	sst_sc_reg_access(power_dn, PMIC_WRITE, 3);
@@ -348,15 +564,22 @@ static int msic_power_down_pb(unsigned int device)
 	struct sc_reg_access vib2_off[] = {
 		{0x26A, 0x00, 0x82},
 	};
+	struct sc_reg_access lout_off[] = {
+		{0x25e, 0x66, 0x00},
+	};
+
+
 
 	pr_debug("powering dn pb for device %d\n", device);
 	switch (device) {
 	case SND_SST_DEVICE_HEADSET:
-		snd_msic_ops.pb_on = 0;
+		snd_msic_ops.pbhs_on = 0;
 		sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3);
 		drv_enable[0].mask = 0x43;
 		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
 		sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 2);
+		if (snd_msic_ops.lineout_dev_id == HEADSET)
+			sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
 		break;
 
 	case SND_SST_DEVICE_IHF:
@@ -364,18 +587,24 @@ static int msic_power_down_pb(unsigned int device)
 		drv_enable[0].mask = 0x0C;
 		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
 		sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2);
+		if (snd_msic_ops.lineout_dev_id == IHF)
+			sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
 		break;
 
 	case SND_SST_DEVICE_VIBRA:
-		sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 2);
+		sst_sc_reg_access(vib1_off, PMIC_READ_MODIFY, 1);
 		drv_enable[0].mask = 0x10;
 		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+		if (snd_msic_ops.lineout_dev_id == VIBRA1)
+			sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
 		break;
 
 	case SND_SST_DEVICE_HAPTIC:
-		sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 2);
+		sst_sc_reg_access(vib2_off, PMIC_READ_MODIFY, 1);
 		drv_enable[0].mask = 0x20;
 		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
+		if (snd_msic_ops.lineout_dev_id == VIBRA2)
+			sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
 		break;
 	}
 	return 0;
@@ -414,7 +643,7 @@ static int msic_set_selected_output_dev(u8 value)
 
 	pr_debug("msic set selected output:%d\n", value);
 	snd_msic_ops.output_dev_id = value;
-	if (snd_msic_ops.pb_on)
+	if (snd_msic_ops.pbhs_on)
 		msic_power_up_pb(SND_SST_DEVICE_HEADSET);
 	return retval;
 }
@@ -494,6 +723,7 @@ static int msic_get_vol(int dev_id, int *value)
 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_mute	=	msic_set_mute,
 	.get_mute	=	msic_get_mute,
 	.set_vol	=	msic_set_vol,
diff --git a/drivers/staging/intel_sst/intelmid_snd_control.h b/drivers/staging/intel_sst/intelmid_snd_control.h
index a4565f3..c7e9f16 100644
--- a/drivers/staging/intel_sst/intelmid_snd_control.h
+++ b/drivers/staging/intel_sst/intelmid_snd_control.h
@@ -80,6 +80,13 @@ enum SND_INPUT_DEVICE {
 	HS_MIC,
 	IN_UNDEFINED
 };
+enum SND_LINE_OUT_DEVICE {
+	HEADSET,
+	IHF,
+	VIBRA1,
+	VIBRA2,
+	NONE,
+};
 
 enum SND_OUTPUT_DEVICE {
 	STEREO_HEADPHONE,
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
index 6cf5901..964c412 100644
--- a/drivers/staging/intel_sst/intelmid_v0_control.c
+++ b/drivers/staging/intel_sst/intelmid_v0_control.c
@@ -494,7 +494,10 @@ static int fs_set_selected_output_dev(u8 value)
 
 	}
 }
-
+static int fs_set_selected_lineout_dev(u8 value)
+{
+	return 0;
+}
 static int fs_set_mute(int dev_id, u8 value)
 {
 	struct sc_reg_access sc_access[6] = {{0,},};
@@ -756,6 +759,7 @@ static int fs_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_pmic_ops_fs = {
 	.set_input_dev = fs_set_selected_input_dev,
 	.set_output_dev = fs_set_selected_output_dev,
+	.set_lineout_dev = fs_set_selected_lineout_dev,
 	.set_mute = fs_set_mute,
 	.get_mute = fs_get_mute,
 	.set_vol = fs_set_vol,
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c
index 445e0fb..4f2b34f 100644
--- a/drivers/staging/intel_sst/intelmid_v1_control.c
+++ b/drivers/staging/intel_sst/intelmid_v1_control.c
@@ -585,6 +585,10 @@ static int mx_set_selected_input_dev(u8 dev_id)
 	}
 	return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
 }
+static int mx_set_selected_lineout_dev(u8 dev_id)
+{
+	return 0;
+}
 
 static int mx_set_mute(int dev_id, u8 value)
 {
@@ -835,6 +839,7 @@ static int mx_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_pmic_ops_mx = {
 	.set_input_dev = mx_set_selected_input_dev,
 	.set_output_dev = mx_set_selected_output_dev,
+	.set_lineout_dev = mx_set_selected_lineout_dev,
 	.set_mute = mx_set_mute,
 	.get_mute = mx_get_mute,
 	.set_vol = mx_set_vol,
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 28754a5..a0cd227 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -885,7 +885,10 @@ static int nc_set_selected_input_dev(u8 value)
 	}
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
 }
-
+static int nc_set_selected_lineout_dev(u8 dev_id)
+{
+	return 0;
+}
 static int nc_get_mute(int dev_id, u8 *value)
 {
 	int retval = 0, mask = 0;
@@ -990,6 +993,7 @@ static int nc_get_vol(int dev_id, int *value)
 struct snd_pmic_ops snd_pmic_ops_nc = {
 	.set_input_dev	=	nc_set_selected_input_dev,
 	.set_output_dev =	nc_set_selected_output_dev,
+	.set_lineout_dev =	nc_set_selected_lineout_dev,
 	.set_mute	=	nc_set_mute,
 	.get_mute	=	nc_get_mute,
 	.set_vol	=	nc_set_vol,


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 06/23] intel_sst: parameter tuning ioctl
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (4 preceding siblings ...)
  2011-05-03 16:32 ` [PATCH 05/23] intel_sst: Line out support Alan Cox
@ 2011-05-03 16:32 ` Alan Cox
  2011-05-03 16:33 ` [PATCH 07/23] intel_sst: DMIC routing Alan Cox
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:32 UTC (permalink / raw)
  To: greg, linux-kernel

From: Vinod Koul <vinod.koul@intel.com>

This patch adds new IOCTL for application interface.

Using parameter tuning IOCTL, application can fine
tune the audio firmware for it's requirement.

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 .../staging/intel_sst/intel_sst_app_interface.c    |   37 ++++++++++++++++++++
 drivers/staging/intel_sst/intel_sst_common.h       |    4 +-
 drivers/staging/intel_sst/intel_sst_fw_ipc.h       |    1 +
 drivers/staging/intel_sst/intel_sst_ioctl.h        |    8 ++++
 drivers/staging/intel_sst/intel_sst_ipc.c          |   18 ++++++++++
 5 files changed, 66 insertions(+), 2 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst_app_interface.c b/drivers/staging/intel_sst/intel_sst_app_interface.c
index d7454e2..b8c7ddb 100644
--- a/drivers/staging/intel_sst/intel_sst_app_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_app_interface.c
@@ -961,6 +961,34 @@ free_mem:
 	return retval;
 }
 
+
+int sst_ioctl_tuning_params(unsigned long arg)
+{
+	struct snd_sst_tuning_params params;
+	struct ipc_post *msg;
+
+	if (copy_from_user(&params, (void __user *)arg, sizeof(params)))
+		return -EFAULT;
+	if (params.size > SST_MAILBOX_SIZE)
+		return -ENOMEM;
+	pr_debug("Parameter %d, Stream %d, Size %d\n", params.type,
+			params.str_id, params.size);
+	if (sst_create_large_msg(&msg))
+		return -ENOMEM;
+
+	sst_fill_header(&msg->header, IPC_IA_TUNING_PARAMS, 1, params.str_id);
+	msg->header.part.data = sizeof(u32) + sizeof(params) + params.size;
+	memcpy(msg->mailbox_data, &msg->header.full, sizeof(u32));
+	memcpy(msg->mailbox_data + sizeof(u32), &params, sizeof(params));
+	if (copy_from_user(msg->mailbox_data + sizeof(params),
+			(void __user *)(unsigned long)params.addr,
+			params.size)) {
+		kfree(msg->mailbox_data);
+		kfree(msg);
+		return -EFAULT;
+	}
+	return sst_send_algo_ipc(&msg);
+}
 /**
  * intel_sst_ioctl - receives the device ioctl's
  * @file_ptr:pointer to file
@@ -1412,6 +1440,15 @@ free_iobufs:
 		}
 		retval = intel_sst_ioctl_dsp(cmd, arg);
 		break;
+
+	case _IOC_NR(SNDRV_SST_TUNING_PARAMS):
+		if (minor != AM_MODULE) {
+			retval = -EBADRQC;
+			break;
+		}
+		retval = sst_ioctl_tuning_params(arg);
+		break;
+
 	default:
 		retval = -EINVAL;
 	}
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
index 9aff1a3..e37b377 100644
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -28,8 +28,8 @@
  *  Common private declarations for SST
  */
 
-#define SST_DRIVER_VERSION "1.2.14"
-#define SST_VERSION_NUM 0x1214
+#define SST_DRIVER_VERSION "1.2.15"
+#define SST_VERSION_NUM 0x1215
 
 /* driver names */
 #define SST_DRV_NAME "intel_sst_driver"
diff --git a/drivers/staging/intel_sst/intel_sst_fw_ipc.h b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
index 8628a8a..5d0cc56 100644
--- a/drivers/staging/intel_sst/intel_sst_fw_ipc.h
+++ b/drivers/staging/intel_sst/intel_sst_fw_ipc.h
@@ -71,6 +71,7 @@
 #define IPC_IA_DECODE_FRAMES 0x18
 
 #define IPC_IA_ALG_PARAMS 0x1A
+#define IPC_IA_TUNING_PARAMS 0x1B
 
 /* I2L Stream config/control msgs */
 #define IPC_IA_ALLOC_STREAM 0x20 /* Allocate a stream ID */
diff --git a/drivers/staging/intel_sst/intel_sst_ioctl.h b/drivers/staging/intel_sst/intel_sst_ioctl.h
index bebc395..5da5ee0 100644
--- a/drivers/staging/intel_sst/intel_sst_ioctl.h
+++ b/drivers/staging/intel_sst/intel_sst_ioctl.h
@@ -400,6 +400,13 @@ struct snd_sst_dbufs  {
 	struct snd_sst_buffs *obufs;
 };
 
+struct snd_sst_tuning_params {
+	__u8 type;
+	__u8 str_id;
+	__u8 size;
+	__u8 rsvd;
+	__aligned_u64 addr;
+} __attribute__ ((packed));
 /*IOCTL defined here */
 /*SST MMF IOCTLS only */
 #define SNDRV_SST_STREAM_SET_PARAMS _IOR('L', 0x00, \
@@ -428,5 +435,6 @@ struct snd_sst_dbufs  {
 /*DSP Ioctls on /dev/intel_sst_ctrl only*/
 #define SNDRV_SST_SET_ALGO	_IOW('L', 0x30,  struct snd_ppp_params *)
 #define SNDRV_SST_GET_ALGO	_IOWR('L', 0x31,  struct snd_ppp_params *)
+#define SNDRV_SST_TUNING_PARAMS	_IOW('L', 0x32,  struct snd_sst_tuning_params *)
 
 #endif /* __INTEL_SST_IOCTL_H__ */
diff --git a/drivers/staging/intel_sst/intel_sst_ipc.c b/drivers/staging/intel_sst/intel_sst_ipc.c
index 878b19d..5c3444f 100644
--- a/drivers/staging/intel_sst/intel_sst_ipc.c
+++ b/drivers/staging/intel_sst/intel_sst_ipc.c
@@ -416,6 +416,24 @@ void sst_process_reply(struct work_struct *work)
 		}
 		break;
 	}
+
+	case IPC_IA_TUNING_PARAMS: {
+		pr_debug("sst:IPC_TUNING_PARAMS resp: %x\n", msg->header.full);
+		pr_debug("data value %x\n", msg->header.part.data);
+		if (msg->header.part.large) {
+			pr_debug("alg set failed\n");
+			sst_drv_ctx->ppp_params_blk.ret_code =
+							-msg->header.part.data;
+		} else {
+			pr_debug("alg set success\n");
+			sst_drv_ctx->ppp_params_blk.ret_code = 0;
+		}
+		if (sst_drv_ctx->ppp_params_blk.on == true) {
+			sst_drv_ctx->ppp_params_blk.condition = true;
+			wake_up(&sst_drv_ctx->wait_queue);
+		}
+	}
+
 	case IPC_IA_GET_FW_INFO: {
 		struct snd_sst_fw_info *fw_info =
 			(struct snd_sst_fw_info *)msg->mailbox;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 07/23] intel_sst: DMIC routing
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (5 preceding siblings ...)
  2011-05-03 16:32 ` [PATCH 06/23] intel_sst: parameter tuning ioctl Alan Cox
@ 2011-05-03 16:33 ` Alan Cox
  2011-05-03 16:33 ` [PATCH 08/23] intel_sst: rework jack implementation Alan Cox
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:33 UTC (permalink / raw)
  To: greg, linux-kernel

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,


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 08/23] intel_sst: rework jack implementation
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (6 preceding siblings ...)
  2011-05-03 16:33 ` [PATCH 07/23] intel_sst: DMIC routing Alan Cox
@ 2011-05-03 16:33 ` Alan Cox
  2011-05-03 16:33 ` [PATCH 09/23] intel_sst: Set de-bounce time Alan Cox
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:33 UTC (permalink / raw)
  To: greg, linux-kernel

From: Ramesh Babu K V <ramesh.babu@intel.com>

This patch fixes the below issues w.r.t jack implementation

a) The current jack implementation in driver is implemented
   in intelmid.c. It has moved to vendor files for better managebility
b) Cleaned up jack reporting per upstream comments
c) Implemented jack for msic, added code to read adc and deduce jack
   type based on mic bias
d) Support detection of american headset

Signed-off-by: Dharageswari R <dharageswari.r@intel.com>
Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
[Corrections]
Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intel_sst.h             |   16 +
 drivers/staging/intel_sst/intel_sst_common.h      |    4 
 drivers/staging/intel_sst/intelmid.c              |  449 +++++----------------
 drivers/staging/intel_sst/intelmid.h              |   14 +
 drivers/staging/intel_sst/intelmid_adc_control.h  |  193 +++++++++
 drivers/staging/intel_sst/intelmid_ctrl.c         |    1 
 drivers/staging/intel_sst/intelmid_msic_control.c |  258 ++++++++++++
 drivers/staging/intel_sst/intelmid_pvt.c          |    1 
 drivers/staging/intel_sst/intelmid_v0_control.c   |  111 +++++
 drivers/staging/intel_sst/intelmid_v1_control.c   |  142 ++++++-
 drivers/staging/intel_sst/intelmid_v2_control.c   |   69 +++
 drivers/staging/intel_sst/jack.h                  |   10 
 12 files changed, 887 insertions(+), 381 deletions(-)
 create mode 100644 drivers/staging/intel_sst/intelmid_adc_control.h
 delete mode 100644 drivers/staging/intel_sst/jack.h


diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
index c0d3156..986a3df 100644
--- a/drivers/staging/intel_sst/intel_sst.h
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -30,6 +30,7 @@
  *  This file is shared between the SST and MAD drivers
  */
 #include "intel_sst_ioctl.h"
+#include <sound/jack.h>
 
 #define SST_CARD_NAMES "intel_mid_card"
 
@@ -88,6 +89,7 @@ struct snd_pmic_ops {
 	int output_dev_id;
 	int lineout_dev_id, line_out_names_cnt;
 	int prev_lineout_dev_id;
+	bool jack_interrupt_status;
 	int (*set_input_dev) (u8 value);
 	int (*set_output_dev) (u8 value);
 	int (*set_lineout_dev) (u8 value);
@@ -109,11 +111,25 @@ 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);
+	void (*pmic_irq_cb) (void *cb_data, u8 value);
+	void (*pmic_irq_enable)(void *data);
+	int (*pmic_jack_enable) (void);
+	int (*pmic_get_mic_bias)(void *intelmaddata);
+	int (*pmic_set_headset_state)(int state);
+
 	unsigned int hw_dmic_map[MFLD_MAX_HW_CH];
 	unsigned int available_dmics;
 	int (*set_hw_dmic_route) (u8 index);
 };
 
+extern void sst_mad_send_jack_report(struct snd_jack *jack,
+				     int buttonpressevent,
+				     int status);
+
+
+int intemad_set_headset_state(int state);
+int intelmad_get_mic_bias(void);
+
 struct intel_sst_pcm_control {
 	int (*open) (struct snd_sst_params *str_param);
 	int (*device_control) (int cmd, void *arg);
diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h
index e37b377..f8e9da6 100644
--- a/drivers/staging/intel_sst/intel_sst_common.h
+++ b/drivers/staging/intel_sst/intel_sst_common.h
@@ -28,8 +28,8 @@
  *  Common private declarations for SST
  */
 
-#define SST_DRIVER_VERSION "1.2.15"
-#define SST_VERSION_NUM 0x1215
+#define SST_DRIVER_VERSION "1.2.17"
+#define SST_VERSION_NUM 0x1217
 
 /* driver names */
 #define SST_DRV_NAME "intel_sst_driver"
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index ee070e3..61ef4a6 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -33,10 +33,11 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/firmware.h>
+#include <linux/input.h>
 #include <sound/control.h>
 #include <asm/mrst.h>
 #include <sound/pcm.h>
-#include "jack.h"
+#include <sound/jack.h>
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include "intel_sst.h"
@@ -44,6 +45,7 @@
 #include "intel_sst_fw_ipc.h"
 #include "intel_sst_common.h"
 #include "intelmid_snd_control.h"
+#include "intelmid_adc_control.h"
 #include "intelmid.h"
 
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
@@ -65,7 +67,14 @@ MODULE_PARM_DESC(card_id, "ID string for INTELMAD soundcard.");
 
 int	sst_card_vendor_id;
 int intelmid_audio_interrupt_enable;/*checkpatch fix*/
-
+struct snd_intelmad *intelmad_drv;
+
+#define INFO(_cpu_id, _irq_cache, _size) \
+	((kernel_ulong_t)&(struct snd_intelmad_probe_info) {	\
+		.cpu_id = (_cpu_id),			\
+		.irq_cache = (_irq_cache),			\
+		.size = (_size),				\
+	})
 /* Data path functionalities */
 static struct snd_pcm_hardware snd_intelmad_stream = {
 	.info =	(SNDRV_PCM_INFO_INTERLEAVED |
@@ -426,7 +435,55 @@ static struct snd_pcm_ops snd_intelmad_capture_ops = {
 	.pointer = snd_intelmad_pcm_pointer,
 };
 
+int intelmad_get_mic_bias(void)
+{
+	struct snd_pmic_ops *pmic_ops;
+
+	if (!intelmad_drv || !intelmad_drv->sstdrv_ops)
+		return -ENODEV;
+	pmic_ops = intelmad_drv->sstdrv_ops->scard_ops;
+	if (pmic_ops && pmic_ops->pmic_get_mic_bias)
+		return pmic_ops->pmic_get_mic_bias(intelmad_drv);
+	else
+		return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(intelmad_get_mic_bias);
+
+int intelmad_set_headset_state(int state)
+{
+	struct snd_pmic_ops *pmic_ops;
+
+	if (!intelmad_drv || !intelmad_drv->sstdrv_ops)
+		return -ENODEV;
+	pmic_ops = intelmad_drv->sstdrv_ops->scard_ops;
+	if (pmic_ops && pmic_ops->pmic_set_headset_state)
+		return pmic_ops->pmic_set_headset_state(state);
+	else
+		return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(intelmad_set_headset_state);
+
+void sst_process_mad_jack_detection(struct work_struct *work)
+{
+	u8 interrupt_status;
+	struct mad_jack_msg_wq *mad_jack_detect =
+			container_of(work, struct mad_jack_msg_wq, wq);
+
+	struct snd_intelmad *intelmaddata =
+			mad_jack_detect->intelmaddata;
 
+	if (!intelmaddata)
+		return;
+
+	interrupt_status = mad_jack_detect->intsts;
+	if (intelmaddata->sstdrv_ops && intelmaddata->sstdrv_ops->scard_ops
+			&& intelmaddata->sstdrv_ops->scard_ops->pmic_irq_cb) {
+		intelmaddata->sstdrv_ops->scard_ops->pmic_irq_cb(
+			(void *)intelmaddata, interrupt_status);
+		intelmaddata->sstdrv_ops->scard_ops->pmic_jack_enable();
+	}
+	kfree(mad_jack_detect);
+}
 /**
  * snd_intelmad_intr_handler- interrupt handler
  *
@@ -439,15 +496,17 @@ static irqreturn_t snd_intelmad_intr_handler(int irq, void *dev)
 {
 	struct snd_intelmad *intelmaddata =
 			(struct snd_intelmad *)dev;
-	u8 intsts;
-
-	memcpy_fromio(&intsts,
+	u8 interrupt_status;
+	struct mad_jack_msg_wq  *mad_jack_msg;
+	memcpy_fromio(&interrupt_status,
 			((void *)(intelmaddata->int_base)),
 			sizeof(u8));
-	intelmaddata->mad_jack_msg.intsts = intsts;
-	intelmaddata->mad_jack_msg.intelmaddata = intelmaddata;
 
-	queue_work(intelmaddata->mad_jack_wq, &intelmaddata->mad_jack_msg.wq);
+	mad_jack_msg = kzalloc(sizeof(*mad_jack_msg), GFP_ATOMIC);
+	mad_jack_msg->intsts = interrupt_status;
+	mad_jack_msg->intelmaddata = intelmaddata;
+	INIT_WORK(&mad_jack_msg->wq, sst_process_mad_jack_detection);
+	queue_work(intelmaddata->mad_jack_wq, &mad_jack_msg->wq);
 
 	return IRQ_HANDLED;
 }
@@ -460,286 +519,22 @@ void sst_mad_send_jack_report(struct snd_jack *jack,
 		pr_debug("MAD error jack empty\n");
 
 	} else {
-		pr_debug("MAD send jack report for = %d!!!\n", status);
-		pr_debug("MAD send jack report %d\n", jack->type);
 		snd_jack_report(jack, status);
-
-		/*button pressed and released */
+		/* button pressed and released */
 		if (buttonpressevent)
 			snd_jack_report(jack, 0);
 		pr_debug("MAD sending jack report Done !!!\n");
 	}
-
-
-
-}
-
-void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata)
-{
-	struct snd_jack *jack = NULL;
-	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-	struct sc_reg_access sc_access[] = {
-				{0x187, 0x00, MASK7},
-				{0x188, 0x10, MASK4},
-				{0x18b, 0x10, MASK4},
-	};
-
-	struct sc_reg_access sc_access_write[] = {
-				{0x198, 0x00, 0x0},
-	};
-
-	if (intsts & 0x4) {
-
-		if (!(intelmid_audio_interrupt_enable)) {
-			pr_debug("Audio interrupt enable\n");
-			sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-
-			sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
-			intelmid_audio_interrupt_enable = 1;
-			intelmaddata->jack[0].jack_status = 0;
-			intelmaddata->jack[1].jack_status = 0;
-
-		}
-		/* send headphone detect */
-		pr_debug("MAD headphone %d\n", intsts & 0x4);
-		jack = &intelmaddata->jack[0].jack;
-		present = !(intelmaddata->jack[0].jack_status);
-		intelmaddata->jack[0].jack_status = present;
-		jack_event_flag = 1;
-
-	}
-
-	if (intsts & 0x2) {
-		/* send short push */
-		pr_debug("MAD short push %d\n", intsts & 0x2);
-		jack = &intelmaddata->jack[2].jack;
-		present = 1;
-		jack_event_flag = 1;
-		buttonpressflag = 1;
-	}
-	if (intsts & 0x1) {
-		/* send long push */
-		pr_debug("MAD long push %d\n", intsts & 0x1);
-		jack = &intelmaddata->jack[3].jack;
-		present = 1;
-		jack_event_flag = 1;
-		buttonpressflag = 1;
-	}
-	if (intsts & 0x8) {
-		if (!(intelmid_audio_interrupt_enable)) {
-			pr_debug("Audio interrupt enable\n");
-			sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
-
-			sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
-			intelmid_audio_interrupt_enable = 1;
-			intelmaddata->jack[0].jack_status = 0;
-			intelmaddata->jack[1].jack_status = 0;
-		}
-		/* send headset detect */
-		pr_debug("MAD headset = %d\n", intsts & 0x8);
-		jack = &intelmaddata->jack[1].jack;
-		present = !(intelmaddata->jack[1].jack_status);
-		intelmaddata->jack[1].jack_status = present;
-		jack_event_flag = 1;
-	}
-
-	if (jack_event_flag)
-		sst_mad_send_jack_report(jack, buttonpressflag, present);
 }
 
-
-void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata)
-{
-	u8 value = 0, jack_prev_state = 0;
-	struct snd_jack *jack = NULL;
-	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-	time_t  timediff;
-	struct sc_reg_access sc_access_read = {0,};
-	struct snd_pmic_ops *scard_ops;
-
-	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
-
-	pr_debug("previous value: %x\n", intelmaddata->jack_prev_state);
-
-	if (!(intelmid_audio_interrupt_enable)) {
-		pr_debug("Audio interrupt enable\n");
-		intelmaddata->jack_prev_state = 0xC0;
-		intelmid_audio_interrupt_enable = 1;
-	}
-
-	if (intsts & 0x2) {
-		jack_prev_state = intelmaddata->jack_prev_state;
-		if (intelmaddata->pmic_status == PMIC_INIT) {
-			sc_access_read.reg_addr = 0x201;
-			sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
-			value = (sc_access_read.value);
-			pr_debug("value returned = 0x%x\n", value);
-		}
-
-		if (jack_prev_state == 0xc0 && value == 0x40) {
-			/*headset detected. */
-			pr_debug("MAD headset inserted\n");
-			jack = &intelmaddata->jack[1].jack;
-			present = 1;
-			jack_event_flag = 1;
-			intelmaddata->jack[1].jack_status = 1;
-
-		}
-
-		if (jack_prev_state == 0xc0 && value == 0x00) {
-			/* headphone  detected. */
-			pr_debug("MAD headphone inserted\n");
-			jack = &intelmaddata->jack[0].jack;
-			present = 1;
-			jack_event_flag = 1;
-
-		}
-
-		if (jack_prev_state == 0x40 && value == 0xc0) {
-			/*headset  removed*/
-			pr_debug("Jack headset status %d\n",
-				intelmaddata->jack[1].jack_status);
-			pr_debug("MAD headset removed\n");
-			jack = &intelmaddata->jack[1].jack;
-			present = 0;
-			jack_event_flag = 1;
-			intelmaddata->jack[1].jack_status = 0;
-		}
-
-		if (jack_prev_state == 0x00 && value == 0xc0) {
-			/* headphone  detected. */
-			pr_debug("Jack headphone status %d\n",
-					intelmaddata->jack[0].jack_status);
-			pr_debug("headphone removed\n");
-			jack = &intelmaddata->jack[0].jack;
-			present = 0;
-			jack_event_flag = 1;
-		}
-
-		if (jack_prev_state == 0x40 && value == 0x00) {
-			/*button pressed*/
-			do_gettimeofday(&intelmaddata->jack[1].buttonpressed);
-			pr_debug("MAD button press detected\n");
-		}
-
-
-		if (jack_prev_state == 0x00 && value == 0x40) {
-			if (intelmaddata->jack[1].jack_status) {
-				/*button pressed*/
-				do_gettimeofday(
-					&intelmaddata->jack[1].buttonreleased);
-				/*button pressed */
-				pr_debug("Button Released detected\n");
-				timediff = intelmaddata->jack[1].
-					buttonreleased.tv_sec - intelmaddata->
-					jack[1].buttonpressed.tv_sec;
-				buttonpressflag = 1;
-				if (timediff > 1) {
-					pr_debug("long press detected\n");
-					/* send headphone detect/undetect */
-					jack = &intelmaddata->jack[3].jack;
-					present = 1;
-					jack_event_flag = 1;
-				} else {
-					pr_debug("short press detected\n");
-					/* send headphone detect/undetect */
-					jack = &intelmaddata->jack[2].jack;
-					present = 1;
-					jack_event_flag = 1;
-				}
-			}
-
-		}
-		intelmaddata->jack_prev_state = value;
-	}
-	if (jack_event_flag)
-		sst_mad_send_jack_report(jack, buttonpressflag, present);
-}
-
-
-void sst_mad_jackdetection_nec(u8 intsts, struct snd_intelmad *intelmaddata)
-{
-	u8 value = 0;
-	struct snd_jack *jack = NULL;
-	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
-	struct sc_reg_access sc_access_read = {0,};
-
-	if (intelmaddata->pmic_status == PMIC_INIT) {
-		sc_access_read.reg_addr = 0x132;
-		sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
-		value = (sc_access_read.value);
-		pr_debug("value returned = 0x%x\n", value);
-	}
-	if (intsts & 0x1) {
-		pr_debug("headset detected\n");
-		/* send headset detect/undetect */
-		jack = &intelmaddata->jack[1].jack;
-		present = (value == 0x1) ? 1 : 0;
-		jack_event_flag = 1;
-	}
-	if (intsts & 0x2) {
-		pr_debug("headphone detected\n");
-		/* send headphone detect/undetect */
-		jack = &intelmaddata->jack[0].jack;
-		present = (value == 0x2) ? 1 : 0;
-		jack_event_flag = 1;
-	}
-	if (intsts & 0x4) {
-		pr_debug("short push detected\n");
-		/* send short push */
-		jack = &intelmaddata->jack[2].jack;
-		present = 1;
-		jack_event_flag = 1;
-		buttonpressflag = 1;
-	}
-	if (intsts & 0x8) {
-		pr_debug("long push detected\n");
-		/* send long push */
-		jack = &intelmaddata->jack[3].jack;
-		present = 1;
-		jack_event_flag = 1;
-		buttonpressflag = 1;
-	}
-
-	if (jack_event_flag)
-		sst_mad_send_jack_report(jack, buttonpressflag, present);
-
-
-}
-
-void sst_process_mad_jack_detection(struct work_struct *work)
-{
-	u8 intsts;
-	struct mad_jack_msg_wq *mad_jack_detect =
-			container_of(work, struct mad_jack_msg_wq, wq);
-
-	struct snd_intelmad *intelmaddata =
-			mad_jack_detect->intelmaddata;
-
-	intsts = mad_jack_detect->intsts;
-
-	switch (intelmaddata->sstdrv_ops->vendor_id) {
-	case SND_FS:
-		sst_mad_jackdetection_fs(intsts , intelmaddata);
-		break;
-	case SND_MX:
-		sst_mad_jackdetection_mx(intsts , intelmaddata);
-		break;
-	case SND_NC:
-		sst_mad_jackdetection_nec(intsts , intelmaddata);
-		break;
-	}
-}
-
-
 static int __devinit snd_intelmad_register_irq(
-					struct snd_intelmad *intelmaddata)
+		struct snd_intelmad *intelmaddata, unsigned int regbase,
+		unsigned int regsize)
 {
 	int ret_val;
-	u32 regbase = AUDINT_BASE, regsize = 8;
 	char *drv_name;
 
-	pr_debug("irq reg done, regbase 0x%x, regsize 0x%x\n",
+	pr_debug("irq reg regbase 0x%x, regsize 0x%x\n",
 					regbase, regsize);
 	intelmaddata->int_base = ioremap_nocache(regbase, regsize);
 	if (!intelmaddata->int_base)
@@ -811,6 +606,10 @@ static int __devinit snd_intelmad_sst_register(
 	return ret_val;
 }
 
+static void snd_intelmad_page_free(struct snd_pcm *pcm)
+{
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
 /* Driver Init/exit functionalities */
 /**
  * snd_intelmad_pcm_new - to setup pcm for the card
@@ -862,6 +661,7 @@ static int __devinit snd_intelmad_pcm_new(struct snd_card *card,
 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, cap_ops);
 	/* setup private data which can be retrieved when required */
 	pcm->private_data = intelmaddata;
+	pcm->private_free = snd_intelmad_page_free;
 	pcm->info_flags = 0;
 	strncpy(pcm->name, card->shortname, strlen(card->shortname));
 	/* allocate dma pages for ALSA stream operations */
@@ -906,8 +706,12 @@ static int snd_intelmad_jack(struct snd_intelmad *intelmaddata)
 
 	pr_debug("snd_intelmad_jack called\n");
 	jack = &intelmaddata->jack[0].jack;
-	retval = snd_jack_new(intelmaddata->card, "Headphone",
-				SND_JACK_HEADPHONE, &jack);
+	snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PHONE);
+	retval = snd_jack_new(intelmaddata->card, "Intel(R) MID Audio Jack",
+		SND_JACK_HEADPHONE | SND_JACK_HEADSET |
+		SW_JACK_PHYSICAL_INSERT | SND_JACK_BTN_0
+		| SND_JACK_BTN_1, &jack);
+	pr_debug("snd_intelmad_jack called\n");
 	if (retval < 0)
 		return retval;
 	snd_jack_report(jack, 0);
@@ -915,40 +719,6 @@ static int snd_intelmad_jack(struct snd_intelmad *intelmaddata)
 	jack->private_data = jack;
 	intelmaddata->jack[0].jack = *jack;
 
-
-	jack = &intelmaddata->jack[1].jack;
-	retval = snd_jack_new(intelmaddata->card, "Headset",
-				SND_JACK_HEADSET, &jack);
-	if (retval < 0)
-		return retval;
-
-
-
-	jack->private_data = jack;
-	intelmaddata->jack[1].jack = *jack;
-
-
-	jack = &intelmaddata->jack[2].jack;
-	retval = snd_jack_new(intelmaddata->card, "Short Press",
-				SND_JACK_HS_SHORT_PRESS, &jack);
-	if (retval < 0)
-		return retval;
-
-
-	jack->private_data = jack;
-	intelmaddata->jack[2].jack = *jack;
-
-
-	jack = &intelmaddata->jack[3].jack;
-	retval = snd_jack_new(intelmaddata->card, "Long Press",
-				SND_JACK_HS_LONG_PRESS, &jack);
-	if (retval < 0)
-		return retval;
-
-
-	jack->private_data = jack;
-	intelmaddata->jack[3].jack = *jack;
-
 	return retval;
 }
 
@@ -1001,14 +771,14 @@ static int snd_intelmad_dev_free(struct snd_device *device)
 	intelmaddata = device->device_data;
 
 	pr_debug("snd_intelmad_dev_free called\n");
-	snd_card_free(intelmaddata->card);
-	/*genl_unregister_family(&audio_event_genl_family);*/
 	unregister_sst_card(intelmaddata->sstdrv_ops);
 
 	/* free allocated memory for internal context */
 	destroy_workqueue(intelmaddata->mad_jack_wq);
+	device->device_data = NULL;
 	kfree(intelmaddata->sstdrv_ops);
 	kfree(intelmaddata);
+
 	return 0;
 }
 
@@ -1039,9 +809,10 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 	int ret_val;
 	struct snd_intelmad *intelmaddata;
 	const struct platform_device_id *id = platform_get_device_id(pdev);
-	unsigned int cpu_id = (unsigned int)id->driver_data;
+	struct snd_intelmad_probe_info *info = (void *)id->driver_data;
 
-	pr_debug("probe for %s cpu_id %d\n", pdev->name, cpu_id);
+	pr_debug("probe for %s cpu_id %d\n", pdev->name, info->cpu_id);
+	pr_debug("rq_chache %x of size %x\n", info->irq_cache, info->size);
 	if (!strcmp(pdev->name, DRIVER_NAME_MRST))
 		pr_debug("detected MRST\n");
 	else if (!strcmp(pdev->name, DRIVER_NAME_MFLD))
@@ -1050,7 +821,8 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 		pr_err("detected unknown device abort!!\n");
 		return -EIO;
 	}
-	if ((cpu_id < CPU_CHIP_LINCROFT) || (cpu_id > CPU_CHIP_PENWELL)) {
+	if ((info->cpu_id < CPU_CHIP_LINCROFT) ||
+				(info->cpu_id > CPU_CHIP_PENWELL)) {
 		pr_err("detected unknown cpu_id abort!!\n");
 		return -EIO;
 	}
@@ -1060,6 +832,7 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 		pr_debug("mem alloctn fail\n");
 		return -ENOMEM;
 	}
+	intelmad_drv = intelmaddata;
 
 	/* allocate memory for LPE API set */
 	intelmaddata->sstdrv_ops = kzalloc(sizeof(struct intel_sst_card_ops),
@@ -1070,7 +843,7 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	intelmaddata->cpu_id = cpu_id;
+	intelmaddata->cpu_id = info->cpu_id;
 	/* create a card instance with ALSA framework */
 	ret_val = snd_card_create(card_index, card_id, THIS_MODULE, 0, &card);
 	if (ret_val) {
@@ -1094,7 +867,7 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 	ret_val = snd_intelmad_sst_register(intelmaddata);
 	if (ret_val) {
 		pr_err("snd_intelmad_sst_register failed\n");
-		goto free_allocs;
+		goto set_null_data;
 	}
 
 	intelmaddata->pmic_status = PMIC_INIT;
@@ -1102,20 +875,21 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 	ret_val = snd_intelmad_pcm(card, intelmaddata);
 	if (ret_val) {
 		pr_err("snd_intelmad_pcm failed\n");
-		goto free_allocs;
+		goto free_sst;
 	}
 
 	ret_val = snd_intelmad_mixer(intelmaddata);
 	if (ret_val) {
 		pr_err("snd_intelmad_mixer failed\n");
-		goto free_allocs;
+		goto free_card;
 	}
 
 	ret_val = snd_intelmad_jack(intelmaddata);
 	if (ret_val) {
 		pr_err("snd_intelmad_jack failed\n");
-		goto free_allocs;
+		goto free_card;
 	}
+	intelmaddata->adc_address = mid_initialize_adc();
 
 	/*create work queue for jack interrupt*/
 	INIT_WORK(&intelmaddata->mad_jack_msg.wq,
@@ -1123,33 +897,42 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 
 	intelmaddata->mad_jack_wq = create_workqueue("sst_mad_jack_wq");
 	if (!intelmaddata->mad_jack_wq)
-		goto free_mad_jack_wq;
+		goto free_card;
 
-	ret_val = snd_intelmad_register_irq(intelmaddata);
+	ret_val = snd_intelmad_register_irq(intelmaddata,
+					info->irq_cache, info->size);
 	if (ret_val) {
 		pr_err("snd_intelmad_register_irq fail\n");
-		goto free_allocs;
+		goto free_mad_jack_wq;
 	}
 
 	/* internal function call to register device with ALSA */
 	ret_val = snd_intelmad_create(intelmaddata, card);
 	if (ret_val) {
 		pr_err("snd_intelmad_create failed\n");
-		goto free_allocs;
+		goto set_pvt_data;;
 	}
 	card->private_data = &intelmaddata;
 	snd_card_set_dev(card, &pdev->dev);
 	ret_val = snd_card_register(card);
 	if (ret_val) {
 		pr_err("snd_card_register failed\n");
-		goto free_allocs;
+		goto set_pvt_data;;
 	}
 
 	pr_debug("snd_intelmad_probe complete\n");
 	return ret_val;
 
+set_pvt_data:
+	card->private_data = NULL;
 free_mad_jack_wq:
 	destroy_workqueue(intelmaddata->mad_jack_wq);
+free_card:
+	snd_card_free(intelmaddata->card);
+free_sst:
+	unregister_sst_card(intelmaddata->sstdrv_ops);
+set_null_data:
+	platform_set_drvdata(pdev, NULL);
 free_allocs:
 	pr_err("probe failed\n");
 	snd_card_free(card);
@@ -1164,13 +947,11 @@ static int snd_intelmad_remove(struct platform_device *pdev)
 	struct snd_intelmad *intelmaddata = platform_get_drvdata(pdev);
 
 	if (intelmaddata) {
+		free_irq(intelmaddata->irq, intelmaddata);
 		snd_card_free(intelmaddata->card);
-		unregister_sst_card(intelmaddata->sstdrv_ops);
-		/* free allocated memory for internal context */
-		destroy_workqueue(intelmaddata->mad_jack_wq);
-		kfree(intelmaddata->sstdrv_ops);
-		kfree(intelmaddata);
 	}
+	intelmad_drv = NULL;
+	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
@@ -1178,8 +959,8 @@ static int snd_intelmad_remove(struct platform_device *pdev)
  *		Driver initialization and exit
  *********************************************************************/
 static const struct platform_device_id snd_intelmad_ids[] = {
-	{DRIVER_NAME_MRST, CPU_CHIP_LINCROFT},
-	{DRIVER_NAME_MFLD, CPU_CHIP_PENWELL},
+	{DRIVER_NAME_MRST, INFO(CPU_CHIP_LINCROFT, AUDINT_BASE, 1)},
+	{DRIVER_NAME_MFLD, INFO(CPU_CHIP_PENWELL, 0xFFFF7FCD, 1)},
 	{"", 0},
 
 };
diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
index 7b3dbf6..3201d5a 100644
--- a/drivers/staging/intel_sst/intelmid.h
+++ b/drivers/staging/intel_sst/intelmid.h
@@ -67,12 +67,17 @@
 #define MIN_VOL		0
 #define PLAYBACK_COUNT  1
 #define CAPTURE_COUNT	1
+#define ADC_ONE_LSB_MULTIPLIER 2346
+
+#define MID_JACK_HS_LONG_PRESS SND_JACK_BTN_0
+#define MID_JACK_HS_SHORT_PRESS SND_JACK_BTN_1
 
 extern int	sst_card_vendor_id;
 
 struct mad_jack {
 	struct snd_jack jack;
 	int jack_status;
+	int jack_dev_state;
 	struct timeval buttonpressed;
 	struct timeval  buttonreleased;
 };
@@ -84,6 +89,12 @@ struct mad_jack_msg_wq {
 
 };
 
+struct snd_intelmad_probe_info {
+	unsigned int cpu_id;
+	unsigned int irq_cache;
+	unsigned int size;
+};
+
 /**
  * struct snd_intelmad - intelmad driver structure
  *
@@ -122,6 +133,7 @@ struct snd_intelmad {
 	struct mad_jack jack[4];
 	int playback_cnt;
 	int capture_cnt;
+	u16 adc_address;
 	struct mad_jack_msg_wq  mad_jack_msg;
 	struct workqueue_struct *mad_jack_wq;
 	u8 jack_prev_state;
@@ -188,5 +200,7 @@ extern struct snd_control_val intelmad_ctrl_val[];
 extern struct snd_kcontrol_new snd_intelmad_controls_mrst[];
 extern struct snd_kcontrol_new snd_intelmad_controls_mfld[];
 extern struct snd_pmic_ops *intelmad_vendor_ops[];
+void sst_mad_send_jack_report(struct snd_jack *jack,
+			int buttonpressevent , int status);
 
 #endif /* __INTELMID_H */
diff --git a/drivers/staging/intel_sst/intelmid_adc_control.h b/drivers/staging/intel_sst/intelmid_adc_control.h
new file mode 100644
index 0000000..65d5c39
--- /dev/null
+++ b/drivers/staging/intel_sst/intelmid_adc_control.h
@@ -0,0 +1,193 @@
+#ifndef __INTELMID_ADC_CONTROL_H__
+#define __INTELMID_ADC_CONTROL_H_
+/*
+ *  intelmid_adc_control.h - Intel SST Driver for audio engine
+ *
+ *  Copyright (C) 2008-10 Intel Corporation
+ *  Authors:	R Durgadadoss <r.durgadoss@intel.com>
+ *		Dharageswari R <dharageswari.r@intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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 of the License.
+ *
+ *  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.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  Common private ADC declarations for SST
+ */
+
+
+#define MSIC_ADC1CNTL1		0x1C0
+#define MSIC_ADC_ENBL		0x10
+#define MSIC_ADC_START		0x08
+
+#define MSIC_ADC1CNTL3		0x1C2
+#define MSIC_ADCTHERM_ENBL	0x04
+#define MSIC_ADCRRDATA_ENBL	0x05
+
+#define MSIC_STOPBIT_MASK	16
+#define MSIC_ADCTHERM_MASK	4
+
+#define ADC_CHANLS_MAX		15 /* Number of ADC channels */
+#define ADC_LOOP_MAX		(ADC_CHANLS_MAX - 1)
+
+/* ADC channel code values */
+#define AUDIO_DETECT_CODE	0x06
+
+/* ADC base addresses */
+#define ADC_CHNL_START_ADDR	0x1C5	/* increments by 1 */
+#define ADC_DATA_START_ADDR     0x1D4   /* increments by 2 */
+
+
+/**
+ * configure_adc - enables/disables the ADC for conversion
+ * @val: zero: disables the ADC non-zero:enables the ADC
+ *
+ * Enable/Disable the ADC depending on the argument
+ *
+ * Can sleep
+ */
+static inline int configure_adc(int val)
+{
+	int ret;
+	struct sc_reg_access sc_access = {0,};
+
+
+	sc_access.reg_addr = MSIC_ADC1CNTL1;
+	ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
+	if (ret)
+		return ret;
+
+	if (val)
+		/* Enable and start the ADC */
+		sc_access.value |= (MSIC_ADC_ENBL | MSIC_ADC_START);
+	else
+		/* Just stop the ADC */
+		sc_access.value &= (~MSIC_ADC_START);
+	sc_access.reg_addr = MSIC_ADC1CNTL1;
+	return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
+}
+
+/**
+ * reset_stopbit - sets the stop bit to 0 on the given channel
+ * @addr: address of the channel
+ *
+ * Can sleep
+ */
+static inline int reset_stopbit(uint16_t addr)
+{
+	int ret;
+	struct sc_reg_access sc_access = {0,};
+	sc_access.reg_addr = addr;
+	ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
+	if (ret)
+		return ret;
+	/* Set the stop bit to zero */
+	sc_access.reg_addr = addr;
+	sc_access.value = (sc_access.value) & 0xEF;
+	return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
+}
+
+/**
+ * find_free_channel - finds an empty channel for conversion
+ *
+ * If the ADC is not enabled then start using 0th channel
+ * itself. Otherwise find an empty channel by looking for a
+ * channel in which the stopbit is set to 1. returns the index
+ * of the first free channel if succeeds or an error code.
+ *
+ * Context: can sleep
+ *
+ */
+static inline int find_free_channel(void)
+{
+	int ret;
+	int i;
+
+	struct sc_reg_access sc_access = {0,};
+
+	/* check whether ADC is enabled */
+	sc_access.reg_addr = MSIC_ADC1CNTL1;
+	ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
+	if (ret)
+		return ret;
+
+	if ((sc_access.value & MSIC_ADC_ENBL) == 0)
+		return 0;
+
+	/* ADC is already enabled; Looking for an empty channel */
+	for (i = 0; i < ADC_CHANLS_MAX; i++) {
+
+		sc_access.reg_addr = ADC_CHNL_START_ADDR + i;
+		ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
+		if (ret)
+			return ret;
+
+		if (sc_access.value & MSIC_STOPBIT_MASK) {
+			ret = i;
+			break;
+		}
+	}
+	return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
+}
+
+/**
+ * mid_initialize_adc - initializing the ADC
+ * @dev: our device structure
+ *
+ * Initialize the ADC for reading thermistor values. Can sleep.
+ */
+static inline int mid_initialize_adc(void)
+{
+	int base_addr, chnl_addr;
+	int ret;
+	static int channel_index;
+	struct sc_reg_access sc_access = {0,};
+
+	/* Index of the first channel in which the stop bit is set */
+	channel_index = find_free_channel();
+	if (channel_index < 0) {
+		pr_err("No free ADC channels");
+		return channel_index;
+	}
+
+	base_addr = ADC_CHNL_START_ADDR + channel_index;
+
+	if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
+		/* Reset stop bit for channels other than 0 and 12 */
+		ret = reset_stopbit(base_addr);
+		if (ret)
+			return ret;
+
+		/* Index of the first free channel */
+		base_addr++;
+		channel_index++;
+	}
+
+	/* Since this is the last channel, set the stop bit
+	   to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
+	sc_access.reg_addr = base_addr;
+	sc_access.value = AUDIO_DETECT_CODE | 0x10;
+	ret = sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
+	if (ret) {
+		pr_err("unable to enable ADC");
+		return ret;
+	}
+
+	chnl_addr = ADC_DATA_START_ADDR + 2 * channel_index;
+	pr_debug("mid_initialize : %x", chnl_addr);
+	configure_adc(1);
+	return chnl_addr;
+}
+#endif
+
diff --git a/drivers/staging/intel_sst/intelmid_ctrl.c b/drivers/staging/intel_sst/intelmid_ctrl.c
index dbe29c3..2c3ee94 100644
--- a/drivers/staging/intel_sst/intelmid_ctrl.c
+++ b/drivers/staging/intel_sst/intelmid_ctrl.c
@@ -29,7 +29,6 @@
 
 #include <sound/core.h>
 #include <sound/control.h>
-#include "jack.h"
 #include "intel_sst.h"
 #include "intel_sst_ioctl.h"
 #include "intelmid_snd_control.h"
diff --git a/drivers/staging/intel_sst/intelmid_msic_control.c b/drivers/staging/intel_sst/intelmid_msic_control.c
index 976091b..70cdb16 100644
--- a/drivers/staging/intel_sst/intelmid_msic_control.c
+++ b/drivers/staging/intel_sst/intelmid_msic_control.c
@@ -89,6 +89,7 @@ static int msic_init_card(void)
 	snd_msic_ops.cap_on = 0;
 	snd_msic_ops.input_dev_id = DMIC; /*def dev*/
 	snd_msic_ops.output_dev_id = STEREO_HEADPHONE;
+	snd_msic_ops.jack_interrupt_status = false;
 	pr_debug("msic init complete!!\n");
 	return 0;
 }
@@ -109,6 +110,9 @@ static int msic_line_out_restore(u8 value)
 	struct sc_reg_access vib2_drv_en[] = {
 		{0x25d, 0x20, 0x20},
 	};
+	struct sc_reg_access pmode_enable[] = {
+		{0x381, 0x10, 0x10},
+	};
 	int retval = 0;
 
 	pr_debug("msic_lineout_restore_lineout_dev:%d\n", value);
@@ -126,6 +130,9 @@ static int msic_line_out_restore(u8 value)
 	case IHF:
 		pr_debug("Selecting Lineout-IHF-restore\n");
 		retval = sst_sc_reg_access(ihf_drv_en, PMIC_READ_MODIFY, 1);
+		if (retval)
+			return retval;
+		retval = sst_sc_reg_access(pmode_enable, PMIC_READ_MODIFY, 1);
 		break;
 	case VIBRA1:
 		pr_debug("Selecting Lineout-Vibra1-restore\n");
@@ -255,6 +262,12 @@ static int msic_set_selected_lineout_dev(u8 value)
 	struct sc_reg_access lout_def[] = {
 		{0x25e, 0x66, 0x0},
 	};
+	struct sc_reg_access pmode_disable[] = {
+		{0x381, 0x00, 0x10},
+	};
+	struct sc_reg_access pmode_enable[] = {
+		{0x381, 0x10, 0x10},
+	};
 	int retval = 0;
 
 	pr_debug("msic_set_selected_lineout_dev:%d\n", value);
@@ -268,29 +281,49 @@ static int msic_set_selected_lineout_dev(u8 value)
 		if (snd_msic_ops.pb_on)
 			retval = sst_sc_reg_access(lout_hs,
 					PMIC_READ_MODIFY, 2);
+			if (retval)
+				return retval;
+			retval = sst_sc_reg_access(pmode_disable,
+					PMIC_READ_MODIFY, 1);
 		break;
 	case IHF:
 		pr_debug("Selecting Lineout-IHF\n");
 		if (snd_msic_ops.pb_on)
 			retval = sst_sc_reg_access(lout_ihf,
 							PMIC_READ_MODIFY, 2);
+			if (retval)
+				return retval;
+			retval = sst_sc_reg_access(pmode_enable,
+					PMIC_READ_MODIFY, 1);
 		break;
 	case VIBRA1:
 		pr_debug("Selecting Lineout-Vibra1\n");
 		if (snd_msic_ops.pb_on)
 			retval = sst_sc_reg_access(lout_vibra1,
 							PMIC_READ_MODIFY, 2);
+			if (retval)
+				return retval;
+			retval = sst_sc_reg_access(pmode_disable,
+					PMIC_READ_MODIFY, 1);
 		break;
 	case VIBRA2:
 		pr_debug("Selecting Lineout-VIBRA2\n");
 		if (snd_msic_ops.pb_on)
 			retval = sst_sc_reg_access(lout_vibra2,
 							PMIC_READ_MODIFY, 2);
+			if (retval)
+				return retval;
+			retval = sst_sc_reg_access(pmode_disable,
+					PMIC_READ_MODIFY, 1);
 		break;
 	case NONE:
 		pr_debug("Selecting Lineout-NONE\n");
 			retval = sst_sc_reg_access(lout_def,
 							PMIC_WRITE, 1);
+			if (retval)
+				return retval;
+			retval = sst_sc_reg_access(pmode_disable,
+					PMIC_READ_MODIFY, 1);
 		break;
 	default:
 		return -EINVAL;
@@ -311,11 +344,12 @@ static int msic_power_up_pb(unsigned int device)
 	};
 	struct sc_reg_access vhs[] = {
 		/*  VHSP */
-		{0x0DC, 0xFF, 0},
+		{0x0DC, 0x3D, 0},
 		/*  VHSN */
 		{0x0DD, 0x3F, 0},
 	};
 	struct sc_reg_access hsdac[] = {
+		{0x382, 0x40, 0x40},
 		/*  disable driver */
 		{0x25D, 0x0, 0x43},
 		/* DAC CONFIG ; both HP, LP on */
@@ -401,7 +435,7 @@ static int msic_power_up_pb(unsigned int device)
 		snd_msic_ops.pbhs_on = 1;
 		if (snd_msic_ops.output_dev_id == STEREO_HEADPHONE) {
 			sst_sc_reg_access(vhs, PMIC_WRITE, 2);
-			sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 2);
+			sst_sc_reg_access(hsdac, PMIC_READ_MODIFY, 3);
 			sst_sc_reg_access(hs_filter, PMIC_WRITE, 2);
 			sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 4);
 		} else {
@@ -555,6 +589,7 @@ static int msic_power_down_pb(unsigned int device)
 	struct sc_reg_access hs_off[] = {
 		{0x257, 0x00, 0x03},
 		{0x250, 0x00, 0x30},
+		{0x382, 0x00, 0x40},
 	};
 	struct sc_reg_access ihf_mute[] = {
 		{0x25B, 0x80, 0x80},
@@ -573,6 +608,9 @@ static int msic_power_down_pb(unsigned int device)
 	struct sc_reg_access lout_off[] = {
 		{0x25e, 0x66, 0x00},
 	};
+	struct sc_reg_access pmode_disable[] = {
+		{0x381, 0x00, 0x10},
+	};
 
 
 
@@ -583,7 +621,7 @@ static int msic_power_down_pb(unsigned int device)
 		sst_sc_reg_access(hs_mute, PMIC_READ_MODIFY, 3);
 		drv_enable[0].mask = 0x43;
 		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
-		sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 2);
+		sst_sc_reg_access(hs_off, PMIC_READ_MODIFY, 3);
 		if (snd_msic_ops.lineout_dev_id == HEADSET)
 			sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
 		break;
@@ -593,8 +631,10 @@ static int msic_power_down_pb(unsigned int device)
 		drv_enable[0].mask = 0x0C;
 		sst_sc_reg_access(drv_enable, PMIC_READ_MODIFY, 1);
 		sst_sc_reg_access(ihf_off, PMIC_READ_MODIFY, 2);
-		if (snd_msic_ops.lineout_dev_id == IHF)
+		if (snd_msic_ops.lineout_dev_id == IHF) {
 			sst_sc_reg_access(lout_off, PMIC_WRITE, 1);
+			sst_sc_reg_access(pmode_disable, PMIC_READ_MODIFY, 1);
+		}
 		break;
 
 	case SND_SST_DEVICE_VIBRA:
@@ -777,6 +817,210 @@ static int msic_get_vol(int dev_id, int *value)
 	return 0;
 }
 
+static int msic_set_headset_state(int state)
+{
+	struct sc_reg_access hs_enable[] = {
+		{0x25D, 0x03, 0x03},
+	};
+
+	if (state)
+		/*enable*/
+		sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 1);
+	else {
+		hs_enable[0].value = 0;
+		sst_sc_reg_access(hs_enable, PMIC_READ_MODIFY, 1);
+	}
+	return 0;
+}
+
+static int msic_enable_mic_bias(void)
+{
+	struct sc_reg_access jack_interrupt_reg[] = {
+		{0x0DB, 0x07, 0x00},
+
+	};
+	struct sc_reg_access jack_bias_reg[] = {
+		{0x247, 0x0C, 0x0C},
+	};
+
+	sst_sc_reg_access(jack_interrupt_reg, PMIC_WRITE, 1);
+	sst_sc_reg_access(jack_bias_reg, PMIC_READ_MODIFY, 1);
+	return 0;
+}
+
+static int msic_disable_mic_bias(void)
+{
+	if (snd_msic_ops.jack_interrupt_status == true)
+		return 0;
+	if (!(snd_msic_ops.pb_on || snd_msic_ops.cap_on))
+		msic_power_down();
+	return 0;
+}
+
+static int msic_disable_jack_btn(void)
+{
+	struct sc_reg_access btn_disable[] = {
+		{0x26C, 0x00, 0x01}
+	};
+
+	if (!(snd_msic_ops.pb_on || snd_msic_ops.cap_on))
+		msic_power_down();
+	snd_msic_ops.jack_interrupt_status = false;
+	return sst_sc_reg_access(btn_disable, PMIC_READ_MODIFY, 1);
+}
+
+static int msic_enable_jack_btn(void)
+{
+	struct sc_reg_access btn_enable[] = {
+			{0x26b, 0x77, 0x00},
+			{0x26C, 0x01, 0x00},
+	};
+	return sst_sc_reg_access(btn_enable, PMIC_WRITE, 2);
+}
+static int msic_convert_adc_to_mvolt(unsigned int mic_bias)
+{
+	return (ADC_ONE_LSB_MULTIPLIER * mic_bias) / 1000;
+}
+int msic_get_headset_state(int mic_bias)
+{
+	struct sc_reg_access msic_hs_toggle[] = {
+		{0x070, 0x00, 0x01},
+	};
+	if (mic_bias >= 0 && mic_bias < 400) {
+
+		pr_debug("Detected Headphone!!!\n");
+		sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
+
+	} else if (mic_bias > 400 && mic_bias < 650) {
+
+		pr_debug("Detected American headset\n");
+		msic_hs_toggle[0].value = 0x01;
+		sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
+
+	} else if (mic_bias >= 650 && mic_bias < 2000) {
+
+		pr_debug("Detected Headset!!!\n");
+		sst_sc_reg_access(msic_hs_toggle, PMIC_READ_MODIFY, 1);
+		/*power on jack and btn*/
+		snd_msic_ops.jack_interrupt_status = true;
+		msic_enable_jack_btn();
+		msic_enable_mic_bias();
+		return SND_JACK_HEADSET;
+
+	} else
+		pr_debug("Detected Open Cable!!!\n");
+
+	return SND_JACK_HEADPHONE;
+}
+
+static int msic_get_mic_bias(void *arg)
+{
+	struct snd_intelmad *intelmad_drv = (struct snd_intelmad *)arg;
+	u16 adc_adr = intelmad_drv->adc_address;
+	u16 adc_val;
+	int ret;
+	struct sc_reg_access adc_ctrl3[2] = {
+			{0x1C2, 0x05, 0x0},
+	};
+
+	struct sc_reg_access audio_adc_reg1 = {0,};
+	struct sc_reg_access audio_adc_reg2 = {0,};
+
+	msic_enable_mic_bias();
+	/* Enable the msic for conversion before reading */
+	ret = sst_sc_reg_access(adc_ctrl3, PMIC_WRITE, 1);
+	if (ret)
+		return ret;
+	adc_ctrl3[0].value = 0x04;
+	/* Re-toggle the RRDATARD bit */
+	ret = sst_sc_reg_access(adc_ctrl3, PMIC_WRITE, 1);
+	if (ret)
+		return ret;
+
+	audio_adc_reg1.reg_addr = adc_adr;
+	/* Read the higher bits of data */
+	msleep(1000);
+	ret = sst_sc_reg_access(&audio_adc_reg1, PMIC_READ, 1);
+	if (ret)
+		return ret;
+	pr_debug("adc read value %x", audio_adc_reg1.value);
+
+	/* Shift bits to accomodate the lower two data bits */
+	adc_val = (audio_adc_reg1.value << 2);
+	adc_adr++;
+	audio_adc_reg2. reg_addr = adc_adr;
+	ret = sst_sc_reg_access(&audio_adc_reg2, PMIC_READ, 1);
+	if (ret)
+		return ret;
+	pr_debug("adc read value %x", audio_adc_reg2.value);
+
+	/* Adding lower two bits to the higher bits */
+	audio_adc_reg2.value &= 03;
+	adc_val += audio_adc_reg2.value;
+
+	pr_debug("ADC value 0x%x", adc_val);
+	msic_disable_mic_bias();
+	return adc_val;
+}
+
+static void msic_pmic_irq_cb(void *cb_data, u8 intsts)
+{
+	struct mad_jack *mjack = NULL;
+	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
+	struct snd_intelmad *intelmaddata = cb_data;
+	int retval = 0;
+
+	pr_debug("value returned = 0x%x\n", intsts);
+
+	if (snd_msic_ops.card_status == SND_CARD_UN_INIT) {
+		retval = msic_init_card();
+		if (retval)
+			return;
+	  }
+
+	mjack = &intelmaddata->jack[0];
+	if (intsts & 0x1) {
+		pr_debug("MAD short_push detected\n");
+		present = SND_JACK_BTN_0;
+		jack_event_flag = buttonpressflag = 1;
+		mjack->jack.type = SND_JACK_BTN_0;
+		mjack->jack.key[0] = BTN_0 ;
+	}
+
+	if (intsts & 0x2) {
+		pr_debug(":MAD long_push detected\n");
+		jack_event_flag = buttonpressflag = 1;
+		mjack->jack.type = present = SND_JACK_BTN_1;
+		mjack->jack.key[1] = BTN_1;
+	}
+
+	if (intsts & 0x4) {
+		unsigned int mic_bias;
+		jack_event_flag = 1;
+		buttonpressflag = 0;
+		mic_bias = msic_get_mic_bias(intelmaddata);
+		pr_debug("mic_bias = %d\n", mic_bias);
+		mic_bias = msic_convert_adc_to_mvolt(mic_bias);
+		pr_debug("mic_bias after conversion = %d mV\n", mic_bias);
+		mjack->jack_dev_state = msic_get_headset_state(mic_bias);
+		mjack->jack.type = present = mjack->jack_dev_state;
+	}
+
+	if (intsts & 0x8) {
+		mjack->jack.type = mjack->jack_dev_state;
+		present = 0;
+		jack_event_flag = 1;
+		buttonpressflag = 0;
+		msic_disable_jack_btn();
+		msic_disable_mic_bias();
+	}
+	if (jack_event_flag)
+		sst_mad_send_jack_report(&mjack->jack,
+					buttonpressflag, present);
+}
+
+
+
 struct snd_pmic_ops snd_msic_ops = {
 	.set_input_dev	=	msic_set_selected_input_dev,
 	.set_output_dev =	msic_set_selected_output_dev,
@@ -795,5 +1039,9 @@ struct snd_pmic_ops snd_msic_ops = {
 	.power_up_pmic_cp =	msic_power_up_cp,
 	.power_down_pmic_pb =	msic_power_down_pb,
 	.power_down_pmic_cp =	msic_power_down_cp,
-	.power_down_pmic =	msic_power_down,
+	.power_down_pmic	=	msic_power_down,
+	.pmic_irq_cb	=	msic_pmic_irq_cb,
+	.pmic_jack_enable = msic_enable_mic_bias,
+	.pmic_get_mic_bias	= msic_get_mic_bias,
+	.pmic_set_headset_state = msic_set_headset_state,
 };
diff --git a/drivers/staging/intel_sst/intelmid_pvt.c b/drivers/staging/intel_sst/intelmid_pvt.c
index 3ba9daf..90e0e64 100644
--- a/drivers/staging/intel_sst/intelmid_pvt.c
+++ b/drivers/staging/intel_sst/intelmid_pvt.c
@@ -31,7 +31,6 @@
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
-#include "jack.h"
 #include "intel_sst.h"
 #include "intel_sst_ioctl.h"
 #include "intelmid_snd_control.h"
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
index 964c412..b8dfdb9 100644
--- a/drivers/staging/intel_sst/intelmid_v0_control.c
+++ b/drivers/staging/intel_sst/intelmid_v0_control.c
@@ -30,9 +30,10 @@
 
 #include <linux/pci.h>
 #include <linux/file.h>
+#include <sound/control.h>
 #include "intel_sst.h"
 #include "intelmid_snd_control.h"
-
+#include "intelmid.h"
 
 enum _reg_v1 {
 	VOICEPORT1 = 0x180,
@@ -64,6 +65,7 @@ enum _reg_v1 {
 };
 
 int rev_id = 0x20;
+static bool jack_det_enabled;
 
 /****
  * fs_init_card - initialize the sound card
@@ -494,10 +496,7 @@ static int fs_set_selected_output_dev(u8 value)
 
 	}
 }
-static int fs_set_selected_lineout_dev(u8 value)
-{
-	return 0;
-}
+
 static int fs_set_mute(int dev_id, u8 value)
 {
 	struct sc_reg_access sc_access[6] = {{0,},};
@@ -756,10 +755,93 @@ static int fs_get_vol(int dev_id, int *value)
 	return retval;
 }
 
+static void fs_pmic_irq_enable(void *data)
+{
+	struct snd_intelmad *intelmaddata = data;
+	struct sc_reg_access sc_access[] = {
+				{0x187, 0x00, MASK7},
+				{0x188, 0x10, MASK4},
+				{0x18b, 0x10, MASK4},
+	};
+
+	struct sc_reg_access sc_access_write[] = {
+				{0x198, 0x00, 0x0},
+	};
+	pr_debug("Audio interrupt enable\n");
+	sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
+	sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
+
+	intelmaddata->jack[0].jack_status = 0;
+	/*intelmaddata->jack[1].jack_status = 0;*/
+
+	jack_det_enabled = true;
+	return;
+}
+
+static void fs_pmic_irq_cb(void *cb_data, u8 value)
+{
+	struct mad_jack *mjack = NULL;
+	struct snd_intelmad *intelmaddata = cb_data;
+	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
+
+	mjack = &intelmaddata->jack[0];
+
+	if (value & 0x4) {
+		if (!jack_det_enabled)
+			fs_pmic_irq_enable(intelmaddata);
+
+		/* send headphone detect */
+		pr_debug(":MAD headphone %d\n", value & 0x4);
+		present = !(mjack->jack_status);
+		mjack->jack_status = present;
+		jack_event_flag = 1;
+		mjack->jack.type = SND_JACK_HEADPHONE;
+	}
+
+	if (value & 0x2) {
+		/* send short push */
+		pr_debug(":MAD short push %d\n", value & 0x2);
+		present = 1;
+		jack_event_flag = 1;
+		buttonpressflag = 1;
+		mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
+	}
+
+	if (value & 0x1) {
+		/* send long push */
+		pr_debug(":MAD long push %d\n", value & 0x1);
+		present = 1;
+		jack_event_flag = 1;
+		buttonpressflag = 1;
+		mjack->jack.type = MID_JACK_HS_LONG_PRESS;
+	}
+
+	if (value & 0x8) {
+		if (!jack_det_enabled)
+			fs_pmic_irq_enable(intelmaddata);
+		/* send headset detect */
+		pr_debug(":MAD headset = %d\n", value & 0x8);
+		present = !(mjack->jack_status);
+		mjack->jack_status = present;
+		jack_event_flag = 1;
+		mjack->jack.type = SND_JACK_HEADSET;
+	}
+
+
+	if (jack_event_flag)
+		sst_mad_send_jack_report(&mjack->jack,
+						buttonpressflag, present);
+
+	return;
+}
+static int fs_jack_enable(void)
+{
+	return 0;
+}
+
 struct snd_pmic_ops snd_pmic_ops_fs = {
 	.set_input_dev = fs_set_selected_input_dev,
 	.set_output_dev = fs_set_selected_output_dev,
-	.set_lineout_dev = fs_set_selected_lineout_dev,
 	.set_mute = fs_set_mute,
 	.get_mute = fs_get_mute,
 	.set_vol = fs_set_vol,
@@ -769,9 +851,16 @@ struct snd_pmic_ops snd_pmic_ops_fs = {
 	.set_pcm_voice_params = fs_set_pcm_voice_params,
 	.set_voice_port = fs_set_voice_port,
 	.set_audio_port = fs_set_audio_port,
-	.power_up_pmic_pb = fs_power_up_pb,
-	.power_up_pmic_cp = fs_power_up_cp,
-	.power_down_pmic_pb = fs_power_down_pb,
-	.power_down_pmic_cp = fs_power_down_cp,
-	.power_down_pmic = fs_power_down,
+	.power_up_pmic_pb =	fs_power_up_pb,
+	.power_up_pmic_cp =	fs_power_up_cp,
+	.power_down_pmic_pb =	fs_power_down_pb,
+	.power_down_pmic_cp =	fs_power_down_cp,
+	.power_down_pmic	=	fs_power_down,
+	.pmic_irq_cb	=	fs_pmic_irq_cb,
+	/*
+	 * Jack detection enabling
+	 * need be delayed till first IRQ happen.
+	 */
+	.pmic_irq_enable =	NULL,
+	.pmic_jack_enable = fs_jack_enable,
 };
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c
index 4f2b34f..9d00728 100644
--- a/drivers/staging/intel_sst/intelmid_v1_control.c
+++ b/drivers/staging/intel_sst/intelmid_v1_control.c
@@ -32,7 +32,6 @@
 #include <linux/file.h>
 #include <asm/mrst.h>
 #include <sound/pcm.h>
-#include "jack.h"
 #include <sound/pcm_params.h>
 #include <sound/control.h>
 #include <sound/initval.h>
@@ -585,10 +584,6 @@ static int mx_set_selected_input_dev(u8 dev_id)
 	}
 	return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
 }
-static int mx_set_selected_lineout_dev(u8 dev_id)
-{
-	return 0;
-}
 
 static int mx_set_mute(int dev_id, u8 value)
 {
@@ -836,10 +831,132 @@ static int mx_get_vol(int dev_id, int *value)
 	return retval;
 }
 
+static u8 mx_get_jack_status(void)
+{
+	struct sc_reg_access sc_access_read = {0,};
+
+	sc_access_read.reg_addr = 0x201;
+	sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
+	pr_debug("value returned = 0x%x\n", sc_access_read.value);
+	return sc_access_read.value;
+}
+
+static void mx_pmic_irq_enable(void *data)
+{
+	struct snd_intelmad *intelmaddata = data;
+
+	intelmaddata->jack_prev_state = 0xc0;
+	return;
+}
+
+static void mx_pmic_irq_cb(void *cb_data, u8 intsts)
+{
+	u8 jack_cur_status, jack_prev_state = 0;
+	struct mad_jack *mjack = NULL;
+	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
+	time_t  timediff;
+	struct snd_intelmad *intelmaddata = cb_data;
+
+	mjack = &intelmaddata->jack[0];
+	if (intsts & 0x2) {
+		jack_cur_status = mx_get_jack_status();
+		jack_prev_state = intelmaddata->jack_prev_state;
+		if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x40)) {
+			/*headset insert detected. */
+			pr_debug("MAD headset inserted\n");
+			present = 1;
+			jack_event_flag = 1;
+			mjack->jack_status = 1;
+			mjack->jack.type = SND_JACK_HEADSET;
+		}
+
+		if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x00)) {
+			/* headphone insert detected. */
+			pr_debug("MAD headphone inserted\n");
+			present = 1;
+			jack_event_flag = 1;
+			mjack->jack.type = SND_JACK_HEADPHONE;
+		}
+
+		if ((jack_prev_state == 0x40) && (jack_cur_status == 0xc0)) {
+			/* headset remove detected. */
+			pr_debug("MAD headset removed\n");
+
+			present = 0;
+			jack_event_flag = 1;
+			mjack->jack_status = 0;
+			mjack->jack.type = SND_JACK_HEADSET;
+		}
+
+		if ((jack_prev_state == 0x00) && (jack_cur_status == 0xc0)) {
+			/* headphone remove detected. */
+			pr_debug("MAD headphone removed\n");
+			present = 0;
+			jack_event_flag = 1;
+			mjack->jack.type = SND_JACK_HEADPHONE;
+		}
+
+		if ((jack_prev_state == 0x40) && (jack_cur_status == 0x00)) {
+			/* button pressed */
+			do_gettimeofday(&mjack->buttonpressed);
+			pr_debug("MAD button press detected\n");
+		}
+
+		if ((jack_prev_state == 0x00) && (jack_cur_status == 0x40)) {
+			if (mjack->jack_status) {
+				/*button pressed */
+				do_gettimeofday(
+					&mjack->buttonreleased);
+				/*button pressed */
+				pr_debug("MAD Button Released detected\n");
+				timediff = mjack->buttonreleased.tv_sec -
+					mjack->buttonpressed.tv_sec;
+				buttonpressflag = 1;
+
+				if (timediff > 1) {
+					pr_debug("MAD long press dtd\n");
+					/* send headphone detect/undetect */
+					present = 1;
+					jack_event_flag = 1;
+					mjack->jack.type =
+							MID_JACK_HS_LONG_PRESS;
+				} else {
+					pr_debug("MAD short press dtd\n");
+					/* send headphone detect/undetect */
+					present = 1;
+					jack_event_flag = 1;
+					mjack->jack.type =
+						MID_JACK_HS_SHORT_PRESS;
+				}
+			} else {
+				/***workaround for maxim
+				hw issue,0x00 t 0x40 is not
+				a valid transiton for Headset insertion */
+				/*headset insert detected. */
+				pr_debug("MAD headset inserted\n");
+				present = 1;
+				jack_event_flag = 1;
+				mjack->jack_status = 1;
+				mjack->jack.type = SND_JACK_HEADSET;
+			}
+		}
+		intelmaddata->jack_prev_state  = jack_cur_status;
+		pr_debug("mx_pmic_irq_cb prv_state= 0x%x\n",
+					intelmaddata->jack_prev_state);
+	}
+
+	if (jack_event_flag)
+		sst_mad_send_jack_report(&mjack->jack,
+						buttonpressflag, present);
+}
+static int mx_jack_enable(void)
+{
+	return 0;
+}
+
 struct snd_pmic_ops snd_pmic_ops_mx = {
 	.set_input_dev = mx_set_selected_input_dev,
 	.set_output_dev = mx_set_selected_output_dev,
-	.set_lineout_dev = mx_set_selected_lineout_dev,
 	.set_mute = mx_set_mute,
 	.get_mute = mx_get_mute,
 	.set_vol = mx_set_vol,
@@ -849,10 +966,13 @@ struct snd_pmic_ops snd_pmic_ops_mx = {
 	.set_pcm_voice_params = mx_set_pcm_voice_params,
 	.set_voice_port = mx_set_voice_port,
 	.set_audio_port = mx_set_audio_port,
-	.power_up_pmic_pb = mx_power_up_pb,
-	.power_up_pmic_cp = mx_power_up_cp,
-	.power_down_pmic_pb = mx_power_down_pb,
-	.power_down_pmic_cp = mx_power_down_cp,
-	.power_down_pmic =  mx_power_down,
+	.power_up_pmic_pb =	mx_power_up_pb,
+	.power_up_pmic_cp =	mx_power_up_cp,
+	.power_down_pmic_pb =	mx_power_down_pb,
+	.power_down_pmic_cp =	mx_power_down_cp,
+	.power_down_pmic =	mx_power_down,
+	.pmic_irq_cb	 =	mx_pmic_irq_cb,
+	.pmic_irq_enable =	mx_pmic_irq_enable,
+	.pmic_jack_enable =	mx_jack_enable,
 };
 
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index a0cd227..10762d7 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -31,8 +31,10 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/file.h>
+#include <sound/control.h>
 #include "intel_sst.h"
 #include "intelmid_snd_control.h"
+#include "intelmid.h"
 
 enum reg_v3 {
 	VAUDIOCNT = 0x51,
@@ -885,10 +887,7 @@ static int nc_set_selected_input_dev(u8 value)
 	}
 	return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
 }
-static int nc_set_selected_lineout_dev(u8 dev_id)
-{
-	return 0;
-}
+
 static int nc_get_mute(int dev_id, u8 *value)
 {
 	int retval = 0, mask = 0;
@@ -990,10 +989,66 @@ static int nc_get_vol(int dev_id, int *value)
 	return retval;
 }
 
+static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
+{
+	u8 value = 0;
+	struct mad_jack *mjack = NULL;
+	unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
+	struct snd_intelmad *intelmaddata = cb_data;
+	struct sc_reg_access sc_access_read = {0,};
+
+	sc_access_read.reg_addr = 0x132;
+	sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
+	value = (sc_access_read.value);
+	pr_debug("value returned = 0x%x\n", value);
+
+	mjack = &intelmaddata->jack[0];
+	if (intsts & 0x1) {
+		pr_debug("SST DBG:MAD headset detected\n");
+		/* send headset detect/undetect */
+		present = (value == 0x1) ? 1 : 0;
+		jack_event_flag = 1;
+		mjack->jack.type = SND_JACK_HEADSET;
+	}
+
+	if (intsts & 0x2) {
+		pr_debug(":MAD headphone detected\n");
+		/* send headphone detect/undetect */
+		present = (value == 0x2) ? 1 : 0;
+		jack_event_flag = 1;
+		mjack->jack.type = SND_JACK_HEADPHONE;
+	}
+
+	if (intsts & 0x4) {
+		pr_debug("MAD short push detected\n");
+		/* send short push */
+		present = 1;
+		jack_event_flag = 1;
+		buttonpressflag = 1;
+		mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
+	}
+
+	if (intsts & 0x8) {
+		pr_debug(":MAD long push detected\n");
+		/* send long push */
+		present = 1;
+		jack_event_flag = 1;
+		buttonpressflag = 1;
+		mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
+	}
+
+	if (jack_event_flag)
+		sst_mad_send_jack_report(&mjack->jack,
+					buttonpressflag, present);
+}
+static int nc_jack_enable(void)
+{
+	return 0;
+}
+
 struct snd_pmic_ops snd_pmic_ops_nc = {
 	.set_input_dev	=	nc_set_selected_input_dev,
 	.set_output_dev =	nc_set_selected_output_dev,
-	.set_lineout_dev =	nc_set_selected_lineout_dev,
 	.set_mute	=	nc_set_mute,
 	.get_mute	=	nc_get_mute,
 	.set_vol	=	nc_set_vol,
@@ -1007,5 +1062,7 @@ struct snd_pmic_ops snd_pmic_ops_nc = {
 	.power_up_pmic_cp =	nc_power_up_cp,
 	.power_down_pmic_pb =	nc_power_down_pb,
 	.power_down_pmic_cp =	nc_power_down_cp,
-	.power_down_pmic =	nc_power_down,
+	.power_down_pmic	=	nc_power_down,
+	.pmic_irq_cb	=	nc_pmic_irq_cb,
+	.pmic_jack_enable =	nc_jack_enable,
 };
diff --git a/drivers/staging/intel_sst/jack.h b/drivers/staging/intel_sst/jack.h
deleted file mode 100644
index 9a6e483..0000000
--- a/drivers/staging/intel_sst/jack.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* Temporary staging glue */
-
-#include <sound/jack.h>
-
-/* These want adding to jack.h as enum entries once approved */
-
-#define SND_JACK_HS_SHORT_PRESS 	(SND_JACK_HEADSET | 0x0020)
-#define	SND_JACK_HS_LONG_PRESS		(SND_JACK_HEADSET | 0x0040)
-
-


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 09/23] intel_sst: Set de-bounce time
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (7 preceding siblings ...)
  2011-05-03 16:33 ` [PATCH 08/23] intel_sst: rework jack implementation Alan Cox
@ 2011-05-03 16:33 ` Alan Cox
  2011-05-03 16:33 ` [PATCH 10/23] intel_sst: Enable recording via HS_MIC Alan Cox
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:33 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

In order to make jack detection behave properly, we have to set
the de-bounce time, otherwise, some weird events happens:
e.g. no plug-out event seen.

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 10762d7..48ef2fa 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -84,6 +84,7 @@ enum reg_v3 {
 	HPLMIXSEL = 0x12b,
 	HPRMIXSEL = 0x12c,
 	LOANTIPOP = 0x12d,
+	AUXDBNC = 0x12f,
 };
 
 /****
@@ -860,7 +861,10 @@ static int nc_set_selected_input_dev(u8 value)
 		sc_access[3].reg_addr = 0x105;
 		sc_access[3].value = 0x40;
 		sc_access[3].mask = MASK6;
-		num_val = 4;
+		sc_access[4].reg_addr = AUXDBNC;
+		sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3|MASK2|MASK1|MASK0;
+		sc_access[4].value = 0xff;
+		num_val = 5;
 		break;
 
 	case DMIC:


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 10/23] intel_sst: Enable recording via HS_MIC
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (8 preceding siblings ...)
  2011-05-03 16:33 ` [PATCH 09/23] intel_sst: Set de-bounce time Alan Cox
@ 2011-05-03 16:33 ` Alan Cox
  2011-05-03 16:33 ` [PATCH 11/23] intel_sst: Enable recording via DMIC Alan Cox
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:33 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

We may need to make some of this board specific eventually.

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 48ef2fa..cae7bc2 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -864,7 +864,10 @@ static int nc_set_selected_input_dev(u8 value)
 		sc_access[4].reg_addr = AUXDBNC;
 		sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3|MASK2|MASK1|MASK0;
 		sc_access[4].value = 0xff;
-		num_val = 5;
+		sc_access[5].reg_addr = ADCSAMPLERATE;
+		sc_access[5].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
+		sc_access[5].value = 0xc8;
+		num_val = 6;
 		break;
 
 	case DMIC:


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 11/23] intel_sst: Enable recording via DMIC
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (9 preceding siblings ...)
  2011-05-03 16:33 ` [PATCH 10/23] intel_sst: Enable recording via HS_MIC Alan Cox
@ 2011-05-03 16:33 ` Alan Cox
  2011-05-03 16:34 ` [PATCH 12/23] intel_sst: Headphone Automute support Alan Cox
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:33 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

We may need to make some of this board specific eventually

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index cae7bc2..3d90f45 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -881,12 +881,12 @@ static int nc_set_selected_input_dev(u8 value)
 		sc_access[2].reg_addr = 0x10a;
 		sc_access[2].value = 0x40;
 		sc_access[2].mask = MASK6;
-		sc_access[3].reg_addr = 0x109;
+		sc_access[3].reg_addr = LILSEL;
 		sc_access[3].mask = MASK6;
 		sc_access[3].value = 0x00;
-		sc_access[4].reg_addr = 0x104;
-		sc_access[4].value = 0x3C;
-		sc_access[4].mask = 0xff;
+		sc_access[4].reg_addr = ADCSAMPLERATE;
+		sc_access[4].mask =  MASK7|MASK6|MASK5|MASK4|MASK3;
+		sc_access[4].value = 0x33;
 		num_val = 5;
 		break;
 	default:


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 12/23] intel_sst: Headphone Automute support
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (10 preceding siblings ...)
  2011-05-03 16:33 ` [PATCH 11/23] intel_sst: Enable recording via DMIC Alan Cox
@ 2011-05-03 16:34 ` Alan Cox
  2011-05-03 16:34 ` [PATCH 13/23] intel_sst: move jack detection related configs to init time Alan Cox
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: xingchao <xingchao.wang@intel.com>

When detected a Jack event, Audio sound routes between internal speaker
and headphone/headset automatically.

Signed-off-by: xingchao <xingchao.wang@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 3d90f45..7cae970 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -996,6 +996,19 @@ static int nc_get_vol(int dev_id, int *value)
 	return retval;
 }
 
+static void hp_automute(enum snd_jack_types type, int present)
+{
+	u8 in = DMIC;
+	u8 out = INTERNAL_SPKR;
+	if (present) {
+		if (type == SND_JACK_HEADSET)
+			in = HS_MIC;
+		out = STEREO_HEADPHONE;
+	}
+	nc_set_selected_input_dev(in);
+	nc_set_selected_output_dev(out);
+}
+
 static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
 {
 	u8 value = 0;
@@ -1016,6 +1029,7 @@ static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
 		present = (value == 0x1) ? 1 : 0;
 		jack_event_flag = 1;
 		mjack->jack.type = SND_JACK_HEADSET;
+		hp_automute(SND_JACK_HEADSET, present);
 	}
 
 	if (intsts & 0x2) {
@@ -1024,6 +1038,7 @@ static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
 		present = (value == 0x2) ? 1 : 0;
 		jack_event_flag = 1;
 		mjack->jack.type = SND_JACK_HEADPHONE;
+		hp_automute(SND_JACK_HEADPHONE, present);
 	}
 
 	if (intsts & 0x4) {


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 13/23] intel_sst: move jack detection related configs to init time
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (11 preceding siblings ...)
  2011-05-03 16:34 ` [PATCH 12/23] intel_sst: Headphone Automute support Alan Cox
@ 2011-05-03 16:34 ` Alan Cox
  2011-05-03 16:34 ` [PATCH 14/23] sst: return correct output/input device id Alan Cox
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

The old policy will not enable MIC2BIAS on Moorstown platform
by default, it's only enabled when the user selects HS_MIC as input source.
Therefore when user selects DMIC and then inserts the jack,
no interrupt will be generated to notify the driver about the
jack insertion event and to take action to auto mute the speaker.

The new policy will enable this bit by default,
then no matter what the output device is, an interrupt will be generated.

This behaviour is more likely what a user expects.

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Reviewed-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |   28 +++++++++++------------
 1 files changed, 13 insertions(+), 15 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 7cae970..6f4caa5 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -114,18 +114,19 @@ static int nc_init_card(void)
 		{VOICEVOL, 0x0e, 0},
 		{HPLVOL, 0x06, 0},
 		{HPRVOL, 0x06, 0},
-		{MICCTRL, 0x41, 0x00},
+		{MICCTRL, 0x51, 0x00},
 		{ADCSAMPLERATE, 0x8B, 0x00},
 		{MICSELVOL, 0x5B, 0x00},
 		{LILSEL, 0x06, 0},
 		{LIRSEL, 0x46, 0},
 		{LOANTIPOP, 0x00, 0},
 		{DMICCTRL1, 0x40, 0},
+		{AUXDBNC, 0xff, 0},
 	};
 	snd_pmic_ops_nc.card_status = SND_CARD_INIT_DONE;
 	snd_pmic_ops_nc.master_mute = UNMUTE;
 	snd_pmic_ops_nc.mute_status = UNMUTE;
-	sst_sc_reg_access(sc_access, PMIC_WRITE, 26);
+	sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
 	pr_debug("init complete!!\n");
 	return 0;
 }
@@ -834,7 +835,7 @@ static int nc_set_selected_input_dev(u8 value)
 		pr_debug("Selecting AMIC\n");
 		sc_access[0].reg_addr = 0x107;
 		sc_access[0].value = 0x40;
-		sc_access[0].mask =  MASK6|MASK4|MASK3|MASK1|MASK0;
+		sc_access[0].mask =  MASK6|MASK3|MASK1|MASK0;
 		sc_access[1].reg_addr = 0x10a;
 		sc_access[1].value = 0x40;
 		sc_access[1].mask = MASK6;
@@ -849,9 +850,9 @@ static int nc_set_selected_input_dev(u8 value)
 
 	case HS_MIC:
 		pr_debug("Selecting HS_MIC\n");
-		sc_access[0].reg_addr = 0x107;
-		sc_access[0].mask =  MASK6|MASK4|MASK3|MASK1|MASK0;
-		sc_access[0].value = 0x10;
+		sc_access[0].reg_addr = MICCTRL;
+		sc_access[0].mask =  MASK6|MASK3|MASK1|MASK0;
+		sc_access[0].value = 0x00;
 		sc_access[1].reg_addr = 0x109;
 		sc_access[1].mask = MASK6;
 		sc_access[1].value = 0x40;
@@ -861,19 +862,16 @@ static int nc_set_selected_input_dev(u8 value)
 		sc_access[3].reg_addr = 0x105;
 		sc_access[3].value = 0x40;
 		sc_access[3].mask = MASK6;
-		sc_access[4].reg_addr = AUXDBNC;
-		sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3|MASK2|MASK1|MASK0;
-		sc_access[4].value = 0xff;
-		sc_access[5].reg_addr = ADCSAMPLERATE;
-		sc_access[5].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
-		sc_access[5].value = 0xc8;
-		num_val = 6;
+		sc_access[4].reg_addr = ADCSAMPLERATE;
+		sc_access[4].mask = MASK7|MASK6|MASK5|MASK4|MASK3;
+		sc_access[4].value = 0xc8;
+		num_val = 5;
 		break;
 
 	case DMIC:
 		pr_debug("DMIC\n");
-		sc_access[0].reg_addr = 0x107;
-		sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0;
+		sc_access[0].reg_addr = MICCTRL;
+		sc_access[0].mask = MASK6|MASK3|MASK1|MASK0;
 		sc_access[0].value = 0x0B;
 		sc_access[1].reg_addr = 0x105;
 		sc_access[1].value = 0x80;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 14/23] sst: return correct output/input device id
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (12 preceding siblings ...)
  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 ` Alan Cox
  2011-05-03 16:34 ` [PATCH 15/23] intel_sst: make sure the sst_drop_stream() get called when needed Alan Cox
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

Without this patch, the change of output/input device can't be reflected
correctly. The mismatch reflects insane design, and should be fixed when
switching to the ASoC framework.

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Acked-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_ctrl.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_ctrl.c b/drivers/staging/intel_sst/intelmid_ctrl.c
index 2c3ee94..af9e112 100644
--- a/drivers/staging/intel_sst/intelmid_ctrl.c
+++ b/drivers/staging/intel_sst/intelmid_ctrl.c
@@ -504,8 +504,8 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
 	WARN_ON(!kcontrol);
 
 	intelmaddata = kcontrol->private_data;
+	scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 	if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
-		scard_ops = intelmaddata->sstdrv_ops->scard_ops;
 		if (kcontrol->id.numid == OUTPUT_SEL)
 			uval->value.enumerated.item[0] =
 					scard_ops->output_dev_id;
@@ -517,6 +517,25 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol,
 					scard_ops->lineout_dev_id;
 		else
 			return -EINVAL;
+	} else if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
+		if (kcontrol->id.numid == OUTPUT_SEL)
+			/* There is a mismatch here.
+			 * ALSA expects 1 for internal speaker.
+			 * But internally, we may give 2 for internal speaker.
+			 */
+			if (scard_ops->output_dev_id == MONO_EARPIECE ||
+			    scard_ops->output_dev_id == INTERNAL_SPKR)
+				uval->value.enumerated.item[0] = MONO_EARPIECE;
+			else if (scard_ops->output_dev_id == STEREO_HEADPHONE)
+				uval->value.enumerated.item[0] =
+					STEREO_HEADPHONE;
+			else
+				return -EINVAL;
+		else if (kcontrol->id.numid == INPUT_SEL)
+			uval->value.enumerated.item[0] =
+					scard_ops->input_dev_id;
+		else
+			return -EINVAL;
 	} else
 	uval->value.enumerated.item[0] = kcontrol->private_value;
 	return 0;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 15/23] intel_sst: make sure the sst_drop_stream() get called when needed
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (13 preceding siblings ...)
  2011-05-03 16:34 ` [PATCH 14/23] sst: return correct output/input device id Alan Cox
@ 2011-05-03 16:34 ` Alan Cox
  2011-05-03 16:35 ` [PATCH 16/23] intel_sst: MRST can only do mono recording Alan Cox
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Feng Tang <feng.tang@intel.com>

When "aplay test.wav", if we "ctrl+z" to suspend it, the last piece of
sound will be played endlessly. So we need make sure the drop_stream
is called in such a case.

Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 .../staging/intel_sst/intel_sst_drv_interface.c    |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c
index 1e8c056..bb64f2a 100644
--- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
+++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
@@ -283,8 +283,8 @@ void sst_process_mad_ops(struct work_struct *work)
 		retval = sst_resume_stream(mad_ops->stream_id);
 		break;
 	case SST_SND_DROP:
-/*		retval = sst_drop_stream(mad_ops->stream_id);
-*/		break;
+		retval = sst_drop_stream(mad_ops->stream_id);
+		break;
 	case SST_SND_START:
 			pr_debug("SST Debug: start stream\n");
 		retval = sst_start_stream(mad_ops->stream_id);


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 16/23] intel_sst: MRST can only do mono recording
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (14 preceding siblings ...)
  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 ` Alan Cox
  2011-05-03 16:35 ` [PATCH 17/23] intel_sst: MRST can only do 16bit recording Alan Cox
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Wu Fengguang <wfg@linux.intel.com>

Fix bug

	$ arecord -Dplughw -c2
	Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Stereo
	arecord: set_params:1116: Unable to install hw params:
	ACCESS:  RW_INTERLEAVED
	FORMAT:  U8
	SUBFORMAT:  STD
	SAMPLE_BITS: 8
	FRAME_BITS: 16
	CHANNELS: 2
	[...]

Root cause is, the driver is reporting 2-channel capture capability
that is not supported by the MRST hardware. So the plughw plugin
end up requesting 2-channel capture which fails.

Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index 61ef4a6..0b9b1b6 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -335,6 +335,13 @@ static int snd_intelmad_open(struct snd_pcm_substream *substream,
 	runtime = substream->runtime;
 	/* set the runtime hw parameter with local snd_pcm_hardware struct */
 	runtime->hw = snd_intelmad_stream;
+	if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) {
+		/*
+		 * MRST firmware currently denies stereo recording requests.
+		 */
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			runtime->hw.channels_max = 1;
+	}
 	if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
 		runtime->hw = snd_intelmad_stream;
 		runtime->hw.rates = SNDRV_PCM_RATE_48000;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 17/23] intel_sst: MRST can only do 16bit recording
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (15 preceding siblings ...)
  2011-05-03 16:35 ` [PATCH 16/23] intel_sst: MRST can only do mono recording Alan Cox
@ 2011-05-03 16:35 ` Alan Cox
  2011-05-03 16:35 ` [PATCH 18/23] intel_sst: intelmid_v2_control: correct jack event type Alan Cox
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Wu Fengguang <wfg@linux.intel.com>

Fix bug

	$ arecord -D dsnoop -r 48000 -f S16_LE 1.wav
	ALSA lib pcm_direct.c:980:(snd1_pcm_direct_initialize_slave) unable to install hw params
	ALSA lib pcm_dsnoop.c:604:(snd_pcm_dsnoop_open) unable to initialize slave
	arecord: main:654: audio open error: Interrupted system call

Root cause is, the driver is reporting 32-bit capture capability
that is not supported by the MRST hardware. So the dsnoop plugin
end up requesting 32-bit capture which fails.

Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index 0b9b1b6..cbe09f2 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -339,8 +339,11 @@ static int snd_intelmad_open(struct snd_pcm_substream *substream,
 		/*
 		 * MRST firmware currently denies stereo recording requests.
 		 */
-		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+			runtime->hw.formats = (SNDRV_PCM_FMTBIT_S16 |
+					       SNDRV_PCM_FMTBIT_U16);
 			runtime->hw.channels_max = 1;
+		}
 	}
 	if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) {
 		runtime->hw = snd_intelmad_stream;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 18/23] intel_sst: intelmid_v2_control: correct jack event type
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (16 preceding siblings ...)
  2011-05-03 16:35 ` [PATCH 17/23] intel_sst: MRST can only do 16bit recording Alan Cox
@ 2011-05-03 16:35 ` Alan Cox
  2011-05-03 16:37 ` [PATCH 19/23] intel_sst: fix runtime pm issue Alan Cox
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Andy CH Lin <andy_ch_lin@wistron.com>

Correct event type of audio jack while receiving long press event.

Signed-off-by: Andy CH Lin <andy_ch_lin@wistron.com>
Signed-off-by: Jekyll Lai <jekyll_lai@wistron.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 6f4caa5..547b8b1 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -1054,7 +1054,7 @@ static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
 		present = 1;
 		jack_event_flag = 1;
 		buttonpressflag = 1;
-		mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
+		mjack->jack.type = MID_JACK_HS_LONG_PRESS;
 	}
 
 	if (jack_event_flag)


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 19/23] intel_sst: fix runtime pm issue
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (17 preceding siblings ...)
  2011-05-03 16:35 ` [PATCH 18/23] intel_sst: intelmid_v2_control: correct jack event type Alan Cox
@ 2011-05-03 16:37 ` Alan Cox
  2011-05-03 16:38 ` [PATCH 20/23] sst: set default output and input device Alan Cox
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:37 UTC (permalink / raw)
  To: greg, linux-kernel

From: Chandramouli Narayanan <chandramouli.narayanan@intel.com>

Use correct api for enabling/disabling runtime pm.  Additionally,
fix runtime suspend/resume to not duplicate pci core functions

Signed-off-by: Chandramouli Narayanan <chandramouli.narayanan@intel.com>
Tested-by: Kristen Carlson Accardi <kristen@linux.intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intel_sst.c |   47 +++++++++++++++++++++++++++------
 1 files changed, 38 insertions(+), 9 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c
index e7c2617..c0c144a 100644
--- a/drivers/staging/intel_sst/intel_sst.c
+++ b/drivers/staging/intel_sst/intel_sst.c
@@ -340,9 +340,9 @@ static int __devinit intel_sst_probe(struct pci_dev *pci,
 		sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr);
 	}
 	sst_drv_ctx->lpe_stalled = 0;
-	pm_runtime_set_active(&pci->dev);
-	pm_runtime_enable(&pci->dev);
+	pci_set_drvdata(pci, sst_drv_ctx);
 	pm_runtime_allow(&pci->dev);
+	pm_runtime_put_noidle(&pci->dev);
 	pr_debug("...successfully done!!!\n");
 	return ret;
 
@@ -389,6 +389,8 @@ do_free_drv_ctx:
 */
 static void __devexit intel_sst_remove(struct pci_dev *pci)
 {
+	pm_runtime_get_noresume(&pci->dev);
+	pm_runtime_forbid(&pci->dev);
 	pci_dev_put(sst_drv_ctx->pci);
 	mutex_lock(&sst_drv_ctx->sst_lock);
 	sst_drv_ctx->sst_state = SST_UN_INIT;
@@ -410,7 +412,7 @@ static void __devexit intel_sst_remove(struct pci_dev *pci)
 	destroy_workqueue(sst_drv_ctx->process_msg_wq);
 	destroy_workqueue(sst_drv_ctx->post_msg_wq);
 	destroy_workqueue(sst_drv_ctx->mad_wq);
-	kfree(sst_drv_ctx);
+	kfree(pci_get_drvdata(pci));
 	sst_drv_ctx = NULL;
 	pci_release_regions(pci);
 	pci_disable_device(pci);
@@ -522,18 +524,45 @@ int intel_sst_resume(struct pci_dev *pci)
 	return 0;
 }
 
+/* The runtime_suspend/resume is pretty much similar to the legacy suspend/resume with the noted exception below:
+ * The PCI core takes care of taking the system through D3hot and restoring it back to D0 and so there is
+ * no need to duplicate that here.
+ */
 static int intel_sst_runtime_suspend(struct device *dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev);
-	pr_debug("runtime_suspend called\n");
-	return intel_sst_suspend(pci_dev, PMSG_SUSPEND);
+	union config_status_reg csr;
+
+	pr_debug("intel_sst_runtime_suspend called\n");
+	if (sst_drv_ctx->stream_cnt) {
+		pr_err("active streams,not able to suspend\n");
+		return -EBUSY;
+	}
+	/*save fw context*/
+	sst_save_dsp_context();
+	/*Assert RESET on LPE Processor*/
+	csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+	csr.full = csr.full | 0x2;
+	/* Move the SST state to Suspended */
+	mutex_lock(&sst_drv_ctx->sst_lock);
+	sst_drv_ctx->sst_state = SST_SUSPENDED;
+	sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
+	mutex_unlock(&sst_drv_ctx->sst_lock);
+	return 0;
 }
 
 static int intel_sst_runtime_resume(struct device *dev)
 {
-	struct pci_dev *pci_dev = to_pci_dev(dev);
-	pr_debug("runtime_resume called\n");
-	return intel_sst_resume(pci_dev);
+
+	pr_debug("intel_sst_runtime_resume called\n");
+	if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
+		pr_err("SST is not in suspended state\n");
+		return 0;
+	}
+
+	mutex_lock(&sst_drv_ctx->sst_lock);
+	sst_drv_ctx->sst_state = SST_UN_INIT;
+	mutex_unlock(&sst_drv_ctx->sst_lock);
+	return 0;
 }
 
 static int intel_sst_runtime_idle(struct device *dev)


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 20/23] sst: set default output and input device
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (18 preceding siblings ...)
  2011-05-03 16:37 ` [PATCH 19/23] intel_sst: fix runtime pm issue Alan Cox
@ 2011-05-03 16:38 ` Alan Cox
  2011-05-03 16:38 ` [PATCH 21/23] intel_sst: add Master Volume Alan Cox
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:38 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid_v2_control.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 547b8b1..5e61fe8 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -1067,6 +1067,8 @@ static int nc_jack_enable(void)
 }
 
 struct snd_pmic_ops snd_pmic_ops_nc = {
+	.input_dev_id   =       DMIC,
+	.output_dev_id  =       INTERNAL_SPKR,
 	.set_input_dev	=	nc_set_selected_input_dev,
 	.set_output_dev =	nc_set_selected_output_dev,
 	.set_mute	=	nc_set_mute,


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 21/23] intel_sst: add Master Volume
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (19 preceding siblings ...)
  2011-05-03 16:38 ` [PATCH 20/23] sst: set default output and input device Alan Cox
@ 2011-05-03 16:38 ` Alan Cox
  2011-05-03 16:43 ` [PATCH 22/23] sst: internal speaker needs setting a GPIO line Alan Cox
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:38 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

With this patch, Master Volume will control AUDIOLVOL(0x10c) and
AUDIORVOL(0x10d); while PCM Volume will control HPLVOL(0x123) and
HPRVOL(0x124).

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intelmid.h             |    7 ++-
 drivers/staging/intel_sst/intelmid_ctrl.c        |   40 +++++++++++++++++-
 drivers/staging/intel_sst/intelmid_snd_control.h |    2 +
 drivers/staging/intel_sst/intelmid_v2_control.c  |   48 +++++++++++++++++-----
 4 files changed, 81 insertions(+), 16 deletions(-)


diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
index 3201d5a..14a7ba0 100644
--- a/drivers/staging/intel_sst/intelmid.h
+++ b/drivers/staging/intel_sst/intelmid.h
@@ -57,9 +57,9 @@
 #define MAX_CHANNEL_DMIC	5
 #define FIFO_SIZE		0 /* fifo not being used */
 #define INTEL_MAD		"Intel MAD"
-#define MAX_CTRL_MRST		7
+#define MAX_CTRL_MRST		8
 #define MAX_CTRL_MFLD		7
-#define MAX_CTRL		7
+#define MAX_CTRL		8
 #define MAX_VENDORS		4
 /* TODO +6 db */
 #define MAX_VOL		64
@@ -145,6 +145,8 @@ struct snd_control_val {
 	int	playback_vol_min;
 	int	capture_vol_max;
 	int	capture_vol_min;
+	int	master_vol_max;
+	int	master_vol_min;
 };
 
 struct mad_stream_pvt {
@@ -175,6 +177,7 @@ enum _widget_ctrl {
 	PLAYBACK_MUTE,
 	CAPTURE_VOL,
 	CAPTURE_MUTE,
+	MASTER_VOL,
 	MASTER_MUTE
 };
 enum _widget_ctrl_mfld {
diff --git a/drivers/staging/intel_sst/intelmid_ctrl.c b/drivers/staging/intel_sst/intelmid_ctrl.c
index af9e112..19ec474 100644
--- a/drivers/staging/intel_sst/intelmid_ctrl.c
+++ b/drivers/staging/intel_sst/intelmid_ctrl.c
@@ -80,9 +80,11 @@ struct snd_control_val intelmad_ctrl_val[MAX_VENDORS] = {
 	},
 	{
 		.playback_vol_max = 0,
-		.playback_vol_min = -126,
+		.playback_vol_min = -31,
 		.capture_vol_max = 0,
 		.capture_vol_min = -31,
+		.master_vol_max = 0,
+		.master_vol_min = -126,
 	},
 };
 
@@ -159,6 +161,15 @@ static int snd_intelmad_playback_volume_info(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int snd_intelmad_master_volume_info(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	snd_intelmad_volume_info(uinfo, STEREO_CNTL,
+		intelmad_ctrl_val[sst_card_vendor_id].master_vol_max,
+		intelmad_ctrl_val[sst_card_vendor_id].master_vol_min);
+	return 0;
+}
+
 /**
 * snd_intelmad_device_info_mrst - provides information about the devices available
 *
@@ -281,6 +292,11 @@ static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
 	case CAPTURE_VOL:
 		cntl_list[0] = PMIC_SND_CAPTURE_VOL;
 		break;
+
+	case MASTER_VOL:
+		cntl_list[0] = PMIC_SND_RIGHT_MASTER_VOL;
+		cntl_list[1] = PMIC_SND_LEFT_MASTER_VOL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -291,7 +307,8 @@ static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol,
 	if (ret_val)
 		return ret_val;
 
-	if (kcontrol->id.numid == PLAYBACK_VOL) {
+	if (kcontrol->id.numid == PLAYBACK_VOL ||
+		kcontrol->id.numid == MASTER_VOL) {
 		ret_val = scard_ops->get_vol(cntl_list[1], &value);
 		uval->value.integer.value[1] = value;
 	}
@@ -399,6 +416,12 @@ static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
 	case CAPTURE_VOL:
 		cntl_list[0] = PMIC_SND_CAPTURE_VOL;
 		break;
+
+	case MASTER_VOL:
+		cntl_list[0] = PMIC_SND_LEFT_MASTER_VOL;
+		cntl_list[1] = PMIC_SND_RIGHT_MASTER_VOL;
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -408,7 +431,8 @@ static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol,
 	if (ret_val)
 		return ret_val;
 
-	if (kcontrol->id.numid == PLAYBACK_VOL)
+	if (kcontrol->id.numid == PLAYBACK_VOL ||
+		kcontrol->id.numid == MASTER_VOL)
 		ret_val = scard_ops->set_vol(cntl_list[1],
 				uval->value.integer.value[1]);
 	return ret_val;
@@ -753,7 +777,6 @@ static int snd_intelmad_device_dmic_info_mfld(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-
 struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
 {
 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -811,6 +834,15 @@ struct snd_kcontrol_new snd_intelmad_controls_mrst[MAX_CTRL] __devinitdata = {
 },
 {
 	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name		=	"Master Playback Volume",
+	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info		=	snd_intelmad_master_volume_info,
+	.get		=	snd_intelmad_volume_get,
+	.put		=	snd_intelmad_volume_set,
+	.private_value	=	0,
+},
+{
+	.iface		=	SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name		=	"Master Playback Switch",
 	.access		=	SNDRV_CTL_ELEM_ACCESS_READWRITE,
 	.info		=	snd_intelmad_mute_info,
diff --git a/drivers/staging/intel_sst/intelmid_snd_control.h b/drivers/staging/intel_sst/intelmid_snd_control.h
index c7e9f16..06ad3a1 100644
--- a/drivers/staging/intel_sst/intelmid_snd_control.h
+++ b/drivers/staging/intel_sst/intelmid_snd_control.h
@@ -111,6 +111,8 @@ enum pmic_controls {
 	PMIC_SND_RIGHT_SPEAKER_MUTE =		0x0015,
 	PMIC_SND_RECEIVER_VOL =			0x0016,
 	PMIC_SND_RECEIVER_MUTE =		0x0017,
+	PMIC_SND_LEFT_MASTER_VOL =		0x0018,
+	PMIC_SND_RIGHT_MASTER_VOL =		0x0019,
 /* Other controls */
 	PMIC_SND_MUTE_ALL =			0x0020,
 	PMIC_MAX_CONTROLS =			0x0020,
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 5e61fe8..b19f51e 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -788,9 +788,8 @@ static int nc_set_vol(int dev_id, int value)
 	case PMIC_SND_LEFT_PB_VOL:
 		pr_debug("PMIC_SND_LEFT_HP_VOL %d\n", value);
 		sc_access[0].value = -value;
-		sc_access[0].reg_addr  = AUDIOLVOL;
-		sc_access[0].mask =
-			(MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
+		sc_access[0].reg_addr  = HPLVOL;
+		sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
 		entries = 1;
 		break;
 
@@ -798,15 +797,32 @@ static int nc_set_vol(int dev_id, int value)
 		pr_debug("PMIC_SND_RIGHT_HP_VOL value %d\n", value);
 		if (snd_pmic_ops_nc.num_channel == 1) {
 			sc_access[0].value = 0x04;
-		    sc_access[0].reg_addr = RMUTE;
+			sc_access[0].reg_addr = RMUTE;
 			sc_access[0].mask = MASK2;
 		} else {
+			sc_access[0].value = -value;
+			sc_access[0].reg_addr  = HPRVOL;
+			sc_access[0].mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
+		}
+		entries = 1;
+		break;
+
+	case PMIC_SND_LEFT_MASTER_VOL:
+		pr_debug("PMIC_SND_LEFT_MASTER_VOL value %d\n", value);
+		sc_access[0].value = -value;
+		sc_access[0].reg_addr = AUDIOLVOL;
+		sc_access[0].mask =
+			(MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
+		entries = 1;
+		break;
+
+	case PMIC_SND_RIGHT_MASTER_VOL:
+		pr_debug("PMIC_SND_RIGHT_MASTER_VOL value %d\n", value);
 		sc_access[0].value = -value;
-		sc_access[0].reg_addr  = AUDIORVOL;
+		sc_access[0].reg_addr = AUDIORVOL;
 		sc_access[0].mask =
 				(MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
 		entries = 1;
-		}
 		break;
 
 	default:
@@ -971,18 +987,30 @@ static int nc_get_vol(int dev_id, int *value)
 		mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5);
 		break;
 
-	case PMIC_SND_RIGHT_PB_VOL:
-		pr_debug("GET_VOLUME_PMIC_LEFT_HP_VOL\n");
+	case PMIC_SND_LEFT_MASTER_VOL:
+		pr_debug("GET_VOLUME_PMIC_LEFT_MASTER_VOL\n");
 		sc_access.reg_addr = AUDIOLVOL;
 		mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
 		break;
 
-	case PMIC_SND_LEFT_PB_VOL:
-		pr_debug("GET_VOLUME_PMIC_RIGHT_HP_VOL\n");
+	case PMIC_SND_RIGHT_MASTER_VOL:
+		pr_debug("GET_VOLUME_PMIC_RIGHT_MASTER_VOL\n");
 		sc_access.reg_addr = AUDIORVOL;
 		mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6);
 		break;
 
+	case PMIC_SND_RIGHT_PB_VOL:
+		pr_debug("GET_VOLUME_PMIC_RIGHT_HP_VOL\n");
+		sc_access.reg_addr = HPRVOL;
+		mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
+		break;
+
+	case PMIC_SND_LEFT_PB_VOL:
+		pr_debug("GET_VOLUME_PMIC_LEFT_HP_VOL\n");
+		sc_access.reg_addr = HPLVOL;
+		mask = (MASK0|MASK1|MASK2|MASK3|MASK4);
+		break;
+
 	default:
 		return -EINVAL;
 


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 22/23] sst: internal speaker needs setting a GPIO line
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (20 preceding siblings ...)
  2011-05-03 16:38 ` [PATCH 21/23] intel_sst: add Master Volume Alan Cox
@ 2011-05-03 16:43 ` 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
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:43 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

On Moorestown platform, internal speaker's power line is connected to a GPIO
line, so we need to enable or disable it properly.

Reviewed-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jeff Cheng <jeff_cheng@wistron.com>
Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Signed-off-by: Wang Xingchao <xingchao.wang@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intel_sst.h           |    2 ++
 drivers/staging/intel_sst/intelmid.c            |   13 ++++++++++--
 drivers/staging/intel_sst/intelmid_v2_control.c |   25 ++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 3 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
index 986a3df..635cf58 100644
--- a/drivers/staging/intel_sst/intel_sst.h
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -120,6 +120,8 @@ struct snd_pmic_ops {
 	unsigned int hw_dmic_map[MFLD_MAX_HW_CH];
 	unsigned int available_dmics;
 	int (*set_hw_dmic_route) (u8 index);
+
+	int gpio_amp;
 };
 
 extern void sst_mad_send_jack_report(struct snd_jack *jack,
diff --git a/drivers/staging/intel_sst/intelmid.c b/drivers/staging/intel_sst/intelmid.c
index cbe09f2..25656ad 100644
--- a/drivers/staging/intel_sst/intelmid.c
+++ b/drivers/staging/intel_sst/intelmid.c
@@ -40,6 +40,7 @@
 #include <sound/jack.h>
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
+#include <linux/gpio.h>
 #include "intel_sst.h"
 #include "intel_sst_ioctl.h"
 #include "intel_sst_fw_ipc.h"
@@ -920,14 +921,20 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev)
 	ret_val = snd_intelmad_create(intelmaddata, card);
 	if (ret_val) {
 		pr_err("snd_intelmad_create failed\n");
-		goto set_pvt_data;;
+		goto set_pvt_data;
 	}
 	card->private_data = &intelmaddata;
 	snd_card_set_dev(card, &pdev->dev);
 	ret_val = snd_card_register(card);
 	if (ret_val) {
 		pr_err("snd_card_register failed\n");
-		goto set_pvt_data;;
+		goto set_pvt_data;
+	}
+	if (pdev->dev.platform_data) {
+		int gpio_amp = *(int *)pdev->dev.platform_data;
+		if (gpio_request_one(gpio_amp, GPIOF_OUT_INIT_LOW, "amp power"))
+			gpio_amp = 0;
+		intelmaddata->sstdrv_ops->scard_ops->gpio_amp = gpio_amp;
 	}
 
 	pr_debug("snd_intelmad_probe complete\n");
@@ -957,6 +964,8 @@ static int snd_intelmad_remove(struct platform_device *pdev)
 	struct snd_intelmad *intelmaddata = platform_get_drvdata(pdev);
 
 	if (intelmaddata) {
+		if (intelmaddata->sstdrv_ops->scard_ops->gpio_amp)
+			gpio_free(intelmaddata->sstdrv_ops->scard_ops->gpio_amp);
 		free_irq(intelmaddata->irq, intelmaddata);
 		snd_card_free(intelmaddata->card);
 	}
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index b19f51e..2dc6738 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -28,6 +28,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/gpio.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/file.h>
@@ -87,6 +88,12 @@ enum reg_v3 {
 	AUXDBNC = 0x12f,
 };
 
+static void nc_set_amp_power(int power)
+{
+	if (snd_pmic_ops_nc.gpio_amp)
+		gpio_set_value(snd_pmic_ops_nc.gpio_amp, power);
+}
+
 /****
  * nc_init_card - initialize the sound card
  *
@@ -213,6 +220,16 @@ static int nc_power_up_pb(unsigned int port)
 
 	msleep(30);
 
+	/*
+	 * There is a mismatch between Playback Sources and the enumerated
+	 * values of output sources.  This mismatch causes ALSA upper to send
+	 * Item 1 for Internal Speaker, but the expected enumeration is 2!  For
+	 * now, treat MONO_EARPIECE and INTERNAL_SPKR identically and power up
+	 * the needed resources
+	 */
+	if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
+	    snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
+		nc_set_amp_power(1);
 	return nc_enable_audiodac(UNMUTE);
 
 }
@@ -274,7 +291,6 @@ static int nc_power_down(void)
 	int retval = 0;
 	struct sc_reg_access sc_access[5];
 
-
 	if (snd_pmic_ops_nc.card_status == SND_CARD_UN_INIT)
 		retval = nc_init_card();
 	if (retval)
@@ -284,6 +300,10 @@ static int nc_power_down(void)
 
 	pr_debug("powering dn nc_power_down ....\n");
 
+	if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
+	    snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
+		nc_set_amp_power(0);
+
 	msleep(30);
 
 	sc_access[0].reg_addr = DRVPOWERCTRL;
@@ -519,9 +539,12 @@ static int nc_set_selected_output_dev(u8 value)
 	switch (value) {
 	case STEREO_HEADPHONE:
 		retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2);
+		nc_set_amp_power(0);
 		break;
+	case MONO_EARPIECE:
 	case INTERNAL_SPKR:
 		retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 2);
+		nc_set_amp_power(1);
 		break;
 	default:
 		pr_err("rcvd illegal request: %d\n", value);


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 23/23] intel_sst: fix output noises when it's not in playback
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (21 preceding siblings ...)
  2011-05-03 16:43 ` [PATCH 22/23] sst: internal speaker needs setting a GPIO line Alan Cox
@ 2011-05-03 16:43 ` Alan Cox
  2011-05-03 17:15 ` [PATCH 00/23] Intel SST driver update Mark Brown
  23 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 16:43 UTC (permalink / raw)
  To: greg, linux-kernel

From: Lu Guanqun <guanqun.lu@intel.com>

When the corresponding output device is not in playback, we can hear a little
noises.

Fix it by powering on the device only when it's in playback.

Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
Reviewed-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/intel_sst/intel_sst.h           |    1 +
 drivers/staging/intel_sst/intelmid_v2_control.c |   33 +++++++++++++++++------
 2 files changed, 25 insertions(+), 9 deletions(-)


diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h
index 635cf58..4ad2829 100644
--- a/drivers/staging/intel_sst/intel_sst.h
+++ b/drivers/staging/intel_sst/intel_sst.h
@@ -84,6 +84,7 @@ struct snd_pmic_ops {
 	int num_channel;
 	int input_dev_id;
 	int mute_status;
+	struct mutex lock;
 	int pb_on, pbhs_on;
 	int cap_on;
 	int output_dev_id;
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index 2dc6738..000378a 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -134,6 +134,7 @@ static int nc_init_card(void)
 	snd_pmic_ops_nc.master_mute = UNMUTE;
 	snd_pmic_ops_nc.mute_status = UNMUTE;
 	sst_sc_reg_access(sc_access, PMIC_WRITE, 27);
+	mutex_init(&snd_pmic_ops_nc.lock);
 	pr_debug("init complete!!\n");
 	return 0;
 }
@@ -180,6 +181,7 @@ static int nc_power_up_pb(unsigned int port)
 		return retval;
 	if (port == 0xFF)
 		return 0;
+	mutex_lock(&snd_pmic_ops_nc.lock);
 	nc_enable_audiodac(MUTE);
 	msleep(30);
 
@@ -220,6 +222,8 @@ static int nc_power_up_pb(unsigned int port)
 
 	msleep(30);
 
+	snd_pmic_ops_nc.pb_on = 1;
+
 	/*
 	 * There is a mismatch between Playback Sources and the enumerated
 	 * values of output sources.  This mismatch causes ALSA upper to send
@@ -230,8 +234,9 @@ static int nc_power_up_pb(unsigned int port)
 	if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE ||
 	    snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR)
 		nc_set_amp_power(1);
-	return nc_enable_audiodac(UNMUTE);
-
+	nc_enable_audiodac(UNMUTE);
+	mutex_unlock(&snd_pmic_ops_nc.lock);
+	return 0;
 }
 
 static int nc_power_up_cp(unsigned int port)
@@ -352,7 +357,7 @@ static int nc_power_down_pb(unsigned int device)
 		return retval;
 
 	pr_debug("powering dn pb....\n");
-
+	mutex_lock(&snd_pmic_ops_nc.lock);
 	nc_enable_audiodac(MUTE);
 
 
@@ -379,9 +384,11 @@ static int nc_power_down_pb(unsigned int device)
 
 	msleep(30);
 
-	return nc_enable_audiodac(UNMUTE);
-
+	snd_pmic_ops_nc.pb_on = 0;
 
+	nc_enable_audiodac(UNMUTE);
+	mutex_unlock(&snd_pmic_ops_nc.lock);
+	return 0;
 }
 
 static int nc_power_down_cp(unsigned int device)
@@ -522,11 +529,13 @@ static int nc_set_selected_output_dev(u8 value)
 {
 	struct sc_reg_access sc_access_HP[] = {
 		{LMUTE, 0x02, 0x06},
-		{RMUTE, 0x02, 0x06}
+		{RMUTE, 0x02, 0x06},
+		{DRVPOWERCTRL, 0x06, 0x06},
 	};
 	struct sc_reg_access sc_access_IS[] = {
 		{LMUTE, 0x04, 0x06},
-		{RMUTE, 0x04, 0x06}
+		{RMUTE, 0x04, 0x06},
+		{DRVPOWERCTRL, 0x00, 0x06},
 	};
 	int retval = 0;
 
@@ -536,20 +545,26 @@ static int nc_set_selected_output_dev(u8 value)
 	if (retval)
 		return retval;
 	pr_debug("nc set selected output:%d\n", value);
+	mutex_lock(&snd_pmic_ops_nc.lock);
 	switch (value) {
 	case STEREO_HEADPHONE:
+		if (snd_pmic_ops_nc.pb_on)
+			sst_sc_reg_access(sc_access_HP+2, PMIC_WRITE, 1);
 		retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2);
 		nc_set_amp_power(0);
 		break;
 	case MONO_EARPIECE:
 	case INTERNAL_SPKR:
-		retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 2);
-		nc_set_amp_power(1);
+		retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 3);
+		if (snd_pmic_ops_nc.pb_on)
+			nc_set_amp_power(1);
 		break;
 	default:
 		pr_err("rcvd illegal request: %d\n", value);
+		mutex_unlock(&snd_pmic_ops_nc.lock);
 		return -EINVAL;
 	}
+	mutex_unlock(&snd_pmic_ops_nc.lock);
 	return retval;
 }
 


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/23] intel_sst: MSIC codec power optimisation
  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
  0 siblings, 1 reply; 42+ messages in thread
From: Mark Brown @ 2011-05-03 16:58 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel

On Tue, May 03, 2011 at 05:32:01PM +0100, Alan Cox wrote:

> From: Vinod Koul <vinod.koul@intel.com>
> 
> This patch adds power optimization for the msic codec and ensure
> codec is completely powered off when codec is idle.

Once you move over to proper CODEC drivers the core will take care of
this stuff for you.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/23] intel_sst: MSIC codec power optimisation
  2011-05-03 17:02     ` Alan Cox
@ 2011-05-03 17:02       ` Mark Brown
  0 siblings, 0 replies; 42+ messages in thread
From: Mark Brown @ 2011-05-03 17:02 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel

On Tue, May 03, 2011 at 06:02:02PM +0100, Alan Cox wrote:
> Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:

> > Once you move over to proper CODEC drivers the core will take care of
> > this stuff for you.

> Please see 00/23

> "This is a forward port of various further Intel work on the SST driver in
> staging. This keeps the staging driver up to date while the ALSA driver
> development continues."

I did see that; I don't see any contradiction here?

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/23] intel_sst: MSIC codec power optimisation
  2011-05-03 16:58   ` Mark Brown
@ 2011-05-03 17:02     ` Alan Cox
  2011-05-03 17:02       ` Mark Brown
  0 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 17:02 UTC (permalink / raw)
  To: Mark Brown; +Cc: greg, linux-kernel

On Tue, 3 May 2011 17:58:38 +0100
Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:

> On Tue, May 03, 2011 at 05:32:01PM +0100, Alan Cox wrote:
> 
> > From: Vinod Koul <vinod.koul@intel.com>
> > 
> > This patch adds power optimization for the msic codec and ensure
> > codec is completely powered off when codec is idle.
> 
> Once you move over to proper CODEC drivers the core will take care of
> this stuff for you.

Please see 00/23

"This is a forward port of various further Intel work on the SST driver in
staging. This keeps the staging driver up to date while the ALSA driver
development continues."


Alan

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 00/23] Intel SST driver update
  2011-05-03 16:31 [PATCH 00/23] Intel SST driver update Alan Cox
                   ` (22 preceding siblings ...)
  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 ` Mark Brown
  2011-05-03 18:36   ` Alan Cox
  23 siblings, 1 reply; 42+ messages in thread
From: Mark Brown @ 2011-05-03 17:15 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel

On Tue, May 03, 2011 at 05:31:17PM +0100, Alan Cox wrote:
> This is a forward port of various further Intel work on the SST driver in
> staging. This keeps the staging driver up to date while the ALSA driver
> development continues.

What's the plan for moving these out of staging?  Quite a few of these
patches feel like moves in the wrong direction, adding more code that's
going to have problems with mainline rather than addressing the issues
that prevent merges.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  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
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2011-05-03 17:42 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel

On Tue, May 03, 2011 at 05:31:49PM +0100, Alan Cox wrote:
> From: Vinod Koul <vinod.koul@intel.com>
> 
> During suspend and runtime_suspend audio dsp will be in D3 state
> and will loose its context.
> 
> This patch adds support in driver to save the dsp context
> and restore this context during resume
> 
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
> Signed-off-by: Alan Cox <alan@linux.intel.com>

Something is messed up here as:

> --- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
> +++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
> @@ -508,6 +508,7 @@ int register_sst_card(struct intel_sst_card_ops *card)
>  			sst_drv_ctx->pmic_state = SND_MAD_INIT_DONE;
>  			sst_drv_ctx->rx_time_slot_status = 0; /*default AMIC*/
>  			card->pcm_control = sst_pmic_ops.pcm_control;
> +			sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
>  			return 0;
>  		} else {
>  			pr_err("strcmp fail %s\n", card->module_name);

This line is in the original patch from Vinod in this function that
added the driver to the tree (git commit id fffa1cca), so the patch
doesn't apply at all.  Do you see this too?

If I comment out this chunk, the patch fails later on as well:

patching file drivers/staging/intel_sst/intelmid.c
Hunk #1 FAILED at 805.
1 out of 1 hunk FAILED -- saving rejects to file drivers/staging/intel_sst/intelmid.c.rej


Which is odd.

What tree did you generate this series against?  I don't have any
outstanding sst patches in my "to-apply" queue, did I miss some that you
previously sent that I should have applied first?

confused,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 00/23] Intel SST driver update
  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
  0 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 18:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: greg, linux-kernel

On Tue, 3 May 2011 18:15:38 +0100
Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:

> On Tue, May 03, 2011 at 05:31:17PM +0100, Alan Cox wrote:
> > This is a forward port of various further Intel work on the SST driver in
> > staging. This keeps the staging driver up to date while the ALSA driver
> > development continues.
> 
> What's the plan for moving these out of staging?  Quite a few of these
> patches feel like moves in the wrong direction, adding more code that's
> going to have problems with mainline rather than addressing the issues
> that prevent merges.

There is a separate driver being written. In the meantime this driver is
getting updated and maintained because in the real world people have
customers and products to deliver.

It might as well therefore be maintained in tree as out. That seems to
serve Linux users rather better.

Alan

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 00/23] Intel SST driver update
  2011-05-03 18:36   ` Alan Cox
@ 2011-05-03 18:40     ` Mark Brown
  2011-05-03 20:27       ` Alan Cox
  0 siblings, 1 reply; 42+ messages in thread
From: Mark Brown @ 2011-05-03 18:40 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel

On Tue, May 03, 2011 at 07:36:12PM +0100, Alan Cox wrote:
> Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:

> > What's the plan for moving these out of staging?  Quite a few of these
> > patches feel like moves in the wrong direction, adding more code that's
> > going to have problems with mainline rather than addressing the issues
> > that prevent merges.

> There is a separate driver being written. In the meantime this driver is
> getting updated and maintained because in the real world people have
> customers and products to deliver.

Sure, I was just asking if there was a plan to work on this properly -
the normal expectation in staging is that we'll see in place refactoring
and this series clearly isn't that.  You seem a little defensive here...

> It might as well therefore be maintained in tree as out. That seems to
> serve Linux users rather better.

Of course, as do most of us, I was mostly making sure that there was a
plan here.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 00/23] Intel SST driver update
  2011-05-03 18:40     ` Mark Brown
@ 2011-05-03 20:27       ` Alan Cox
  0 siblings, 0 replies; 42+ messages in thread
From: Alan Cox @ 2011-05-03 20:27 UTC (permalink / raw)
  To: Mark Brown; +Cc: greg, linux-kernel

> Sure, I was just asking if there was a plan to work on this properly -
> the normal expectation in staging is that we'll see in place refactoring
> and this series clearly isn't that.  You seem a little defensive here...

There I disagree (on both points). We have a collection of drivers in
staging some of which are in the 'refactor and move' category (eg SEP)
others of which are in the 'until the nice one is done' category - eg
much of the wireless stuff, rim4 and a few other drivers.

> > It might as well therefore be maintained in tree as out. That seems to
> > serve Linux users rather better.
> 
> Of course, as do most of us, I was mostly making sure that there was a
> plan here.

Yes there is a plan. SST essentially gets updated to fix stuff that needs
to work (eg runtime PM for Moorestown) but isn't the future. My favourite
sst patch is going to be the one which reads 'added 0 lines, removed
bazillions' because at that point it ceases to be my problem ;)

Alan

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 17:42   ` Greg KH
@ 2011-05-03 21:29     ` Alan Cox
  2011-05-03 21:39       ` Mark Brown
  0 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 21:29 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, broonie

> > Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> > Signed-off-by: Ramesh Babu K V <ramesh.babu@intel.com>
> > Signed-off-by: Alan Cox <alan@linux.intel.com>
> 
> Something is messed up here as:
> 
> > --- a/drivers/staging/intel_sst/intel_sst_drv_interface.c
> > +++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c
> > @@ -508,6 +508,7 @@ int register_sst_card(struct intel_sst_card_ops *card)
> >  			sst_drv_ctx->pmic_state = SND_MAD_INIT_DONE;
> >  			sst_drv_ctx->rx_time_slot_status = 0; /*default AMIC*/
> >  			card->pcm_control = sst_pmic_ops.pcm_control;
> > +			sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT;
> >  			return 0;
> >  		} else {
> >  			pr_err("strcmp fail %s\n", card->module_name);
> 
> This line is in the original patch from Vinod in this function that
> added the driver to the tree (git commit id fffa1cca), so the patch
> doesn't apply at all.  Do you see this too?

I see it present in ffa1cca then removed then added back

I see the problem - Mark Brown took a patch in staging via the ASoC tree
which clashes with this.

fa880004682cf0d10e7a7c71dc8d56bbd67ac3d5

which is not only a staging patch but also breaks compilation of the code
because the sst_drv_ctx symbol isn't even exported or visible to the
intelmid module, which suggests it wasn't even compile tested.

Best plan seems to be for the patch Mark took to go into the staging tree
as well, and I'll then rebuild the patch stack on top of it and fix the
fact it didn't even build.

In general we have a bigger problem here, the ASoC driver appears to be
violating rule #1 of staging - nothing outside of staging should be using
or depending upon staging code in the first place.

Alan

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 21:29     ` Alan Cox
@ 2011-05-03 21:39       ` Mark Brown
  2011-05-03 21:53         ` Alan Cox
  0 siblings, 1 reply; 42+ messages in thread
From: Mark Brown @ 2011-05-03 21:39 UTC (permalink / raw)
  To: Alan Cox; +Cc: Greg KH, linux-kernel

On Tue, May 03, 2011 at 10:29:03PM +0100, Alan Cox wrote:

> I see the problem - Mark Brown took a patch in staging via the ASoC tree
> which clashes with this.

> fa880004682cf0d10e7a7c71dc8d56bbd67ac3d5

> which is not only a staging patch but also breaks compilation of the code
> because the sst_drv_ctx symbol isn't even exported or visible to the
> intelmid module, which suggests it wasn't even compile tested.

I am assured that this patch is essential to build with the Intel
drivers that are currently upstream in ASoC, though I've not personally
verified that.  I'd not be surprised if the tests whoever submitted it
did had only been done with the module built in, though I'd have
expected whatever tests people do on -next to pick that up since x86
seems to be a popular target there.

> In general we have a bigger problem here, the ASoC driver appears to be
> violating rule #1 of staging - nothing outside of staging should be using
> or depending upon staging code in the first place.

To recap the previous discussion: staging is just not in the slightest
bit viable for ASoC stuff, code that does anything non-trivial is going
to get broken between releases.  Especially with something like this
where the drivers are for unreleased hardware that has no current end
users it's just not a problem for the core if drivers do stuff like this
so long as they don't do anything visibly bad or cause problems for the
people who do build test whatever architecture is affected.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 21:39       ` Mark Brown
@ 2011-05-03 21:53         ` Alan Cox
  2011-05-03 22:02           ` Greg KH
  0 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 21:53 UTC (permalink / raw)
  To: Mark Brown; +Cc: Greg KH, linux-kernel

> To recap the previous discussion: staging is just not in the slightest
> bit viable for ASoC stuff, code that does anything non-trivial is going

Yes I know that - and its active development of a nice clean driver going
on upstream so doesn't belong there anyway. The ASoC driver should
probably have its own copy of the bits of the staging driver that it
needs however.

I can fix this collision up easily enough and if doing it not via the
rules is best fine by me. I think it might be wiser however if the ASoC
driver took its own copy of the bits it actually needed.

Alan

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 21:53         ` Alan Cox
@ 2011-05-03 22:02           ` Greg KH
  2011-05-03 22:26             ` Mark Brown
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2011-05-03 22:02 UTC (permalink / raw)
  To: Alan Cox; +Cc: Mark Brown, linux-kernel

On Tue, May 03, 2011 at 10:53:16PM +0100, Alan Cox wrote:
> > To recap the previous discussion: staging is just not in the slightest
> > bit viable for ASoC stuff, code that does anything non-trivial is going
> 
> Yes I know that - and its active development of a nice clean driver going
> on upstream so doesn't belong there anyway. The ASoC driver should
> probably have its own copy of the bits of the staging driver that it
> needs however.
> 
> I can fix this collision up easily enough and if doing it not via the
> rules is best fine by me. I think it might be wiser however if the ASoC
> driver took its own copy of the bits it actually needed.

That sounds like a good idea.

Mark, can you try to let me know if you are patching staging code?  If
you want to "own" a driver in the staging tree, that's fine, just let me
konw and I'll funnel patches to you for it (we do that for other staging
drivers).

It's just that for times like this, when I have no idea that someone
else modified it in linux-next, and then patches fail to apply, that it
gets messy.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 22:02           ` Greg KH
@ 2011-05-03 22:26             ` Mark Brown
  2011-05-03 22:32               ` Greg KH
  0 siblings, 1 reply; 42+ messages in thread
From: Mark Brown @ 2011-05-03 22:26 UTC (permalink / raw)
  To: Greg KH; +Cc: Alan Cox, linux-kernel

On Tue, May 03, 2011 at 03:02:33PM -0700, Greg KH wrote:

> Mark, can you try to let me know if you are patching staging code?  If
> you want to "own" a driver in the staging tree, that's fine, just let me
> konw and I'll funnel patches to you for it (we do that for other staging
> drivers).

I CCed you in on the thread where the patch was applied.  Probably you
forgot about it as it was described as a build fix for my tree.

I'm not really that interested in the Intel patches in staging, the bulk
of them require a from scratch rewrite to go upstream as they're so far
from following the Linux driver model for these things.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 22:26             ` Mark Brown
@ 2011-05-03 22:32               ` Greg KH
  2011-05-03 22:59                 ` Alan Cox
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2011-05-03 22:32 UTC (permalink / raw)
  To: Mark Brown; +Cc: Alan Cox, linux-kernel

On Tue, May 03, 2011 at 11:26:35PM +0100, Mark Brown wrote:
> On Tue, May 03, 2011 at 03:02:33PM -0700, Greg KH wrote:
> 
> > Mark, can you try to let me know if you are patching staging code?  If
> > you want to "own" a driver in the staging tree, that's fine, just let me
> > konw and I'll funnel patches to you for it (we do that for other staging
> > drivers).
> 
> I CCed you in on the thread where the patch was applied.  Probably you
> forgot about it as it was described as a build fix for my tree.

I must have, sorry about that.

> I'm not really that interested in the Intel patches in staging, the bulk
> of them require a from scratch rewrite to go upstream as they're so far
> from following the Linux driver model for these things.

Ok, then I guess I can handle them.

Alan, how do you want to go about sending patches that we can apply
somehow?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 22:32               ` Greg KH
@ 2011-05-03 22:59                 ` Alan Cox
  2011-05-03 23:06                   ` Greg KH
  0 siblings, 1 reply; 42+ messages in thread
From: Alan Cox @ 2011-05-03 22:59 UTC (permalink / raw)
  To: Greg KH; +Cc: Mark Brown, linux-kernel

> > I'm not really that interested in the Intel patches in staging, the bulk
> > of them require a from scratch rewrite to go upstream as they're so far
> > from following the Linux driver model for these things.
> 
> Ok, then I guess I can handle them.
> 
> Alan, how do you want to go about sending patches that we can apply
> somehow?

Best bet is to apply Mark's patch into your git tree then apply mine on
top I think. Git will see the same patch in both trees and resolve it all
nicely for -next.

Alan

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 22:59                 ` Alan Cox
@ 2011-05-03 23:06                   ` Greg KH
  2011-05-04  8:57                     ` Mark Brown
  0 siblings, 1 reply; 42+ messages in thread
From: Greg KH @ 2011-05-03 23:06 UTC (permalink / raw)
  To: Alan Cox; +Cc: Mark Brown, linux-kernel

On Tue, May 03, 2011 at 11:59:17PM +0100, Alan Cox wrote:
> > > I'm not really that interested in the Intel patches in staging, the bulk
> > > of them require a from scratch rewrite to go upstream as they're so far
> > > from following the Linux driver model for these things.
> > 
> > Ok, then I guess I can handle them.
> > 
> > Alan, how do you want to go about sending patches that we can apply
> > somehow?
> 
> Best bet is to apply Mark's patch into your git tree then apply mine on
> top I think. Git will see the same patch in both trees and resolve it all
> nicely for -next.

Have a pointer to which patch that was?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-03 23:06                   ` Greg KH
@ 2011-05-04  8:57                     ` Mark Brown
  2011-05-10 20:01                       ` Greg KH
  0 siblings, 1 reply; 42+ messages in thread
From: Mark Brown @ 2011-05-04  8:57 UTC (permalink / raw)
  To: Greg KH; +Cc: Alan Cox, linux-kernel

On Tue, May 03, 2011 at 04:06:30PM -0700, Greg KH wrote:
> On Tue, May 03, 2011 at 11:59:17PM +0100, Alan Cox wrote:

> > Best bet is to apply Mark's patch into your git tree then apply mine on
> > top I think. Git will see the same patch in both trees and resolve it all
> > nicely for -next.

> Have a pointer to which patch that was?

It's 774fd7 (sst: fix compile error) which is in -next.

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield
  2011-05-04  8:57                     ` Mark Brown
@ 2011-05-10 20:01                       ` Greg KH
  0 siblings, 0 replies; 42+ messages in thread
From: Greg KH @ 2011-05-10 20:01 UTC (permalink / raw)
  To: Mark Brown; +Cc: Alan Cox, linux-kernel

On Wed, May 04, 2011 at 09:57:53AM +0100, Mark Brown wrote:
> On Tue, May 03, 2011 at 04:06:30PM -0700, Greg KH wrote:
> > On Tue, May 03, 2011 at 11:59:17PM +0100, Alan Cox wrote:
> 
> > > Best bet is to apply Mark's patch into your git tree then apply mine on
> > > top I think. Git will see the same patch in both trees and resolve it all
> > > nicely for -next.
> 
> > Have a pointer to which patch that was?
> 
> It's 774fd7 (sst: fix compile error) which is in -next.

That's one of the, I needed another as well :)

Anyway, I've queued all of these up now so hopefully we should all be in
sync correctly.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2011-05-10 20:08 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 07/23] intel_sst: DMIC routing Alan Cox
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

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.