Skip to contentSkip to conversation

Intel SST driver update

PATCH In review Alan Cox 3 participants 42 messages May 3, 2011 – May 10, 2011 Staging

lore
Share & tools
lore

Alan Cox

author
#0 lore raw

cover Intel SST driver update

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
Signature · 2 lines
	"Policy is a poor man's substitute for common sense."
			-- David Woodhouse
author
#1 lore raw

PATCH 1/23 intel_sst: Save audio state across D3 on Medfield

From: Vinod Koul <[email protected]>

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

---

 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(-)
drivers/staging/intel_sst/intel_sst.c +63 -4
index 81c24d1..2f21f42 100644
@@ -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;
drivers/staging/intel_sst/intel_sst_common.h +6 -3
index 0a60e86..0f48838 100644
@@ -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;
drivers/staging/intel_sst/intel_sst_drv_interface.c +2 -0
index 971588c..78ee44d 100644
@@ -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);
drivers/staging/intel_sst/intel_sst_dsp.c +10 -4
index bffe4c6..a89e1ad 100644
@@ -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");
 
drivers/staging/intel_sst/intel_sst_fw_ipc.h +6 -0
index 0f0c5bb..8628a8a 100644
@@ -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__ */
drivers/staging/intel_sst/intel_sst_ipc.c +52 -4

89 lines not on this page · raw message

drivers/staging/intel_sst/intel_sst_stream.c +7 -4
index dd58be5..55a561c 100644
@@ -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);
drivers/staging/intel_sst/intel_sst_stream_encoded.c +2 -6
index d5f07b8..2be58c5 100644
@@ -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,
drivers/staging/intel_sst/intelmid.c +0 -2
index ebb6d03..0925a88 100644
@@ -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;
#2 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 11 lines · Alan Cox

From: Vinod Koul <[email protected]>

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

Something is messed up here as:

drivers/staging/intel_sst/intel_sst_drv_interface.c int register_sst_card(struct intel_sst_card_ops *card) · line 514

Quoted 10 lines
drivers/staging/intel_sst/intel_sst_drv_interface.c +1 -0
@@ -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

author
#3 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 6 lines
Quoted 3 lines

Something is messed up here as:

Quoted 14 lines

drivers/staging/intel_sst/intel_sst_drv_interface.c int register_sst_card(struct intel_sst_card_ops *card) · line 514

Quoted 10 lines
drivers/staging/intel_sst/intel_sst_drv_interface.c +1 -0
@@ -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

#4 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 8 lines · Alan Cox

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.

Quoted 3 lines

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.

author
#5 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 2 lines

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

#6 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 11 lines · Alan Cox
Quoted 2 lines

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

#7 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 4 lines · Greg KH

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.

#8 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 9 lines · Mark Brown
Quoted 4 lines · Greg KH

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.

Quoted 3 lines

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

author
#9 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 8 lines
Quoted 3 lines

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

#10 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 4 lines · Alan Cox
Quoted 4 lines
Quoted 3 lines

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.

Quoted 8 lines
Quoted 4 lines

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

#11 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 7 lines · Greg KH
Quoted 3 lines · Alan Cox

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.

#12 lore raw

Re: [PATCH 01/23] intel_sst: Save audio state across D3 on Medfield

Quoted 10 lines · Mark Brown
Quoted 7 lines · Greg KH
Quoted 3 lines · Alan Cox

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

author
#13 lore raw

PATCH 2/23 intel_sst: MSIC codec power optimisation

In reply to Alan Cox

From: Vinod Koul <[email protected]>

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

---

 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(-)
drivers/staging/intel_sst/intel_sst.h +2 -2
index cb03ff7..bf0f9e2 100644
@@ -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);
 };
 
drivers/staging/intel_sst/intel_sst_drv_interface.c +6 -4
index 78ee44d..a47e382 100644
@@ -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]);
 	}
 }
 
drivers/staging/intel_sst/intelmid_msic_control.c +187 -88

422 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_v0_control.c +2 -2
index 7756f8f..6cf5901 100644
@@ -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},
drivers/staging/intel_sst/intelmid_v1_control.c +2 -2
index 1ea8142..445e0fb 100644
@@ -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},
drivers/staging/intel_sst/intelmid_v2_control.c +2 -2
index 3c6b3ab..28754a5 100644
@@ -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},
#14 lore raw

Re: [PATCH 02/23] intel_sst: MSIC codec power optimisation

Quoted 4 lines · Alan Cox

From: Vinod Koul <[email protected]>

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.

author
#15 lore raw

Re: [PATCH 02/23] intel_sst: MSIC codec power optimisation

Quoted 9 lines · On Tue, 3 May 2011 17:58:38 +0100 Mark Brown…
Quoted 4 lines · Alan Cox

From: Vinod Koul <[email protected]>

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

#16 lore raw

Re: [PATCH 02/23] intel_sst: MSIC codec power optimisation

Quoted 10 lines · Alan Cox
Quoted 2 lines · Mark Brown

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?

author
#17 lore raw

PATCH 3/23 intel_sst: fix unload bugs

In reply to Alan Cox

From: Vinod Koul <[email protected]>

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

This patch fixes both of these issues

---

 drivers/staging/intel_sst/intel_sst.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)
drivers/staging/intel_sst/intel_sst.c +6 -6
index 2f21f42..c40e00a 100644
@@ -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;
 }
 
author
#18 lore raw

PATCH 4/23 intel_sst: ignore IRQ when suspended

In reply to Alan Cox

From: Vinod Koul <[email protected]>

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.

---

 drivers/staging/intel_sst/intel_sst.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/staging/intel_sst/intel_sst.c +3 -0
index c40e00a..e7c2617 100644
@@ -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);
 
author
#19 lore raw

PATCH 5/23 intel_sst: Line out support

In reply to Alan Cox

From: Dharageswari R <[email protected]>

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

---

 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(-)
drivers/staging/intel_sst/intel_sst.h +4 -2
index bf0f9e2..ea6cd97 100644
@@ -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);
 
drivers/staging/intel_sst/intel_sst_common.h +2 -2
index 0f48838..9aff1a3 100644
@@ -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"
drivers/staging/intel_sst/intel_sst_drv_interface.c +6 -1
index a47e382..1e8c056 100644
@@ -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)
drivers/staging/intel_sst/intel_sst_stream.c +2 -0
index 55a561c..dd9c530 100644
@@ -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;
drivers/staging/intel_sst/intelmid.c +2 -1
index 0925a88..ee070e3 100644
@@ -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 */
drivers/staging/intel_sst/intelmid.h +6 -2
index e77da87..4ed4a94 100644
@@ -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);
drivers/staging/intel_sst/intelmid_ctrl.c +44 -2

90 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_msic_control.c +242 -12

359 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_snd_control.h +7 -0
index a4565f3..c7e9f16 100644
@@ -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,
drivers/staging/intel_sst/intelmid_v0_control.c +5 -1
index 6cf5901..964c412 100644
@@ -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,
drivers/staging/intel_sst/intelmid_v1_control.c +5 -0
index 445e0fb..4f2b34f 100644
@@ -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,
drivers/staging/intel_sst/intelmid_v2_control.c +5 -1
index 28754a5..a0cd227 100644
@@ -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,
author
#20 lore raw

PATCH 6/23 intel_sst: parameter tuning ioctl

In reply to Alan Cox

From: Vinod Koul <[email protected]>

This patch adds new IOCTL for application interface.

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

---

 .../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(-)
drivers/staging/intel_sst/intel_sst_app_interface.c +37 -0
index d7454e2..b8c7ddb 100644
@@ -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;
 	}
drivers/staging/intel_sst/intel_sst_common.h +2 -2
index 9aff1a3..e37b377 100644
@@ -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"
drivers/staging/intel_sst/intel_sst_fw_ipc.h +1 -0
index 8628a8a..5d0cc56 100644
@@ -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 */
drivers/staging/intel_sst/intel_sst_ioctl.h +8 -0
index bebc395..5da5ee0 100644
@@ -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__ */
drivers/staging/intel_sst/intel_sst_ipc.c +18 -0
index 878b19d..5c3444f 100644
@@ -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;
author
#21 lore raw

PATCH 7/23 intel_sst: DMIC routing

In reply to Alan Cox

From: Sitanshu Nanavati <[email protected]>

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

---

 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(-)
drivers/staging/intel_sst/intel_sst.h +4 -0
index ea6cd97..c0d3156 100644
@@ -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 {
drivers/staging/intel_sst/intel_sst_stream.c +1 -1
index dd9c530..be4565e 100644
@@ -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;
 	}
drivers/staging/intel_sst/intelmid.h +9 -2
index 4ed4a94..7b3dbf6 100644
@@ -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);
drivers/staging/intel_sst/intelmid_ctrl.c +198 -0

215 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_msic_control.c +58 -0

78 lines not on this page · raw message

author
#22 lore raw

PATCH 8/23 intel_sst: rework jack implementation

In reply to Alan Cox

From: Ramesh Babu K V <[email protected]>

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

---

 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
drivers/staging/intel_sst/intel_sst.h +16 -0
index c0d3156..986a3df 100644
@@ -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);
drivers/staging/intel_sst/intel_sst_common.h +2 -2
index e37b377..f8e9da6 100644
@@ -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"
drivers/staging/intel_sst/intelmid.c +115 -334

630 lines not on this page · raw message

drivers/staging/intel_sst/intelmid.h +14 -0
index 7b3dbf6..3201d5a 100644
@@ -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 */
drivers/staging/intel_sst/intelmid_adc_control.h new file +193 -0

193 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_ctrl.c +0 -1
index dbe29c3..2c3ee94 100644
@@ -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"
drivers/staging/intel_sst/intelmid_msic_control.c +253 -5

362 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_pvt.c +0 -1
index 3ba9daf..90e0e64 100644
@@ -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"
drivers/staging/intel_sst/intelmid_v0_control.c +100 -11

144 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_v1_control.c +131 -11

168 lines not on this page · raw message

drivers/staging/intel_sst/intelmid_v2_control.c +63 -6

96 lines not on this page · raw message

drivers/staging/intel_sst/jack.h deleted +0 -10
deleted file mode 100644
index 9a6e483..0000000
@@ -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)
-
-
author
#23 lore raw

PATCH 9/23 intel_sst: Set de-bounce time

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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.

---

 drivers/staging/intel_sst/intelmid_v2_control.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +5 -1
index 10762d7..48ef2fa 100644
@@ -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:
author
#24 lore raw

PATCH 10/23 intel_sst: Enable recording via HS_MIC

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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

---

 drivers/staging/intel_sst/intelmid_v2_control.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +4 -1
index 48ef2fa..cae7bc2 100644
@@ -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:
author
#25 lore raw

PATCH 11/23 intel_sst: Enable recording via DMIC

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

We may need to make some of this board specific eventually

---

 drivers/staging/intel_sst/intelmid_v2_control.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +4 -4
index cae7bc2..3d90f45 100644
@@ -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:
author
#26 lore raw

PATCH 12/23 intel_sst: Headphone Automute support

In reply to Alan Cox

From: xingchao <[email protected]>

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

---

 drivers/staging/intel_sst/intelmid_v2_control.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +15 -0
index 3d90f45..7cae970 100644
@@ -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) {
author
#27 lore raw

PATCH 13/23 intel_sst: move jack detection related configs to init time

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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.

---

 drivers/staging/intel_sst/intelmid_v2_control.c |   28 +++++++++++------------
 1 files changed, 13 insertions(+), 15 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +13 -15
index 7cae970..6f4caa5 100644
@@ -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;
author
#28 lore raw

PATCH 14/23 sst: return correct output/input device id

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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.

---

 drivers/staging/intel_sst/intelmid_ctrl.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)
drivers/staging/intel_sst/intelmid_ctrl.c +20 -1
index 2c3ee94..af9e112 100644
@@ -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;
#29 lore raw
In reply to Alan Cox
Quoted 3 lines · Alan Cox

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.

author
#30 lore raw
Quoted 9 lines · On Tue, 3 May 2011 18:15:38 +0100 Mark Brown…
Quoted 3 lines · Alan Cox

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

#31 lore raw
Quoted 10 lines · Alan Cox
Quoted 4 lines · Mark Brown

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...

Quoted 2 lines

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.

author
#32 lore raw
Quoted 3 lines

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.

Quoted 5 lines
Quoted 2 lines

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

author
#33 lore raw

PATCH 15/23 intel_sst: make sure the sst_drop_stream() get called when needed

In reply to Alan Cox

From: Feng Tang <[email protected]>

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.

---

 .../staging/intel_sst/intel_sst_drv_interface.c    |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/staging/intel_sst/intel_sst_drv_interface.c +2 -2
index 1e8c056..bb64f2a 100644
@@ -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);
author
#34 lore raw

PATCH 16/23 intel_sst: MRST can only do mono recording

In reply to Alan Cox

From: Wu Fengguang <[email protected]>

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.

---

 drivers/staging/intel_sst/intelmid.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
drivers/staging/intel_sst/intelmid.c +7 -0
index 61ef4a6..0b9b1b6 100644
@@ -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;
author
#35 lore raw

PATCH 17/23 intel_sst: MRST can only do 16bit recording

In reply to Alan Cox

From: Wu Fengguang <[email protected]>

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.

---

 drivers/staging/intel_sst/intelmid.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/staging/intel_sst/intelmid.c +4 -1
index 0b9b1b6..cbe09f2 100644
@@ -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;
author
#36 lore raw

PATCH 18/23 intel_sst: intelmid_v2_control: correct jack event type

In reply to Alan Cox

From: Andy CH Lin <[email protected]>

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

---

 drivers/staging/intel_sst/intelmid_v2_control.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +1 -1
index 6f4caa5..547b8b1 100644
@@ -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)
author
#37 lore raw

PATCH 19/23 intel_sst: fix runtime pm issue

In reply to Alan Cox

From: Chandramouli Narayanan <[email protected]>

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

---

 drivers/staging/intel_sst/intel_sst.c |   47 +++++++++++++++++++++++++++------
 1 files changed, 38 insertions(+), 9 deletions(-)
drivers/staging/intel_sst/intel_sst.c +38 -9
index e7c2617..c0c144a 100644
@@ -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)
author
#38 lore raw

PATCH 20/23 sst: set default output and input device

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

---

 drivers/staging/intel_sst/intelmid_v2_control.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/staging/intel_sst/intelmid_v2_control.c +2 -0
index 547b8b1..5e61fe8 100644
@@ -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,
author
#39 lore raw

PATCH 21/23 intel_sst: add Master Volume

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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

---

 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(-)
drivers/staging/intel_sst/intelmid.h +5 -2
index 3201d5a..14a7ba0 100644
@@ -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 {
drivers/staging/intel_sst/intelmid_ctrl.c +36 -4
index af9e112..19ec474 100644
@@ -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,
drivers/staging/intel_sst/intelmid_snd_control.h +2 -0
index c7e9f16..06ad3a1 100644
@@ -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,
drivers/staging/intel_sst/intelmid_v2_control.c +38 -10

80 lines not on this page · raw message

author
#40 lore raw

PATCH 22/23 sst: internal speaker needs setting a GPIO line

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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

---

 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(-)
drivers/staging/intel_sst/intel_sst.h +2 -0
index 986a3df..635cf58 100644
@@ -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,
drivers/staging/intel_sst/intelmid.c +11 -2
index cbe09f2..25656ad 100644
@@ -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);
 	}
drivers/staging/intel_sst/intelmid_v2_control.c +24 -1
index b19f51e..2dc6738 100644
@@ -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);
author
#41 lore raw

PATCH 23/23 intel_sst: fix output noises when it's not in playback

In reply to Alan Cox

From: Lu Guanqun <[email protected]>

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.

---

 drivers/staging/intel_sst/intel_sst.h           |    1 +
 drivers/staging/intel_sst/intelmid_v2_control.c |   33 +++++++++++++++++------
 2 files changed, 25 insertions(+), 9 deletions(-)
drivers/staging/intel_sst/intel_sst.h +1 -0
index 635cf58..4ad2829 100644
@@ -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;
drivers/staging/intel_sst/intelmid_v2_control.c +24 -9
index 2dc6738..000378a 100644
@@ -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;
 }