diff options
author | Lu Guanqun <guanqun.lu@intel.com> | 2011-05-03 17:43:40 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-10 13:00:49 -0700 |
commit | 2124f8dad0334270a26334c0c23b67abfeaef954 (patch) | |
tree | ff8f4b70ec2c5da3cb841e841f96ec54a3341612 /drivers/staging/intel_sst | |
parent | b8df15b2a7479903eb7051ce96a5c8dac5e60a18 (diff) |
intel_sst: internal speaker needs setting a GPIO line
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/intel_sst')
-rw-r--r-- | drivers/staging/intel_sst/intel_sst.h | 2 | ||||
-rw-r--r-- | drivers/staging/intel_sst/intelmid.c | 13 | ||||
-rw-r--r-- | 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 986a3dfefd16..635cf58ca881 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 cbe09f2bde39..25656ad2802e 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 82191dc8d4e7..5c5bd5e05fe5 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/file.h> #include <sound/control.h> @@ -86,6 +87,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 * @@ -212,6 +219,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); } @@ -273,7 +290,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) @@ -283,6 +299,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; @@ -518,9 +538,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); |