mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
ASoC: Additional updates for v3.7
A couple more updates for 3.7, enhancements to the ux500 and wm2000 drivers, a new driver for DA9055 and the support for regulator bypass mode. With the exception of the DA9055 this has all had a chance to soak in -next (the driver was added on Friday so should be in -next today). -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJQaWzdAAoJEOoSHmUN5Tg4UB0P/Avr2Xbg+aH6hrqcSBe7TR1C 410uSU/4b9vz3BOoZ3ITW8+6C9chwtnOPuRsCtUQbWFy8Rd9rZvmNQL2xLYK/NMt tMvRMJXQZtwGCes8Agw5mme9Pcun7ra5vKwQ93mxvTqAQOkLTlCo43PcXSr9j8+Z QnnVlajOECm3+PjwXzQ9dwc+QhgAiLR35Xhe7CsCKvj278Ng4FenZpxj+FySaXhL rZnSnImNUn/zAuSIlsOasTOciSNwuqrGcdholpWcFJ8qHzAmntAL4VBrQQl3FNNh qTsrIzzlByEdK5qFr8/7erRlni4Xy1YmSOhtJ85fGFfo62xUK+cdLCpvPFKwqTPt GfQtsqnKTUNBUSoAHDHWCf0zP4/80ZD4XTEpt8+3Oj7QsKzwU2YS3gNf9zQktDtZ lMKo/yN0ihPAmIHLtQdXpNDCuZDyurP/r11sJku4GQXnQG302pzGo8Lc5mig7Tzw 5TDQ58OY4Gz4pJZ7y70nGn8+z3nMMBkoMFXZD1dBxgQnNdvNWrgu1jiGPOHrHXMm TkVS3i7VWXAwX5jAGnXeUOuNmlGsvHE/WO7dantGGgf1ef06oqcM/FEeew7heme0 oLYiklbhaxdWED632FVjzsOpgEwTF+QUqKpzAMFsFieK9yQzFiZ2mkuMT+1QoQaI 8ksSVvD1cP/yXkVf8h1E =nHb7 -----END PGP SIGNATURE----- Merge tag 'asoc-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next ASoC: Additional updates for v3.7 A couple more updates for 3.7, enhancements to the ux500 and wm2000 drivers, a new driver for DA9055 and the support for regulator bypass mode. With the exception of the DA9055 this has all had a chance to soak in -next (the driver was added on Friday so should be in -next today).
This commit is contained in:
commit
0fd0ba5f9e
@ -349,3 +349,24 @@ Description:
|
||||
|
||||
This will be one of the same strings reported by
|
||||
the "state" attribute.
|
||||
|
||||
What: /sys/class/regulator/.../bypass
|
||||
Date: September 2012
|
||||
KernelVersion: 3.7
|
||||
Contact: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
Description:
|
||||
Some regulator directories will contain a field called
|
||||
bypass. This indicates if the device is in bypass mode.
|
||||
|
||||
This will be one of the following strings:
|
||||
|
||||
'enabled'
|
||||
'disabled'
|
||||
'unknown'
|
||||
|
||||
'enabled' means the regulator is in bypass mode.
|
||||
|
||||
'disabled' means that the regulator is regulating.
|
||||
|
||||
'unknown' means software cannot determine the state, or
|
||||
the reported state is invalid.
|
||||
|
36
Documentation/devicetree/bindings/sound/cs4271.txt
Normal file
36
Documentation/devicetree/bindings/sound/cs4271.txt
Normal file
@ -0,0 +1,36 @@
|
||||
Cirrus Logic CS4271 DT bindings
|
||||
|
||||
This driver supports both the I2C and the SPI bus.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "cirrus,cs4271"
|
||||
|
||||
For required properties on SPI, please consult
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
Required properties on I2C:
|
||||
|
||||
- reg: the i2c address
|
||||
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reset-gpio: a GPIO spec to define which pin is connected to the chip's
|
||||
!RESET pin
|
||||
|
||||
Examples:
|
||||
|
||||
codec_i2c: cs4271@10 {
|
||||
compatible = "cirrus,cs4271";
|
||||
reg = <0x10>;
|
||||
reset-gpio = <&gpio 23 0>;
|
||||
};
|
||||
|
||||
codec_spi: cs4271@0 {
|
||||
compatible = "cirrus,cs4271";
|
||||
reg = <0x0>;
|
||||
reset-gpio = <&gpio 23 0>;
|
||||
spi-max-frequency = <6000000>;
|
||||
};
|
||||
|
39
Documentation/devicetree/bindings/sound/ux500-mop500.txt
Normal file
39
Documentation/devicetree/bindings/sound/ux500-mop500.txt
Normal file
@ -0,0 +1,39 @@
|
||||
* MOP500 Audio Machine Driver
|
||||
|
||||
This node is responsible for linking together all ux500 Audio Driver components.
|
||||
|
||||
Required properties:
|
||||
- compatible : "stericsson,snd-soc-mop500"
|
||||
|
||||
Non-standard properties:
|
||||
- stericsson,cpu-dai : Phandle to the CPU-side DAI
|
||||
- stericsson,audio-codec : Phandle to the Audio CODEC
|
||||
- stericsson,card-name : Over-ride default card name
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "stericsson,snd-soc-mop500";
|
||||
|
||||
stericsson,cpu-dai = <&msp1 &msp3>;
|
||||
stericsson,audio-codec = <&codec>;
|
||||
};
|
||||
|
||||
msp1: msp@80124000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80124000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
msp3: msp@80125000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80125000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
codec: ab8500-codec {
|
||||
compatible = "stericsson,ab8500-codec";
|
||||
stericsson,earpeice-cmv = <950>; /* Units in mV. */
|
||||
};
|
43
Documentation/devicetree/bindings/sound/ux500-msp.txt
Normal file
43
Documentation/devicetree/bindings/sound/ux500-msp.txt
Normal file
@ -0,0 +1,43 @@
|
||||
* ux500 MSP (CPU-side Digital Audio Interface)
|
||||
|
||||
Required properties:
|
||||
- compatible :"stericsson,ux500-msp-i2s"
|
||||
- reg : Physical base address and length of the device's registers.
|
||||
|
||||
Optional properties:
|
||||
- interrupts : The interrupt output from the device.
|
||||
- interrupt-parent : The parent interrupt controller.
|
||||
- <name>-supply : Phandle to the regulator <name> supply
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "stericsson,snd-soc-mop500";
|
||||
|
||||
stericsson,platform-pcm-dma = <&pcm>;
|
||||
stericsson,cpu-dai = <&msp1 &msp3>;
|
||||
stericsson,audio-codec = <&codec>;
|
||||
};
|
||||
|
||||
pcm: ux500-pcm {
|
||||
compatible = "stericsson,ux500-pcm";
|
||||
};
|
||||
|
||||
msp1: msp@80124000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80124000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
msp3: msp@80125000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80125000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
codec: ab8500-codec {
|
||||
compatible = "stericsson,ab8500-codec";
|
||||
stericsson,earpeice-cmv = <950>; /* Units in mV. */
|
||||
};
|
@ -348,4 +348,5 @@ void __init eukrea_mbimx27_baseboard_init(void)
|
||||
imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data);
|
||||
|
||||
gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info);
|
||||
imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
@ -306,4 +306,5 @@ void __init eukrea_mbimxsd25_baseboard_init(void)
|
||||
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
|
||||
gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
|
||||
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
|
||||
imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
@ -315,4 +315,5 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
|
||||
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
|
||||
gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
|
||||
imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
|
||||
imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
@ -228,4 +228,5 @@ void __init eukrea_mbimxsd51_baseboard_init(void)
|
||||
|
||||
gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info);
|
||||
imx_add_gpio_keys(&eukrea_mbimxsd51_button_data);
|
||||
imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include <plat/gpio-nomadik.h>
|
||||
#include <plat/pincfg.h>
|
||||
@ -23,53 +22,6 @@
|
||||
#include "devices-db8500.h"
|
||||
#include "pins-db8500.h"
|
||||
|
||||
/* MSP1/3 Tx/Rx usage protection */
|
||||
static DEFINE_SPINLOCK(msp_rxtx_lock);
|
||||
|
||||
/* Reference Count */
|
||||
static int msp_rxtx_ref;
|
||||
|
||||
/* Pin modes */
|
||||
struct pinctrl *msp1_p;
|
||||
struct pinctrl_state *msp1_def;
|
||||
struct pinctrl_state *msp1_sleep;
|
||||
|
||||
int msp13_i2s_init(void)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msp_rxtx_lock, flags);
|
||||
if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_def))) {
|
||||
retval = pinctrl_select_state(msp1_p, msp1_def);
|
||||
if (retval)
|
||||
pr_err("could not set MSP1 defstate\n");
|
||||
}
|
||||
if (!retval)
|
||||
msp_rxtx_ref++;
|
||||
spin_unlock_irqrestore(&msp_rxtx_lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int msp13_i2s_exit(void)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msp_rxtx_lock, flags);
|
||||
WARN_ON(!msp_rxtx_ref);
|
||||
msp_rxtx_ref--;
|
||||
if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_sleep))) {
|
||||
retval = pinctrl_select_state(msp1_p, msp1_sleep);
|
||||
if (retval)
|
||||
pr_err("could not set MSP1 sleepstate\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&msp_rxtx_lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct stedma40_chan_cfg msp0_dma_rx = {
|
||||
.high_priority = true,
|
||||
.dir = STEDMA40_PERIPH_TO_MEM,
|
||||
@ -132,8 +84,6 @@ static struct msp_i2s_platform_data msp1_platform_data = {
|
||||
.id = MSP_I2S_1,
|
||||
.msp_i2s_dma_rx = NULL,
|
||||
.msp_i2s_dma_tx = &msp1_dma_tx,
|
||||
.msp_i2s_init = msp13_i2s_init,
|
||||
.msp_i2s_exit = msp13_i2s_exit,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg msp2_dma_rx = {
|
||||
@ -219,49 +169,22 @@ static struct msp_i2s_platform_data msp3_platform_data = {
|
||||
.id = MSP_I2S_3,
|
||||
.msp_i2s_dma_rx = &msp1_dma_rx,
|
||||
.msp_i2s_dma_tx = NULL,
|
||||
.msp_i2s_init = msp13_i2s_init,
|
||||
.msp_i2s_exit = msp13_i2s_exit,
|
||||
};
|
||||
|
||||
int mop500_msp_init(struct device *parent)
|
||||
{
|
||||
struct platform_device *msp1;
|
||||
|
||||
pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
|
||||
platform_device_register(&snd_soc_mop500);
|
||||
|
||||
pr_info("Initialize MSP I2S-devices.\n");
|
||||
db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
|
||||
&msp0_platform_data);
|
||||
msp1 = db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
|
||||
db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
|
||||
&msp1_platform_data);
|
||||
db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2,
|
||||
&msp2_platform_data);
|
||||
db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
|
||||
&msp3_platform_data);
|
||||
|
||||
/* Get the pinctrl handle for MSP1 */
|
||||
if (msp1) {
|
||||
msp1_p = pinctrl_get(&msp1->dev);
|
||||
if (IS_ERR(msp1_p))
|
||||
dev_err(&msp1->dev, "could not get MSP1 pinctrl\n");
|
||||
else {
|
||||
msp1_def = pinctrl_lookup_state(msp1_p,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(msp1_def)) {
|
||||
dev_err(&msp1->dev,
|
||||
"could not get MSP1 defstate\n");
|
||||
}
|
||||
msp1_sleep = pinctrl_lookup_state(msp1_p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(msp1_sleep))
|
||||
dev_err(&msp1->dev,
|
||||
"could not get MSP1 idlestate\n");
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
|
||||
platform_device_register(&ux500_pcm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,8 +22,6 @@ struct msp_i2s_platform_data {
|
||||
enum msp_i2s_id id;
|
||||
struct stedma40_chan_cfg *msp_i2s_dma_rx;
|
||||
struct stedma40_chan_cfg *msp_i2s_dma_tx;
|
||||
int (*msp_i2s_init) (void);
|
||||
int (*msp_i2s_exit) (void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -434,6 +434,11 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
|
||||
regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
|
||||
ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
|
||||
|
||||
ret = regulator_allow_bypass(info->micvdd, true);
|
||||
if (ret != 0)
|
||||
dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
|
||||
ret);
|
||||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
@ -39,6 +39,8 @@ static struct regulator_ops arizona_ldo1_ops = {
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc arizona_ldo1 = {
|
||||
@ -49,6 +51,8 @@ static const struct regulator_desc arizona_ldo1 = {
|
||||
|
||||
.vsel_reg = ARIZONA_LDO1_CONTROL_1,
|
||||
.vsel_mask = ARIZONA_LDO1_VSEL_MASK,
|
||||
.bypass_reg = ARIZONA_LDO1_CONTROL_1,
|
||||
.bypass_mask = ARIZONA_LDO1_BYPASS,
|
||||
.min_uV = 900000,
|
||||
.uV_step = 50000,
|
||||
.n_voltages = 7,
|
||||
|
@ -82,6 +82,9 @@ static struct regulator_ops arizona_micsupp_ops = {
|
||||
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc arizona_micsupp = {
|
||||
@ -95,6 +98,8 @@ static const struct regulator_desc arizona_micsupp = {
|
||||
.vsel_mask = ARIZONA_LDO2_VSEL_MASK,
|
||||
.enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
|
||||
.enable_mask = ARIZONA_CPMIC_ENA,
|
||||
.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
|
||||
.bypass_mask = ARIZONA_CPMIC_BYPASS,
|
||||
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
@ -77,6 +77,7 @@ struct regulator {
|
||||
struct device *dev;
|
||||
struct list_head list;
|
||||
unsigned int always_on:1;
|
||||
unsigned int bypass:1;
|
||||
int uA_load;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
@ -394,6 +395,9 @@ static ssize_t regulator_status_show(struct device *dev,
|
||||
case REGULATOR_STATUS_STANDBY:
|
||||
label = "standby";
|
||||
break;
|
||||
case REGULATOR_STATUS_BYPASS:
|
||||
label = "bypass";
|
||||
break;
|
||||
case REGULATOR_STATUS_UNDEFINED:
|
||||
label = "undefined";
|
||||
break;
|
||||
@ -585,6 +589,27 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev,
|
||||
static DEVICE_ATTR(suspend_standby_state, 0444,
|
||||
regulator_suspend_standby_state_show, NULL);
|
||||
|
||||
static ssize_t regulator_bypass_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct regulator_dev *rdev = dev_get_drvdata(dev);
|
||||
const char *report;
|
||||
bool bypass;
|
||||
int ret;
|
||||
|
||||
ret = rdev->desc->ops->get_bypass(rdev, &bypass);
|
||||
|
||||
if (ret != 0)
|
||||
report = "unknown";
|
||||
else if (bypass)
|
||||
report = "enabled";
|
||||
else
|
||||
report = "disabled";
|
||||
|
||||
return sprintf(buf, "%s\n", report);
|
||||
}
|
||||
static DEVICE_ATTR(bypass, 0444,
|
||||
regulator_bypass_show, NULL);
|
||||
|
||||
/*
|
||||
* These are the only attributes are present for all regulators.
|
||||
@ -2673,6 +2698,100 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
|
||||
|
||||
/**
|
||||
* regulator_set_bypass_regmap - Default set_bypass() using regmap
|
||||
*
|
||||
* @rdev: device to operate on.
|
||||
* @enable: state to set.
|
||||
*/
|
||||
int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
if (enable)
|
||||
val = rdev->desc->bypass_mask;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
|
||||
rdev->desc->bypass_mask, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
|
||||
|
||||
/**
|
||||
* regulator_get_bypass_regmap - Default get_bypass() using regmap
|
||||
*
|
||||
* @rdev: device to operate on.
|
||||
* @enable: current state.
|
||||
*/
|
||||
int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
*enable = val & rdev->desc->bypass_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
|
||||
|
||||
/**
|
||||
* regulator_allow_bypass - allow the regulator to go into bypass mode
|
||||
*
|
||||
* @regulator: Regulator to configure
|
||||
* @allow: enable or disable bypass mode
|
||||
*
|
||||
* Allow the regulator to go into bypass mode if all other consumers
|
||||
* for the regulator also enable bypass mode and the machine
|
||||
* constraints allow this. Bypass mode means that the regulator is
|
||||
* simply passing the input directly to the output with no regulation.
|
||||
*/
|
||||
int regulator_allow_bypass(struct regulator *regulator, bool enable)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (!rdev->desc->ops->set_bypass)
|
||||
return 0;
|
||||
|
||||
if (rdev->constraints &&
|
||||
!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&rdev->mutex);
|
||||
|
||||
if (enable && !regulator->bypass) {
|
||||
rdev->bypass_count++;
|
||||
|
||||
if (rdev->bypass_count == rdev->open_count) {
|
||||
ret = rdev->desc->ops->set_bypass(rdev, enable);
|
||||
if (ret != 0)
|
||||
rdev->bypass_count--;
|
||||
}
|
||||
|
||||
} else if (!enable && regulator->bypass) {
|
||||
rdev->bypass_count--;
|
||||
|
||||
if (rdev->bypass_count != rdev->open_count) {
|
||||
ret = rdev->desc->ops->set_bypass(rdev, enable);
|
||||
if (ret != 0)
|
||||
rdev->bypass_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
regulator->bypass = enable;
|
||||
|
||||
mutex_unlock(&rdev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_allow_bypass);
|
||||
|
||||
/**
|
||||
* regulator_register_notifier - register regulator event notifier
|
||||
* @regulator: regulator source
|
||||
@ -3036,6 +3155,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
if (ops->get_bypass) {
|
||||
status = device_create_file(dev, &dev_attr_bypass);
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* some attributes are type-specific */
|
||||
if (rdev->desc->type == REGULATOR_CURRENT) {
|
||||
@ -3124,6 +3248,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
|
||||
&rdev->use_count);
|
||||
debugfs_create_u32("open_count", 0444, rdev->debugfs,
|
||||
&rdev->open_count);
|
||||
debugfs_create_u32("bypass_count", 0444, rdev->debugfs,
|
||||
&rdev->bypass_count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,6 +237,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
|
||||
.set_mode = wm831x_gp_ldo_set_mode,
|
||||
.get_status = wm831x_gp_ldo_get_status,
|
||||
.get_optimum_mode = wm831x_gp_ldo_get_optimum_mode,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
@ -293,6 +295,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK;
|
||||
ldo->desc.enable_reg = WM831X_LDO_ENABLE;
|
||||
ldo->desc.enable_mask = 1 << id;
|
||||
ldo->desc.bypass_reg = ldo->base;
|
||||
ldo->desc.bypass_mask = WM831X_LDO1_SWI;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
if (pdata)
|
||||
@ -488,6 +492,8 @@ static struct regulator_ops wm831x_aldo_ops = {
|
||||
.get_mode = wm831x_aldo_get_mode,
|
||||
.set_mode = wm831x_aldo_set_mode,
|
||||
.get_status = wm831x_aldo_get_status,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
@ -544,6 +550,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK;
|
||||
ldo->desc.enable_reg = WM831X_LDO_ENABLE;
|
||||
ldo->desc.enable_mask = 1 << id;
|
||||
ldo->desc.bypass_reg = ldo->base;
|
||||
ldo->desc.bypass_mask = WM831X_LDO7_SWI;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
if (pdata)
|
||||
|
@ -23,7 +23,8 @@ enum amic_type {
|
||||
/* Mic-biases */
|
||||
enum amic_micbias {
|
||||
AMIC_MICBIAS_VAMIC1,
|
||||
AMIC_MICBIAS_VAMIC2
|
||||
AMIC_MICBIAS_VAMIC2,
|
||||
AMIC_MICBIAS_UNKNOWN
|
||||
};
|
||||
|
||||
/* Bias-voltage */
|
||||
@ -31,7 +32,8 @@ enum ear_cm_voltage {
|
||||
EAR_CMV_0_95V,
|
||||
EAR_CMV_1_10V,
|
||||
EAR_CMV_1_27V,
|
||||
EAR_CMV_1_58V
|
||||
EAR_CMV_1_58V,
|
||||
EAR_CMV_UNKNOWN
|
||||
};
|
||||
|
||||
/* Analog microphone settings */
|
||||
|
@ -177,6 +177,8 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode);
|
||||
unsigned int regulator_get_mode(struct regulator *regulator);
|
||||
int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
|
||||
|
||||
int regulator_allow_bypass(struct regulator *regulator, bool allow);
|
||||
|
||||
/* regulator notifier block */
|
||||
int regulator_register_notifier(struct regulator *regulator,
|
||||
struct notifier_block *nb);
|
||||
@ -328,6 +330,12 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator,
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static inline int regulator_allow_bypass(struct regulator *regulator,
|
||||
bool allow)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int regulator_register_notifier(struct regulator *regulator,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
|
@ -32,6 +32,8 @@ enum regulator_status {
|
||||
REGULATOR_STATUS_NORMAL,
|
||||
REGULATOR_STATUS_IDLE,
|
||||
REGULATOR_STATUS_STANDBY,
|
||||
/* The regulator is enabled but not regulating */
|
||||
REGULATOR_STATUS_BYPASS,
|
||||
/* in case that any other status doesn't apply */
|
||||
REGULATOR_STATUS_UNDEFINED,
|
||||
};
|
||||
@ -67,6 +69,9 @@ enum regulator_status {
|
||||
* @get_optimum_mode: Get the most efficient operating mode for the regulator
|
||||
* when running with the specified parameters.
|
||||
*
|
||||
* @set_bypass: Set the regulator in bypass mode.
|
||||
* @get_bypass: Get the regulator bypass mode state.
|
||||
*
|
||||
* @enable_time: Time taken for the regulator voltage output voltage to
|
||||
* stabilise after being enabled, in microseconds.
|
||||
* @set_ramp_delay: Set the ramp delay for the regulator. The driver should
|
||||
@ -133,6 +138,10 @@ struct regulator_ops {
|
||||
unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
|
||||
int output_uV, int load_uA);
|
||||
|
||||
/* control and report on bypass mode */
|
||||
int (*set_bypass)(struct regulator_dev *dev, bool enable);
|
||||
int (*get_bypass)(struct regulator_dev *dev, bool *enable);
|
||||
|
||||
/* the operations below are for configuration of regulator state when
|
||||
* its parent PMIC enters a global STANDBY/HIBERNATE state */
|
||||
|
||||
@ -205,6 +214,8 @@ struct regulator_desc {
|
||||
unsigned int vsel_mask;
|
||||
unsigned int enable_reg;
|
||||
unsigned int enable_mask;
|
||||
unsigned int bypass_reg;
|
||||
unsigned int bypass_mask;
|
||||
|
||||
unsigned int enable_time;
|
||||
};
|
||||
@ -253,6 +264,7 @@ struct regulator_dev {
|
||||
int exclusive;
|
||||
u32 use_count;
|
||||
u32 open_count;
|
||||
u32 bypass_count;
|
||||
|
||||
/* lists we belong to */
|
||||
struct list_head list; /* list of all regulators */
|
||||
@ -310,6 +322,8 @@ int regulator_disable_regmap(struct regulator_dev *rdev);
|
||||
int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
unsigned int old_selector,
|
||||
unsigned int new_selector);
|
||||
int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable);
|
||||
int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable);
|
||||
|
||||
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
|
||||
|
||||
|
@ -32,6 +32,7 @@ struct regulator;
|
||||
* board/machine.
|
||||
* STATUS: Regulator can be enabled and disabled.
|
||||
* DRMS: Dynamic Regulator Mode Switching is enabled for this regulator.
|
||||
* BYPASS: Regulator can be put into bypass mode
|
||||
*/
|
||||
|
||||
#define REGULATOR_CHANGE_VOLTAGE 0x1
|
||||
@ -39,6 +40,7 @@ struct regulator;
|
||||
#define REGULATOR_CHANGE_MODE 0x4
|
||||
#define REGULATOR_CHANGE_STATUS 0x8
|
||||
#define REGULATOR_CHANGE_DRMS 0x10
|
||||
#define REGULATOR_CHANGE_BYPASS 0x20
|
||||
|
||||
/**
|
||||
* struct regulator_state - regulator state during low power system states
|
||||
|
33
include/sound/da9055.h
Normal file
33
include/sound/da9055.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* DA9055 ALSA Soc codec driver
|
||||
*
|
||||
* Copyright (c) 2012 Dialog Semiconductor
|
||||
*
|
||||
* Tested on (Samsung SMDK6410 board + DA9055 EVB) using I2S and I2C
|
||||
* Written by David Chen <david.chen@diasemi.com> and
|
||||
* Ashish Chavan <ashish.chavan@kpitcummins.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; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_DA9055_H__
|
||||
#define __SOUND_DA9055_H__
|
||||
|
||||
enum da9055_micbias_voltage {
|
||||
DA9055_MICBIAS_1_6V = 0,
|
||||
DA9055_MICBIAS_1_8V = 1,
|
||||
DA9055_MICBIAS_2_1V = 2,
|
||||
DA9055_MICBIAS_2_2V = 3,
|
||||
};
|
||||
|
||||
struct da9055_platform_data {
|
||||
/* Selects which of the two MicBias pins acts as the bias source */
|
||||
bool micbias_source;
|
||||
/* Selects the micbias voltage */
|
||||
enum da9055_micbias_voltage micbias;
|
||||
};
|
||||
|
||||
#endif
|
@ -320,6 +320,9 @@ struct device;
|
||||
#define SND_SOC_DAPM_EVENT_OFF(e) \
|
||||
(e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD))
|
||||
|
||||
/* regulator widget flags */
|
||||
#define SND_SOC_DAPM_REGULATOR_BYPASS 0x1 /* bypass when disabled */
|
||||
|
||||
struct snd_soc_dapm_widget;
|
||||
enum snd_soc_dapm_type;
|
||||
struct snd_soc_dapm_path;
|
||||
|
@ -37,6 +37,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_CX20442
|
||||
select SND_SOC_DA7210 if I2C
|
||||
select SND_SOC_DA732X if I2C
|
||||
select SND_SOC_DA9055 if I2C
|
||||
select SND_SOC_DFBMCS320
|
||||
select SND_SOC_ISABELLE if I2C
|
||||
select SND_SOC_JZ4740_CODEC
|
||||
@ -239,6 +240,9 @@ config SND_SOC_DA7210
|
||||
config SND_SOC_DA732X
|
||||
tristate
|
||||
|
||||
config SND_SOC_DA9055
|
||||
tristate
|
||||
|
||||
config SND_SOC_DFBMCS320
|
||||
tristate
|
||||
|
||||
|
@ -24,6 +24,7 @@ snd-soc-cs4271-objs := cs4271.o
|
||||
snd-soc-cx20442-objs := cx20442.o
|
||||
snd-soc-da7210-objs := da7210.o
|
||||
snd-soc-da732x-objs := da732x.o
|
||||
snd-soc-da9055-objs := da9055.o
|
||||
snd-soc-dfbmcs320-objs := dfbmcs320.o
|
||||
snd-soc-dmic-objs := dmic.o
|
||||
snd-soc-isabelle-objs := isabelle.o
|
||||
@ -144,6 +145,7 @@ obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
|
||||
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
|
||||
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
|
||||
obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
|
||||
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
|
||||
obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
|
||||
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
|
||||
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <linux/mfd/abx500/ab8500-sysctrl.h>
|
||||
#include <linux/mfd/abx500/ab8500-codec.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
@ -2394,9 +2395,65 @@ struct snd_soc_dai_driver ab8500_codec_dai[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static void ab8500_codec_of_probe(struct device *dev, struct device_node *np,
|
||||
struct ab8500_codec_platform_data *codec)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (of_get_property(np, "stericsson,amic1-type-single-ended", NULL))
|
||||
codec->amics.mic1_type = AMIC_TYPE_SINGLE_ENDED;
|
||||
else
|
||||
codec->amics.mic1_type = AMIC_TYPE_DIFFERENTIAL;
|
||||
|
||||
if (of_get_property(np, "stericsson,amic2-type-single-ended", NULL))
|
||||
codec->amics.mic2_type = AMIC_TYPE_SINGLE_ENDED;
|
||||
else
|
||||
codec->amics.mic2_type = AMIC_TYPE_DIFFERENTIAL;
|
||||
|
||||
/* Has a non-standard Vamic been requested? */
|
||||
if (of_get_property(np, "stericsson,amic1a-bias-vamic2", NULL))
|
||||
codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC2;
|
||||
else
|
||||
codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC1;
|
||||
|
||||
if (of_get_property(np, "stericsson,amic1b-bias-vamic2", NULL))
|
||||
codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC2;
|
||||
else
|
||||
codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC1;
|
||||
|
||||
if (of_get_property(np, "stericsson,amic2-bias-vamic1", NULL))
|
||||
codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC1;
|
||||
else
|
||||
codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC2;
|
||||
|
||||
if (!of_property_read_u32(np, "stericsson,earpeice-cmv", &value)) {
|
||||
switch (value) {
|
||||
case 950 :
|
||||
codec->ear_cmv = EAR_CMV_0_95V;
|
||||
break;
|
||||
case 1100 :
|
||||
codec->ear_cmv = EAR_CMV_1_10V;
|
||||
break;
|
||||
case 1270 :
|
||||
codec->ear_cmv = EAR_CMV_1_27V;
|
||||
break;
|
||||
case 1580 :
|
||||
codec->ear_cmv = EAR_CMV_1_58V;
|
||||
break;
|
||||
default :
|
||||
codec->ear_cmv = EAR_CMV_UNKNOWN;
|
||||
dev_err(dev, "Unsuitable earpiece voltage found in DT\n");
|
||||
}
|
||||
} else {
|
||||
dev_warn(dev, "No earpiece voltage found in DT - using default\n");
|
||||
codec->ear_cmv = EAR_CMV_0_95V;
|
||||
}
|
||||
}
|
||||
|
||||
static int ab8500_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct device *dev = codec->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
struct ab8500_platform_data *pdata;
|
||||
struct filter_control *fc;
|
||||
@ -2407,6 +2464,30 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
|
||||
/* Setup AB8500 according to board-settings */
|
||||
pdata = dev_get_platdata(dev->parent);
|
||||
|
||||
if (np) {
|
||||
if (!pdata)
|
||||
pdata = devm_kzalloc(dev,
|
||||
sizeof(struct ab8500_platform_data),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (pdata && !pdata->codec)
|
||||
pdata->codec
|
||||
= devm_kzalloc(dev,
|
||||
sizeof(struct ab8500_codec_platform_data),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!(pdata && pdata->codec))
|
||||
return -ENOMEM;
|
||||
|
||||
ab8500_codec_of_probe(dev, np, pdata->codec);
|
||||
|
||||
} else {
|
||||
if (!(pdata && pdata->codec)) {
|
||||
dev_err(dev, "No codec platform data or DT found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
status = ab8500_audio_setup_mics(codec, &pdata->codec->amics);
|
||||
if (status < 0) {
|
||||
pr_err("%s: Failed to setup mics (%d)!\n", __func__, status);
|
||||
|
@ -119,6 +119,24 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
|
||||
"DSP1.4",
|
||||
"DSP1.5",
|
||||
"DSP1.6",
|
||||
"DSP2.1",
|
||||
"DSP2.2",
|
||||
"DSP2.3",
|
||||
"DSP2.4",
|
||||
"DSP2.5",
|
||||
"DSP2.6",
|
||||
"DSP3.1",
|
||||
"DSP3.2",
|
||||
"DSP3.3",
|
||||
"DSP3.4",
|
||||
"DSP3.5",
|
||||
"DSP3.6",
|
||||
"DSP4.1",
|
||||
"DSP4.2",
|
||||
"DSP4.3",
|
||||
"DSP4.4",
|
||||
"DSP4.5",
|
||||
"DSP4.6",
|
||||
"ASRC1L",
|
||||
"ASRC1R",
|
||||
"ASRC2L",
|
||||
@ -180,6 +198,24 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
|
||||
0x6b,
|
||||
0x6c,
|
||||
0x6d,
|
||||
0x70, /* DSP2.1 */
|
||||
0x71,
|
||||
0x72,
|
||||
0x73,
|
||||
0x74,
|
||||
0x75,
|
||||
0x78, /* DSP3.1 */
|
||||
0x79,
|
||||
0x7a,
|
||||
0x7b,
|
||||
0x7c,
|
||||
0x7d,
|
||||
0x80, /* DSP4.1 */
|
||||
0x81,
|
||||
0x82,
|
||||
0x83,
|
||||
0x84,
|
||||
0x85,
|
||||
0x90, /* ASRC1L */
|
||||
0x91,
|
||||
0x92,
|
||||
@ -234,6 +270,9 @@ static unsigned int arizona_sysclk_48k_rates[] = {
|
||||
12288000,
|
||||
22579200,
|
||||
49152000,
|
||||
73728000,
|
||||
98304000,
|
||||
147456000,
|
||||
};
|
||||
|
||||
static unsigned int arizona_sysclk_44k1_rates[] = {
|
||||
@ -241,6 +280,9 @@ static unsigned int arizona_sysclk_44k1_rates[] = {
|
||||
11289600,
|
||||
24576000,
|
||||
45158400,
|
||||
67737600,
|
||||
90316800,
|
||||
135475200,
|
||||
};
|
||||
|
||||
static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
|
||||
|
@ -61,7 +61,7 @@ struct arizona_priv {
|
||||
struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
|
||||
};
|
||||
|
||||
#define ARIZONA_NUM_MIXER_INPUTS 57
|
||||
#define ARIZONA_NUM_MIXER_INPUTS 75
|
||||
|
||||
extern const unsigned int arizona_mixer_tlv[];
|
||||
extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
|
||||
|
@ -459,7 +459,7 @@ static struct snd_soc_dai_driver cs4270_dai = {
|
||||
.name = "cs4270-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||
.rate_min = 4000,
|
||||
@ -468,7 +468,7 @@ static struct snd_soc_dai_driver cs4270_dai = {
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||
.rate_min = 4000,
|
||||
|
@ -22,12 +22,14 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/cs4271.h>
|
||||
|
||||
#define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
@ -458,6 +460,14 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec)
|
||||
#define cs4271_soc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id cs4271_dt_ids[] = {
|
||||
{ .compatible = "cirrus,cs4271", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs4271_dt_ids);
|
||||
#endif
|
||||
|
||||
static int cs4271_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
|
||||
@ -465,6 +475,12 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
||||
int ret;
|
||||
int gpio_nreset = -EINVAL;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (of_match_device(cs4271_dt_ids, codec->dev))
|
||||
gpio_nreset = of_get_named_gpio(codec->dev->of_node,
|
||||
"reset-gpio", 0);
|
||||
#endif
|
||||
|
||||
if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
|
||||
gpio_nreset = cs4271plat->gpio_nreset;
|
||||
|
||||
@ -569,6 +585,7 @@ static struct spi_driver cs4271_spi_driver = {
|
||||
.driver = {
|
||||
.name = "cs4271",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(cs4271_dt_ids),
|
||||
},
|
||||
.probe = cs4271_spi_probe,
|
||||
.remove = __devexit_p(cs4271_spi_remove),
|
||||
@ -608,6 +625,7 @@ static struct i2c_driver cs4271_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cs4271",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(cs4271_dt_ids),
|
||||
},
|
||||
.id_table = cs4271_i2c_id,
|
||||
.probe = cs4271_i2c_probe,
|
||||
|
1510
sound/soc/codecs/da9055.c
Normal file
1510
sound/soc/codecs/da9055.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -168,7 +168,8 @@ static void wm0010_halt(struct snd_soc_codec *codec)
|
||||
case WM0010_STAGE2:
|
||||
case WM0010_FIRMWARE:
|
||||
/* Remember to put chip back into reset */
|
||||
gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value);
|
||||
gpio_set_value_cansleep(wm0010->gpio_reset,
|
||||
wm0010->gpio_reset_value);
|
||||
/* Disable the regulators */
|
||||
regulator_disable(wm0010->dbvdd);
|
||||
regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies),
|
||||
@ -387,7 +388,7 @@ static int wm0010_boot(struct snd_soc_codec *codec)
|
||||
}
|
||||
|
||||
/* Release reset */
|
||||
gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value);
|
||||
gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value);
|
||||
spin_lock_irqsave(&wm0010->irq_lock, flags);
|
||||
wm0010->state = WM0010_OUT_OF_RESET;
|
||||
spin_unlock_irqrestore(&wm0010->irq_lock, flags);
|
||||
@ -809,7 +810,6 @@ static int wm0010_probe(struct snd_soc_codec *codec)
|
||||
|
||||
static int __devinit wm0010_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long gpio_flags;
|
||||
int ret;
|
||||
int trigger;
|
||||
@ -876,6 +876,8 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wm0010->state = WM0010_POWER_OFF;
|
||||
|
||||
irq = spi->irq;
|
||||
if (wm0010->pdata.irq_flags)
|
||||
trigger = wm0010->pdata.irq_flags;
|
||||
@ -897,10 +899,6 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi)
|
||||
else
|
||||
wm0010->board_max_spi_speed = 0;
|
||||
|
||||
spin_lock_irqsave(&wm0010->irq_lock, flags);
|
||||
wm0010->state = WM0010_POWER_OFF;
|
||||
spin_unlock_irqrestore(&wm0010->irq_lock, flags);
|
||||
|
||||
ret = snd_soc_register_codec(&spi->dev,
|
||||
&soc_codec_dev_wm0010, wm0010_dai,
|
||||
ARRAY_SIZE(wm0010_dai));
|
||||
@ -916,10 +914,8 @@ static int __devexit wm0010_spi_remove(struct spi_device *spi)
|
||||
|
||||
snd_soc_unregister_codec(&spi->dev);
|
||||
|
||||
if (wm0010->gpio_reset) {
|
||||
/* Remember to put chip back into reset */
|
||||
gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value);
|
||||
}
|
||||
gpio_set_value_cansleep(wm0010->gpio_reset,
|
||||
wm0010->gpio_reset_value);
|
||||
|
||||
if (wm0010->irq)
|
||||
free_irq(wm0010->irq, wm0010);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
@ -43,6 +44,14 @@
|
||||
|
||||
#include "wm2000.h"
|
||||
|
||||
#define WM2000_NUM_SUPPLIES 3
|
||||
|
||||
static const char *wm2000_supplies[WM2000_NUM_SUPPLIES] = {
|
||||
"SPKVDD",
|
||||
"DBVDD",
|
||||
"DCVDD",
|
||||
};
|
||||
|
||||
enum wm2000_anc_mode {
|
||||
ANC_ACTIVE = 0,
|
||||
ANC_BYPASS = 1,
|
||||
@ -54,6 +63,8 @@ struct wm2000_priv {
|
||||
struct i2c_client *i2c;
|
||||
struct regmap *regmap;
|
||||
|
||||
struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES];
|
||||
|
||||
enum wm2000_anc_mode anc_mode;
|
||||
|
||||
unsigned int anc_active:1;
|
||||
@ -126,6 +137,12 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
|
||||
|
||||
dev_dbg(&i2c->dev, "Beginning power up\n");
|
||||
|
||||
ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!wm2000->mclk_div) {
|
||||
dev_dbg(&i2c->dev, "Disabling MCLK divider\n");
|
||||
wm2000_write(i2c, WM2000_REG_SYS_CTL2,
|
||||
@ -143,12 +160,14 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
|
||||
if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
|
||||
WM2000_ANC_ENG_IDLE)) {
|
||||
dev_err(&i2c->dev, "ANC engine failed to reset\n");
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
|
||||
WM2000_STATUS_BOOT_COMPLETE)) {
|
||||
dev_err(&i2c->dev, "ANC engine failed to initialise\n");
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -163,11 +182,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
|
||||
wm2000->anc_download_size);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret);
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
return ret;
|
||||
}
|
||||
if (ret != wm2000->anc_download_size) {
|
||||
dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n",
|
||||
ret, wm2000->anc_download_size);
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -201,6 +222,7 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
|
||||
if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
|
||||
WM2000_STATUS_MOUSE_ACTIVE)) {
|
||||
dev_err(&i2c->dev, "Timed out waiting for device\n");
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -238,6 +260,8 @@ static int wm2000_power_down(struct i2c_client *i2c, int analogue)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
|
||||
dev_dbg(&i2c->dev, "powered off\n");
|
||||
wm2000->anc_mode = ANC_OFF;
|
||||
|
||||
@ -747,7 +771,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
struct wm2000_platform_data *pdata;
|
||||
const char *filename;
|
||||
const struct firmware *fw = NULL;
|
||||
int ret;
|
||||
int ret, i;
|
||||
int reg;
|
||||
u16 id;
|
||||
|
||||
@ -760,7 +784,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
dev_set_drvdata(&i2c->dev, wm2000);
|
||||
|
||||
wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap);
|
||||
wm2000->regmap = devm_regmap_init_i2c(i2c, &wm2000_regmap);
|
||||
if (IS_ERR(wm2000->regmap)) {
|
||||
ret = PTR_ERR(wm2000->regmap);
|
||||
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
|
||||
@ -768,6 +792,22 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < WM2000_NUM_SUPPLIES; i++)
|
||||
wm2000->supplies[i].supply = wm2000_supplies[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(&i2c->dev, WM2000_NUM_SUPPLIES,
|
||||
wm2000->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Verify that this is a WM2000 */
|
||||
reg = wm2000_read(i2c, WM2000_REG_ID1);
|
||||
id = reg << 8;
|
||||
@ -777,7 +817,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
if (id != 0x2000) {
|
||||
dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
|
||||
ret = -ENODEV;
|
||||
goto out_regmap_exit;
|
||||
goto err_supplies;
|
||||
}
|
||||
|
||||
reg = wm2000_read(i2c, WM2000_REG_REVISON);
|
||||
@ -796,7 +836,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
ret = request_firmware(&fw, filename, &i2c->dev);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
|
||||
goto out_regmap_exit;
|
||||
goto err_supplies;
|
||||
}
|
||||
|
||||
/* Pre-cook the concatenation of the register address onto the image */
|
||||
@ -807,7 +847,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
if (wm2000->anc_download == NULL) {
|
||||
dev_err(&i2c->dev, "Out of memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_regmap_exit;
|
||||
goto err_supplies;
|
||||
}
|
||||
|
||||
wm2000->anc_download[0] = 0x80;
|
||||
@ -822,11 +862,10 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
|
||||
wm2000_reset(wm2000);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
out_regmap_exit:
|
||||
regmap_exit(wm2000->regmap);
|
||||
err_supplies:
|
||||
regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
@ -834,10 +873,7 @@ out:
|
||||
|
||||
static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
|
||||
|
||||
snd_soc_unregister_codec(&i2c->dev);
|
||||
regmap_exit(wm2000->regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK,
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
|
||||
|
||||
|
@ -153,6 +153,15 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
|
||||
SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
|
||||
SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
|
||||
|
||||
ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP3R", ARIZONA_DSP3RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP4L", ARIZONA_DSP4LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("DSP5R", ARIZONA_DSP4RMIX_INPUT_1_SOURCE),
|
||||
|
||||
ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
|
||||
|
||||
@ -163,7 +172,8 @@ ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("HPOUT3L", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("HPOUT3R", ARIZONA_OUT3RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
|
||||
ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
|
||||
@ -175,7 +185,7 @@ SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
|
||||
ARIZONA_OUT1_OSR_SHIFT, 1, 0),
|
||||
SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
|
||||
ARIZONA_OUT2_OSR_SHIFT, 1, 0),
|
||||
SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
|
||||
SOC_SINGLE("OUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
|
||||
ARIZONA_OUT3_OSR_SHIFT, 1, 0),
|
||||
SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
|
||||
ARIZONA_OUT4_OSR_SHIFT, 1, 0),
|
||||
@ -188,8 +198,8 @@ SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
|
||||
SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
|
||||
SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
|
||||
ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
|
||||
SOC_DOUBLE_R("OUT3 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
|
||||
SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
|
||||
SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
|
||||
@ -203,8 +213,9 @@ SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
|
||||
SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
|
||||
0xbf, 0, digital_tlv),
|
||||
SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
|
||||
ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("OUT3 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_VOL_SHIFT,
|
||||
0xbf, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT,
|
||||
0xbf, 0, digital_tlv),
|
||||
@ -223,8 +234,9 @@ SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
|
||||
ARIZONA_OUTPUT_PATH_CONFIG_2R,
|
||||
ARIZONA_OUT2L_PGA_VOL_SHIFT,
|
||||
0x34, 0x40, 0, ana_tlv),
|
||||
SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
|
||||
ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
|
||||
SOC_DOUBLE_R_RANGE_TLV("OUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
|
||||
ARIZONA_OUTPUT_PATH_CONFIG_3R,
|
||||
ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
|
||||
|
||||
SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
|
||||
ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
|
||||
@ -272,7 +284,8 @@ ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(OUT3L, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(OUT3R, ARIZONA_OUT3RMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE);
|
||||
@ -300,6 +313,26 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
|
||||
ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
|
||||
|
||||
static const char *wm5110_aec_loopback_texts[] = {
|
||||
"HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
|
||||
"SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R",
|
||||
};
|
||||
|
||||
static const unsigned int wm5110_aec_loopback_values[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
};
|
||||
|
||||
static const struct soc_enum wm5110_aec_loopback =
|
||||
SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
|
||||
ARIZONA_AEC_LOOPBACK_SRC_SHIFT,
|
||||
ARIZONA_AEC_LOOPBACK_SRC_MASK,
|
||||
ARRAY_SIZE(wm5110_aec_loopback_texts),
|
||||
wm5110_aec_loopback_texts,
|
||||
wm5110_aec_loopback_values);
|
||||
|
||||
static const struct snd_kcontrol_new wm5110_aec_loopback_mux =
|
||||
SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5110_aec_loopback);
|
||||
|
||||
static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
|
||||
0, NULL, 0),
|
||||
@ -313,7 +346,7 @@ SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK,
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0),
|
||||
SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0),
|
||||
|
||||
@ -409,6 +442,9 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
|
||||
SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
|
||||
NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
|
||||
ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5110_aec_loopback_mux),
|
||||
|
||||
SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
|
||||
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
|
||||
@ -478,6 +514,9 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
|
||||
SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
|
||||
ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
|
||||
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1,
|
||||
ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
|
||||
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
|
||||
ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
|
||||
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
|
||||
@ -522,7 +561,8 @@ ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
|
||||
ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
|
||||
ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"),
|
||||
ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"),
|
||||
ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"),
|
||||
ARIZONA_MIXER_WIDGETS(OUT3L, "HPOUT3L"),
|
||||
ARIZONA_MIXER_WIDGETS(OUT3R, "HPOUT3R"),
|
||||
ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
|
||||
ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
|
||||
ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
|
||||
@ -554,8 +594,8 @@ SND_SOC_DAPM_OUTPUT("HPOUT1L"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUT1R"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUT2L"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUT2R"),
|
||||
SND_SOC_DAPM_OUTPUT("EPOUTN"),
|
||||
SND_SOC_DAPM_OUTPUT("EPOUTP"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUT3L"),
|
||||
SND_SOC_DAPM_OUTPUT("HPOUT3R"),
|
||||
SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
|
||||
SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
|
||||
SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
|
||||
@ -570,6 +610,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
|
||||
{ name, "Noise Generator", "Noise Generator" }, \
|
||||
{ name, "Tone Generator 1", "Tone Generator 1" }, \
|
||||
{ name, "Tone Generator 2", "Tone Generator 2" }, \
|
||||
{ name, "AEC", "AEC Loopback" }, \
|
||||
{ name, "IN1L", "IN1L PGA" }, \
|
||||
{ name, "IN1R", "IN1R PGA" }, \
|
||||
{ name, "IN2L", "IN2L PGA" }, \
|
||||
@ -620,6 +661,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
|
||||
{ "OUT2L", NULL, "CPVDD" },
|
||||
{ "OUT2R", NULL, "CPVDD" },
|
||||
{ "OUT3L", NULL, "CPVDD" },
|
||||
{ "OUT3R", NULL, "CPVDD" },
|
||||
|
||||
{ "OUT4L", NULL, "SPKVDDL" },
|
||||
{ "OUT4R", NULL, "SPKVDDR" },
|
||||
@ -701,7 +743,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
|
||||
ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
|
||||
ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
|
||||
ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"),
|
||||
ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"),
|
||||
ARIZONA_MIXER_ROUTES("OUT3L", "HPOUT3L"),
|
||||
ARIZONA_MIXER_ROUTES("OUT3R", "HPOUT3R"),
|
||||
|
||||
ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"),
|
||||
ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"),
|
||||
@ -754,8 +797,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
|
||||
{ "HPOUT2L", NULL, "OUT2L" },
|
||||
{ "HPOUT2R", NULL, "OUT2R" },
|
||||
|
||||
{ "EPOUTN", NULL, "OUT3L" },
|
||||
{ "EPOUTP", NULL, "OUT3L" },
|
||||
{ "HPOUT3L", NULL, "OUT3L" },
|
||||
{ "HPOUT3R", NULL, "OUT3L" },
|
||||
|
||||
{ "SPKOUTLN", NULL, "OUT4L" },
|
||||
{ "SPKOUTLP", NULL, "OUT4L" },
|
||||
@ -873,6 +916,8 @@ static unsigned int wm5110_digital_vu[] = {
|
||||
ARIZONA_ADC_DIGITAL_VOLUME_2R,
|
||||
ARIZONA_ADC_DIGITAL_VOLUME_3L,
|
||||
ARIZONA_ADC_DIGITAL_VOLUME_3R,
|
||||
ARIZONA_ADC_DIGITAL_VOLUME_4L,
|
||||
ARIZONA_ADC_DIGITAL_VOLUME_4R,
|
||||
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_1L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_1R,
|
||||
@ -884,6 +929,8 @@ static unsigned int wm5110_digital_vu[] = {
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_4R,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_5L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_5R,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_6L,
|
||||
ARIZONA_DAC_DIGITAL_VOLUME_6R,
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
|
||||
|
@ -681,6 +681,11 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec)
|
||||
|
||||
snd_soc_update_bits(codec, WM8993_CLASS_W_0,
|
||||
WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable);
|
||||
|
||||
snd_soc_write(codec, WM8993_LEFT_OUTPUT_VOLUME,
|
||||
snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME));
|
||||
snd_soc_write(codec, WM8993_RIGHT_OUTPUT_VOLUME,
|
||||
snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
|
||||
|
||||
|
@ -93,9 +93,7 @@ static struct snd_soc_card eukrea_tlv320 = {
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
static struct platform_device *eukrea_tlv320_snd_device;
|
||||
|
||||
static int __init eukrea_tlv320_init(void)
|
||||
static int __devinit eukrea_tlv320_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
int int_port = 0, ext_port;
|
||||
@ -136,29 +134,32 @@ static int __init eukrea_tlv320_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
|
||||
if (!eukrea_tlv320_snd_device)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320);
|
||||
ret = platform_device_add(eukrea_tlv320_snd_device);
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_ERR "ASoC: Platform device allocation failed\n");
|
||||
platform_device_put(eukrea_tlv320_snd_device);
|
||||
}
|
||||
eukrea_tlv320.dev = &pdev->dev;
|
||||
ret = snd_soc_register_card(&eukrea_tlv320);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit eukrea_tlv320_exit(void)
|
||||
static int __devexit eukrea_tlv320_remove(struct platform_device *pdev)
|
||||
{
|
||||
platform_device_unregister(eukrea_tlv320_snd_device);
|
||||
snd_soc_unregister_card(&eukrea_tlv320);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(eukrea_tlv320_init);
|
||||
module_exit(eukrea_tlv320_exit);
|
||||
static struct platform_driver eukrea_tlv320_driver = {
|
||||
.driver = {
|
||||
.name = "eukrea_tlv320",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = eukrea_tlv320_probe,
|
||||
.remove = __devexit_p(eukrea_tlv320_remove),};
|
||||
|
||||
module_platform_driver(eukrea_tlv320_driver);
|
||||
|
||||
MODULE_AUTHOR("Eric Bénard <eric@eukrea.com>");
|
||||
MODULE_DESCRIPTION("CPUIMX ALSA SoC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:eukrea_tlv320");
|
||||
|
@ -1017,10 +1017,29 @@ EXPORT_SYMBOL_GPL(dapm_reg_event);
|
||||
int dapm_regulator_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
int ret;
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
|
||||
ret = regulator_allow_bypass(w->regulator, true);
|
||||
if (ret != 0)
|
||||
dev_warn(w->dapm->dev,
|
||||
"Failed to bypass %s: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
|
||||
return regulator_enable(w->regulator);
|
||||
else
|
||||
} else {
|
||||
if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
|
||||
ret = regulator_allow_bypass(w->regulator, false);
|
||||
if (ret != 0)
|
||||
dev_warn(w->dapm->dev,
|
||||
"Failed to unbypass %s: %d\n",
|
||||
w->name, ret);
|
||||
}
|
||||
|
||||
return regulator_disable_deferred(w->regulator, w->shift);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dapm_regulator_event);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/initval.h>
|
||||
@ -56,16 +57,47 @@ static struct snd_soc_card mop500_card = {
|
||||
.num_links = ARRAY_SIZE(mop500_dai_links),
|
||||
};
|
||||
|
||||
static int __devinit mop500_of_probe(struct platform_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct device_node *codec_np, *msp_np[2];
|
||||
int i;
|
||||
|
||||
msp_np[0] = of_parse_phandle(np, "stericsson,cpu-dai", 0);
|
||||
msp_np[1] = of_parse_phandle(np, "stericsson,cpu-dai", 1);
|
||||
codec_np = of_parse_phandle(np, "stericsson,audio-codec", 0);
|
||||
|
||||
if (!(msp_np[0] && msp_np[1] && codec_np)) {
|
||||
dev_err(&pdev->dev, "Phandle missing or invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
mop500_dai_links[i].cpu_of_node = msp_np[i];
|
||||
mop500_dai_links[i].cpu_dai_name = NULL;
|
||||
mop500_dai_links[i].codec_of_node = codec_np;
|
||||
mop500_dai_links[i].codec_name = NULL;
|
||||
}
|
||||
|
||||
snd_soc_of_parse_card_name(&mop500_card, "stericsson,card-name");
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int __devinit mop500_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret;
|
||||
|
||||
pr_debug("%s: Enter.\n", __func__);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: Enter.\n", __func__);
|
||||
|
||||
mop500_card.dev = &pdev->dev;
|
||||
|
||||
if (np) {
|
||||
ret = mop500_of_probe(pdev, np);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n",
|
||||
__func__, mop500_card.name);
|
||||
platform_set_drvdata(pdev, &mop500_card);
|
||||
@ -83,8 +115,7 @@ static int __devinit mop500_probe(struct platform_device *pdev)
|
||||
ret = snd_soc_register_card(&mop500_card);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev,
|
||||
"Error: snd_soc_register_card failed (%d)!\n",
|
||||
ret);
|
||||
"Error: snd_soc_register_card failed (%d)!\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -97,14 +128,20 @@ static int __devexit mop500_remove(struct platform_device *pdev)
|
||||
|
||||
snd_soc_unregister_card(mop500_card);
|
||||
mop500_ab8500_remove(mop500_card);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id snd_soc_mop500_match[] = {
|
||||
{ .compatible = "stericsson,snd-soc-mop500", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver snd_soc_mop500_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "snd-soc-mop500",
|
||||
.of_match_table = snd_soc_mop500_match,
|
||||
},
|
||||
.probe = mop500_probe,
|
||||
.remove = __devexit_p(mop500_remove),
|
||||
|
@ -833,10 +833,16 @@ static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ux500_msp_i2s_match[] = {
|
||||
{ .compatible = "stericsson,ux500-msp-i2s", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver msp_i2s_driver = {
|
||||
.driver = {
|
||||
.name = "ux500-msp-i2s",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = ux500_msp_i2s_match,
|
||||
},
|
||||
.probe = ux500_msp_drv_probe,
|
||||
.remove = ux500_msp_drv_remove,
|
||||
|
@ -15,8 +15,10 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/msp.h>
|
||||
@ -25,6 +27,9 @@
|
||||
|
||||
#include "ux500_msp_i2s.h"
|
||||
|
||||
/* MSP1/3 Tx/Rx usage protection */
|
||||
static DEFINE_SPINLOCK(msp_rxtx_lock);
|
||||
|
||||
/* Protocol desciptors */
|
||||
static const struct msp_protdesc prot_descs[] = {
|
||||
{ /* I2S */
|
||||
@ -352,17 +357,23 @@ static int configure_multichannel(struct ux500_msp *msp,
|
||||
|
||||
static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
|
||||
{
|
||||
int status = 0;
|
||||
int status = 0, retval = 0;
|
||||
u32 reg_val_DMACR, reg_val_GCR;
|
||||
unsigned long flags;
|
||||
|
||||
/* Check msp state whether in RUN or CONFIGURED Mode */
|
||||
if ((msp->msp_state == MSP_STATE_IDLE) && (msp->plat_init)) {
|
||||
status = msp->plat_init();
|
||||
if (status) {
|
||||
dev_err(msp->dev, "%s: ERROR: Failed to init MSP (%d)!\n",
|
||||
__func__, status);
|
||||
return status;
|
||||
if (msp->msp_state == MSP_STATE_IDLE) {
|
||||
spin_lock_irqsave(&msp_rxtx_lock, flags);
|
||||
if (msp->pinctrl_rxtx_ref == 0 &&
|
||||
!(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) {
|
||||
retval = pinctrl_select_state(msp->pinctrl_p,
|
||||
msp->pinctrl_def);
|
||||
if (retval)
|
||||
pr_err("could not set MSP defstate\n");
|
||||
}
|
||||
if (!retval)
|
||||
msp->pinctrl_rxtx_ref++;
|
||||
spin_unlock_irqrestore(&msp_rxtx_lock, flags);
|
||||
}
|
||||
|
||||
/* Configure msp with protocol dependent settings */
|
||||
@ -620,7 +631,8 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)
|
||||
|
||||
int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
|
||||
{
|
||||
int status = 0;
|
||||
int status = 0, retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);
|
||||
|
||||
@ -631,12 +643,19 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
|
||||
writel((readl(msp->registers + MSP_GCR) &
|
||||
(~(FRAME_GEN_ENABLE | SRG_ENABLE))),
|
||||
msp->registers + MSP_GCR);
|
||||
if (msp->plat_exit)
|
||||
status = msp->plat_exit();
|
||||
if (status)
|
||||
dev_warn(msp->dev,
|
||||
"%s: WARN: ux500_msp_i2s_exit failed (%d)!\n",
|
||||
__func__, status);
|
||||
|
||||
spin_lock_irqsave(&msp_rxtx_lock, flags);
|
||||
WARN_ON(!msp->pinctrl_rxtx_ref);
|
||||
msp->pinctrl_rxtx_ref--;
|
||||
if (msp->pinctrl_rxtx_ref == 0 &&
|
||||
!(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) {
|
||||
retval = pinctrl_select_state(msp->pinctrl_p,
|
||||
msp->pinctrl_sleep);
|
||||
if (retval)
|
||||
pr_err("could not set MSP sleepstate\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&msp_rxtx_lock, flags);
|
||||
|
||||
writel(0, msp->registers + MSP_GCR);
|
||||
writel(0, msp->registers + MSP_TCF);
|
||||
writel(0, msp->registers + MSP_RCF);
|
||||
@ -665,20 +684,33 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
|
||||
{
|
||||
struct resource *res = NULL;
|
||||
struct i2s_controller *i2s_cont;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct ux500_msp *msp;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
|
||||
pdev->name, platform_data->id);
|
||||
|
||||
*msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL);
|
||||
msp = *msp_p;
|
||||
if (!msp)
|
||||
return -ENOMEM;
|
||||
|
||||
if (np) {
|
||||
if (!platform_data) {
|
||||
platform_data = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct msp_i2s_platform_data), GFP_KERNEL);
|
||||
if (!platform_data)
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
} else
|
||||
if (!platform_data)
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret)
|
||||
goto err_res;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
|
||||
pdev->name, platform_data->id);
|
||||
|
||||
msp->id = platform_data->id;
|
||||
msp->dev = &pdev->dev;
|
||||
msp->plat_init = platform_data->msp_i2s_init;
|
||||
msp->plat_exit = platform_data->msp_i2s_exit;
|
||||
msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx;
|
||||
msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx;
|
||||
|
||||
@ -715,6 +747,25 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
|
||||
dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);
|
||||
msp->i2s_cont = i2s_cont;
|
||||
|
||||
msp->pinctrl_p = pinctrl_get(msp->dev);
|
||||
if (IS_ERR(msp->pinctrl_p))
|
||||
dev_err(&pdev->dev, "could not get MSP pinctrl\n");
|
||||
else {
|
||||
msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p,
|
||||
PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(msp->pinctrl_def)) {
|
||||
dev_err(&pdev->dev,
|
||||
"could not get MSP defstate (%li)\n",
|
||||
PTR_ERR(msp->pinctrl_def));
|
||||
}
|
||||
msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(msp->pinctrl_sleep))
|
||||
dev_err(&pdev->dev,
|
||||
"could not get MSP idlestate (%li)\n",
|
||||
PTR_ERR(msp->pinctrl_def));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -524,14 +524,18 @@ struct ux500_msp {
|
||||
struct dma_chan *rx_pipeid;
|
||||
enum msp_state msp_state;
|
||||
int (*transfer) (struct ux500_msp *msp, struct i2s_message *message);
|
||||
int (*plat_init) (void);
|
||||
int (*plat_exit) (void);
|
||||
struct timer_list notify_timer;
|
||||
int def_elem_len;
|
||||
unsigned int dir_busy;
|
||||
int loopback_enable;
|
||||
u32 backup_regs[MAX_MSP_BACKUP_REGS];
|
||||
unsigned int f_bitclk;
|
||||
/* Pin modes */
|
||||
struct pinctrl *pinctrl_p;
|
||||
struct pinctrl_state *pinctrl_def;
|
||||
struct pinctrl_state *pinctrl_sleep;
|
||||
/* Reference Count */
|
||||
int pinctrl_rxtx_ref;
|
||||
};
|
||||
|
||||
struct ux500_msp_dma_params {
|
||||
|
Loading…
Reference in New Issue
Block a user