diff options
40 files changed, 2307 insertions, 174 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator index e091fa873792..bc578bc60628 100644 --- a/Documentation/ABI/testing/sysfs-class-regulator +++ b/Documentation/ABI/testing/sysfs-class-regulator | |||
| @@ -349,3 +349,24 @@ Description: | |||
| 349 | 349 | ||
| 350 | This will be one of the same strings reported by | 350 | This will be one of the same strings reported by |
| 351 | the "state" attribute. | 351 | the "state" attribute. |
| 352 | |||
| 353 | What: /sys/class/regulator/.../bypass | ||
| 354 | Date: September 2012 | ||
| 355 | KernelVersion: 3.7 | ||
| 356 | Contact: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
| 357 | Description: | ||
| 358 | Some regulator directories will contain a field called | ||
| 359 | bypass. This indicates if the device is in bypass mode. | ||
| 360 | |||
| 361 | This will be one of the following strings: | ||
| 362 | |||
| 363 | 'enabled' | ||
| 364 | 'disabled' | ||
| 365 | 'unknown' | ||
| 366 | |||
| 367 | 'enabled' means the regulator is in bypass mode. | ||
| 368 | |||
| 369 | 'disabled' means that the regulator is regulating. | ||
| 370 | |||
| 371 | 'unknown' means software cannot determine the state, or | ||
| 372 | the reported state is invalid. | ||
diff --git a/Documentation/devicetree/bindings/sound/cs4271.txt b/Documentation/devicetree/bindings/sound/cs4271.txt new file mode 100644 index 000000000000..c81b5fd5a5bc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs4271.txt | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | Cirrus Logic CS4271 DT bindings | ||
| 2 | |||
| 3 | This driver supports both the I2C and the SPI bus. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible: "cirrus,cs4271" | ||
| 8 | |||
| 9 | For required properties on SPI, please consult | ||
| 10 | Documentation/devicetree/bindings/spi/spi-bus.txt | ||
| 11 | |||
| 12 | Required properties on I2C: | ||
| 13 | |||
| 14 | - reg: the i2c address | ||
| 15 | |||
| 16 | |||
| 17 | Optional properties: | ||
| 18 | |||
| 19 | - reset-gpio: a GPIO spec to define which pin is connected to the chip's | ||
| 20 | !RESET pin | ||
| 21 | |||
| 22 | Examples: | ||
| 23 | |||
| 24 | codec_i2c: cs4271@10 { | ||
| 25 | compatible = "cirrus,cs4271"; | ||
| 26 | reg = <0x10>; | ||
| 27 | reset-gpio = <&gpio 23 0>; | ||
| 28 | }; | ||
| 29 | |||
| 30 | codec_spi: cs4271@0 { | ||
| 31 | compatible = "cirrus,cs4271"; | ||
| 32 | reg = <0x0>; | ||
| 33 | reset-gpio = <&gpio 23 0>; | ||
| 34 | spi-max-frequency = <6000000>; | ||
| 35 | }; | ||
| 36 | |||
diff --git a/Documentation/devicetree/bindings/sound/ux500-mop500.txt b/Documentation/devicetree/bindings/sound/ux500-mop500.txt new file mode 100644 index 000000000000..48e071c96b46 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ux500-mop500.txt | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | * MOP500 Audio Machine Driver | ||
| 2 | |||
| 3 | This node is responsible for linking together all ux500 Audio Driver components. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | - compatible : "stericsson,snd-soc-mop500" | ||
| 7 | |||
| 8 | Non-standard properties: | ||
| 9 | - stericsson,cpu-dai : Phandle to the CPU-side DAI | ||
| 10 | - stericsson,audio-codec : Phandle to the Audio CODEC | ||
| 11 | - stericsson,card-name : Over-ride default card name | ||
| 12 | |||
| 13 | Example: | ||
| 14 | |||
| 15 | sound { | ||
| 16 | compatible = "stericsson,snd-soc-mop500"; | ||
| 17 | |||
| 18 | stericsson,cpu-dai = <&msp1 &msp3>; | ||
| 19 | stericsson,audio-codec = <&codec>; | ||
| 20 | }; | ||
| 21 | |||
| 22 | msp1: msp@80124000 { | ||
| 23 | compatible = "stericsson,ux500-msp-i2s"; | ||
| 24 | reg = <0x80124000 0x1000>; | ||
| 25 | interrupts = <0 62 0x4>; | ||
| 26 | v-ape-supply = <&db8500_vape_reg>; | ||
| 27 | }; | ||
| 28 | |||
| 29 | msp3: msp@80125000 { | ||
| 30 | compatible = "stericsson,ux500-msp-i2s"; | ||
| 31 | reg = <0x80125000 0x1000>; | ||
| 32 | interrupts = <0 62 0x4>; | ||
| 33 | v-ape-supply = <&db8500_vape_reg>; | ||
| 34 | }; | ||
| 35 | |||
| 36 | codec: ab8500-codec { | ||
| 37 | compatible = "stericsson,ab8500-codec"; | ||
| 38 | stericsson,earpeice-cmv = <950>; /* Units in mV. */ | ||
| 39 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/ux500-msp.txt b/Documentation/devicetree/bindings/sound/ux500-msp.txt new file mode 100644 index 000000000000..99acd9c774e1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ux500-msp.txt | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | * ux500 MSP (CPU-side Digital Audio Interface) | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible :"stericsson,ux500-msp-i2s" | ||
| 5 | - reg : Physical base address and length of the device's registers. | ||
| 6 | |||
| 7 | Optional properties: | ||
| 8 | - interrupts : The interrupt output from the device. | ||
| 9 | - interrupt-parent : The parent interrupt controller. | ||
| 10 | - <name>-supply : Phandle to the regulator <name> supply | ||
| 11 | |||
| 12 | Example: | ||
| 13 | |||
| 14 | sound { | ||
| 15 | compatible = "stericsson,snd-soc-mop500"; | ||
| 16 | |||
| 17 | stericsson,platform-pcm-dma = <&pcm>; | ||
| 18 | stericsson,cpu-dai = <&msp1 &msp3>; | ||
| 19 | stericsson,audio-codec = <&codec>; | ||
| 20 | }; | ||
| 21 | |||
| 22 | pcm: ux500-pcm { | ||
| 23 | compatible = "stericsson,ux500-pcm"; | ||
| 24 | }; | ||
| 25 | |||
| 26 | msp1: msp@80124000 { | ||
| 27 | compatible = "stericsson,ux500-msp-i2s"; | ||
| 28 | reg = <0x80124000 0x1000>; | ||
| 29 | interrupts = <0 62 0x4>; | ||
| 30 | v-ape-supply = <&db8500_vape_reg>; | ||
| 31 | }; | ||
| 32 | |||
| 33 | msp3: msp@80125000 { | ||
| 34 | compatible = "stericsson,ux500-msp-i2s"; | ||
| 35 | reg = <0x80125000 0x1000>; | ||
| 36 | interrupts = <0 62 0x4>; | ||
| 37 | v-ape-supply = <&db8500_vape_reg>; | ||
| 38 | }; | ||
| 39 | |||
| 40 | codec: ab8500-codec { | ||
| 41 | compatible = "stericsson,ab8500-codec"; | ||
| 42 | stericsson,earpeice-cmv = <950>; /* Units in mV. */ | ||
| 43 | }; | ||
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index fd3177f9e79a..98aef571b9f8 100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | |||
| @@ -348,4 +348,5 @@ void __init eukrea_mbimx27_baseboard_init(void) | |||
| 348 | imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data); | 348 | imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data); |
| 349 | 349 | ||
| 350 | gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info); | 350 | gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info); |
| 351 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 351 | } | 352 | } |
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c index dfd2da87c2df..0b84666792f0 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | |||
| @@ -306,4 +306,5 @@ void __init eukrea_mbimxsd25_baseboard_init(void) | |||
| 306 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | 306 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); |
| 307 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); | 307 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); |
| 308 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); | 308 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); |
| 309 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 309 | } | 310 | } |
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c index 6e9dd12a6961..c6532a007d46 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | |||
| @@ -315,4 +315,5 @@ void __init eukrea_mbimxsd35_baseboard_init(void) | |||
| 315 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | 315 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); |
| 316 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); | 316 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); |
| 317 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); | 317 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); |
| 318 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 318 | } | 319 | } |
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c index 96a24b73dc23..8b0de30d7a3f 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c | |||
| @@ -228,4 +228,5 @@ void __init eukrea_mbimxsd51_baseboard_init(void) | |||
| 228 | 228 | ||
| 229 | gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info); | 229 | gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info); |
| 230 | imx_add_gpio_keys(&eukrea_mbimxsd51_button_data); | 230 | imx_add_gpio_keys(&eukrea_mbimxsd51_button_data); |
| 231 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 231 | } | 232 | } |
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c index df15646036aa..ace6c051bc1a 100644 --- a/arch/arm/mach-ux500/board-mop500-msp.c +++ b/arch/arm/mach-ux500/board-mop500-msp.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 9 | #include <linux/gpio.h> | 9 | #include <linux/gpio.h> |
| 10 | #include <linux/pinctrl/consumer.h> | ||
| 11 | 10 | ||
| 12 | #include <plat/gpio-nomadik.h> | 11 | #include <plat/gpio-nomadik.h> |
| 13 | #include <plat/pincfg.h> | 12 | #include <plat/pincfg.h> |
| @@ -23,53 +22,6 @@ | |||
| 23 | #include "devices-db8500.h" | 22 | #include "devices-db8500.h" |
| 24 | #include "pins-db8500.h" | 23 | #include "pins-db8500.h" |
| 25 | 24 | ||
| 26 | /* MSP1/3 Tx/Rx usage protection */ | ||
| 27 | static DEFINE_SPINLOCK(msp_rxtx_lock); | ||
| 28 | |||
| 29 | /* Reference Count */ | ||
| 30 | static int msp_rxtx_ref; | ||
| 31 | |||
| 32 | /* Pin modes */ | ||
| 33 | struct pinctrl *msp1_p; | ||
| 34 | struct pinctrl_state *msp1_def; | ||
| 35 | struct pinctrl_state *msp1_sleep; | ||
| 36 | |||
| 37 | int msp13_i2s_init(void) | ||
| 38 | { | ||
| 39 | int retval = 0; | ||
| 40 | unsigned long flags; | ||
| 41 | |||
| 42 | spin_lock_irqsave(&msp_rxtx_lock, flags); | ||
| 43 | if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_def))) { | ||
| 44 | retval = pinctrl_select_state(msp1_p, msp1_def); | ||
| 45 | if (retval) | ||
| 46 | pr_err("could not set MSP1 defstate\n"); | ||
| 47 | } | ||
| 48 | if (!retval) | ||
| 49 | msp_rxtx_ref++; | ||
| 50 | spin_unlock_irqrestore(&msp_rxtx_lock, flags); | ||
| 51 | |||
| 52 | return retval; | ||
| 53 | } | ||
| 54 | |||
| 55 | int msp13_i2s_exit(void) | ||
| 56 | { | ||
| 57 | int retval = 0; | ||
| 58 | unsigned long flags; | ||
| 59 | |||
| 60 | spin_lock_irqsave(&msp_rxtx_lock, flags); | ||
| 61 | WARN_ON(!msp_rxtx_ref); | ||
| 62 | msp_rxtx_ref--; | ||
| 63 | if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_sleep))) { | ||
| 64 | retval = pinctrl_select_state(msp1_p, msp1_sleep); | ||
| 65 | if (retval) | ||
| 66 | pr_err("could not set MSP1 sleepstate\n"); | ||
| 67 | } | ||
| 68 | spin_unlock_irqrestore(&msp_rxtx_lock, flags); | ||
| 69 | |||
| 70 | return retval; | ||
| 71 | } | ||
| 72 | |||
| 73 | static struct stedma40_chan_cfg msp0_dma_rx = { | 25 | static struct stedma40_chan_cfg msp0_dma_rx = { |
| 74 | .high_priority = true, | 26 | .high_priority = true, |
| 75 | .dir = STEDMA40_PERIPH_TO_MEM, | 27 | .dir = STEDMA40_PERIPH_TO_MEM, |
| @@ -132,8 +84,6 @@ static struct msp_i2s_platform_data msp1_platform_data = { | |||
| 132 | .id = MSP_I2S_1, | 84 | .id = MSP_I2S_1, |
| 133 | .msp_i2s_dma_rx = NULL, | 85 | .msp_i2s_dma_rx = NULL, |
| 134 | .msp_i2s_dma_tx = &msp1_dma_tx, | 86 | .msp_i2s_dma_tx = &msp1_dma_tx, |
| 135 | .msp_i2s_init = msp13_i2s_init, | ||
| 136 | .msp_i2s_exit = msp13_i2s_exit, | ||
| 137 | }; | 87 | }; |
| 138 | 88 | ||
| 139 | static struct stedma40_chan_cfg msp2_dma_rx = { | 89 | static struct stedma40_chan_cfg msp2_dma_rx = { |
| @@ -219,49 +169,22 @@ static struct msp_i2s_platform_data msp3_platform_data = { | |||
| 219 | .id = MSP_I2S_3, | 169 | .id = MSP_I2S_3, |
| 220 | .msp_i2s_dma_rx = &msp1_dma_rx, | 170 | .msp_i2s_dma_rx = &msp1_dma_rx, |
| 221 | .msp_i2s_dma_tx = NULL, | 171 | .msp_i2s_dma_tx = NULL, |
| 222 | .msp_i2s_init = msp13_i2s_init, | ||
| 223 | .msp_i2s_exit = msp13_i2s_exit, | ||
| 224 | }; | 172 | }; |
| 225 | 173 | ||
| 226 | int mop500_msp_init(struct device *parent) | 174 | int mop500_msp_init(struct device *parent) |
| 227 | { | 175 | { |
| 228 | struct platform_device *msp1; | ||
| 229 | |||
| 230 | pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__); | 176 | pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__); |
| 231 | platform_device_register(&snd_soc_mop500); | 177 | platform_device_register(&snd_soc_mop500); |
| 232 | 178 | ||
| 233 | pr_info("Initialize MSP I2S-devices.\n"); | 179 | pr_info("Initialize MSP I2S-devices.\n"); |
| 234 | db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, | 180 | db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, |
| 235 | &msp0_platform_data); | 181 | &msp0_platform_data); |
| 236 | msp1 = db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, | 182 | db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, |
| 237 | &msp1_platform_data); | 183 | &msp1_platform_data); |
| 238 | db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, | 184 | db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, |
| 239 | &msp2_platform_data); | 185 | &msp2_platform_data); |
| 240 | db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, | 186 | db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, |
| 241 | &msp3_platform_data); | 187 | &msp3_platform_data); |
| 242 | 188 | ||
| 243 | /* Get the pinctrl handle for MSP1 */ | ||
| 244 | if (msp1) { | ||
| 245 | msp1_p = pinctrl_get(&msp1->dev); | ||
| 246 | if (IS_ERR(msp1_p)) | ||
| 247 | dev_err(&msp1->dev, "could not get MSP1 pinctrl\n"); | ||
| 248 | else { | ||
| 249 | msp1_def = pinctrl_lookup_state(msp1_p, | ||
| 250 | PINCTRL_STATE_DEFAULT); | ||
| 251 | if (IS_ERR(msp1_def)) { | ||
| 252 | dev_err(&msp1->dev, | ||
| 253 | "could not get MSP1 defstate\n"); | ||
| 254 | } | ||
| 255 | msp1_sleep = pinctrl_lookup_state(msp1_p, | ||
| 256 | PINCTRL_STATE_SLEEP); | ||
| 257 | if (IS_ERR(msp1_sleep)) | ||
| 258 | dev_err(&msp1->dev, | ||
| 259 | "could not get MSP1 idlestate\n"); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__); | ||
| 264 | platform_device_register(&ux500_pcm); | ||
| 265 | |||
| 266 | return 0; | 189 | return 0; |
| 267 | } | 190 | } |
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h index 798be19129ef..3cc7142eee02 100644 --- a/arch/arm/mach-ux500/include/mach/msp.h +++ b/arch/arm/mach-ux500/include/mach/msp.h | |||
| @@ -22,8 +22,6 @@ struct msp_i2s_platform_data { | |||
| 22 | enum msp_i2s_id id; | 22 | enum msp_i2s_id id; |
| 23 | struct stedma40_chan_cfg *msp_i2s_dma_rx; | 23 | struct stedma40_chan_cfg *msp_i2s_dma_rx; |
| 24 | struct stedma40_chan_cfg *msp_i2s_dma_tx; | 24 | struct stedma40_chan_cfg *msp_i2s_dma_tx; |
| 25 | int (*msp_i2s_init) (void); | ||
| 26 | int (*msp_i2s_exit) (void); | ||
| 27 | }; | 25 | }; |
| 28 | 26 | ||
| 29 | #endif | 27 | #endif |
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 427a289f32a5..6c19833ed2d0 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c | |||
| @@ -434,6 +434,11 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) | |||
| 434 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, | 434 | regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, |
| 435 | ARIZONA_JD1_ENA, ARIZONA_JD1_ENA); | 435 | ARIZONA_JD1_ENA, ARIZONA_JD1_ENA); |
| 436 | 436 | ||
| 437 | ret = regulator_allow_bypass(info->micvdd, true); | ||
| 438 | if (ret != 0) | ||
| 439 | dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", | ||
| 440 | ret); | ||
| 441 | |||
| 437 | pm_runtime_put(&pdev->dev); | 442 | pm_runtime_put(&pdev->dev); |
| 438 | 443 | ||
| 439 | return 0; | 444 | return 0; |
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index c8f95c07adb6..80e012f14160 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c | |||
| @@ -39,6 +39,8 @@ static struct regulator_ops arizona_ldo1_ops = { | |||
| 39 | .map_voltage = regulator_map_voltage_linear, | 39 | .map_voltage = regulator_map_voltage_linear, |
| 40 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 40 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 41 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 41 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| 42 | .get_bypass = regulator_get_bypass_regmap, | ||
| 43 | .set_bypass = regulator_set_bypass_regmap, | ||
| 42 | }; | 44 | }; |
| 43 | 45 | ||
| 44 | static const struct regulator_desc arizona_ldo1 = { | 46 | static const struct regulator_desc arizona_ldo1 = { |
| @@ -49,6 +51,8 @@ static const struct regulator_desc arizona_ldo1 = { | |||
| 49 | 51 | ||
| 50 | .vsel_reg = ARIZONA_LDO1_CONTROL_1, | 52 | .vsel_reg = ARIZONA_LDO1_CONTROL_1, |
| 51 | .vsel_mask = ARIZONA_LDO1_VSEL_MASK, | 53 | .vsel_mask = ARIZONA_LDO1_VSEL_MASK, |
| 54 | .bypass_reg = ARIZONA_LDO1_CONTROL_1, | ||
| 55 | .bypass_mask = ARIZONA_LDO1_BYPASS, | ||
| 52 | .min_uV = 900000, | 56 | .min_uV = 900000, |
| 53 | .uV_step = 50000, | 57 | .uV_step = 50000, |
| 54 | .n_voltages = 7, | 58 | .n_voltages = 7, |
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 450a069aa9b6..d9b1f82cc5bd 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c | |||
| @@ -82,6 +82,9 @@ static struct regulator_ops arizona_micsupp_ops = { | |||
| 82 | 82 | ||
| 83 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 83 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 84 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 84 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| 85 | |||
| 86 | .get_bypass = regulator_get_bypass_regmap, | ||
| 87 | .set_bypass = regulator_set_bypass_regmap, | ||
| 85 | }; | 88 | }; |
| 86 | 89 | ||
| 87 | static const struct regulator_desc arizona_micsupp = { | 90 | static const struct regulator_desc arizona_micsupp = { |
| @@ -95,6 +98,8 @@ static const struct regulator_desc arizona_micsupp = { | |||
| 95 | .vsel_mask = ARIZONA_LDO2_VSEL_MASK, | 98 | .vsel_mask = ARIZONA_LDO2_VSEL_MASK, |
| 96 | .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, | 99 | .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, |
| 97 | .enable_mask = ARIZONA_CPMIC_ENA, | 100 | .enable_mask = ARIZONA_CPMIC_ENA, |
| 101 | .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, | ||
| 102 | .bypass_mask = ARIZONA_CPMIC_BYPASS, | ||
| 98 | 103 | ||
| 99 | .owner = THIS_MODULE, | 104 | .owner = THIS_MODULE, |
| 100 | }; | 105 | }; |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175a..419805cdd9d7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -77,6 +77,7 @@ struct regulator { | |||
| 77 | struct device *dev; | 77 | struct device *dev; |
| 78 | struct list_head list; | 78 | struct list_head list; |
| 79 | unsigned int always_on:1; | 79 | unsigned int always_on:1; |
| 80 | unsigned int bypass:1; | ||
| 80 | int uA_load; | 81 | int uA_load; |
| 81 | int min_uV; | 82 | int min_uV; |
| 82 | int max_uV; | 83 | int max_uV; |
| @@ -394,6 +395,9 @@ static ssize_t regulator_status_show(struct device *dev, | |||
| 394 | case REGULATOR_STATUS_STANDBY: | 395 | case REGULATOR_STATUS_STANDBY: |
| 395 | label = "standby"; | 396 | label = "standby"; |
| 396 | break; | 397 | break; |
| 398 | case REGULATOR_STATUS_BYPASS: | ||
| 399 | label = "bypass"; | ||
| 400 | break; | ||
| 397 | case REGULATOR_STATUS_UNDEFINED: | 401 | case REGULATOR_STATUS_UNDEFINED: |
| 398 | label = "undefined"; | 402 | label = "undefined"; |
| 399 | break; | 403 | break; |
| @@ -585,6 +589,27 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev, | |||
| 585 | static DEVICE_ATTR(suspend_standby_state, 0444, | 589 | static DEVICE_ATTR(suspend_standby_state, 0444, |
| 586 | regulator_suspend_standby_state_show, NULL); | 590 | regulator_suspend_standby_state_show, NULL); |
| 587 | 591 | ||
| 592 | static ssize_t regulator_bypass_show(struct device *dev, | ||
| 593 | struct device_attribute *attr, char *buf) | ||
| 594 | { | ||
| 595 | struct regulator_dev *rdev = dev_get_drvdata(dev); | ||
| 596 | const char *report; | ||
| 597 | bool bypass; | ||
| 598 | int ret; | ||
| 599 | |||
| 600 | ret = rdev->desc->ops->get_bypass(rdev, &bypass); | ||
| 601 | |||
| 602 | if (ret != 0) | ||
| 603 | report = "unknown"; | ||
| 604 | else if (bypass) | ||
| 605 | report = "enabled"; | ||
| 606 | else | ||
| 607 | report = "disabled"; | ||
| 608 | |||
| 609 | return sprintf(buf, "%s\n", report); | ||
| 610 | } | ||
| 611 | static DEVICE_ATTR(bypass, 0444, | ||
| 612 | regulator_bypass_show, NULL); | ||
| 588 | 613 | ||
| 589 | /* | 614 | /* |
| 590 | * These are the only attributes are present for all regulators. | 615 | * These are the only attributes are present for all regulators. |
| @@ -2674,6 +2699,100 @@ out: | |||
| 2674 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); | 2699 | EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); |
| 2675 | 2700 | ||
| 2676 | /** | 2701 | /** |
| 2702 | * regulator_set_bypass_regmap - Default set_bypass() using regmap | ||
| 2703 | * | ||
| 2704 | * @rdev: device to operate on. | ||
| 2705 | * @enable: state to set. | ||
| 2706 | */ | ||
| 2707 | int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) | ||
| 2708 | { | ||
| 2709 | unsigned int val; | ||
| 2710 | |||
| 2711 | if (enable) | ||
| 2712 | val = rdev->desc->bypass_mask; | ||
| 2713 | else | ||
| 2714 | val = 0; | ||
| 2715 | |||
| 2716 | return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, | ||
| 2717 | rdev->desc->bypass_mask, val); | ||
| 2718 | } | ||
| 2719 | EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); | ||
| 2720 | |||
| 2721 | /** | ||
| 2722 | * regulator_get_bypass_regmap - Default get_bypass() using regmap | ||
| 2723 | * | ||
| 2724 | * @rdev: device to operate on. | ||
| 2725 | * @enable: current state. | ||
| 2726 | */ | ||
| 2727 | int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) | ||
| 2728 | { | ||
| 2729 | unsigned int val; | ||
| 2730 | int ret; | ||
| 2731 | |||
| 2732 | ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); | ||
| 2733 | if (ret != 0) | ||
| 2734 | return ret; | ||
| 2735 | |||
| 2736 | *enable = val & rdev->desc->bypass_mask; | ||
| 2737 | |||
| 2738 | return 0; | ||
| 2739 | } | ||
| 2740 | EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); | ||
| 2741 | |||
| 2742 | /** | ||
| 2743 | * regulator_allow_bypass - allow the regulator to go into bypass mode | ||
| 2744 | * | ||
| 2745 | * @regulator: Regulator to configure | ||
| 2746 | * @allow: enable or disable bypass mode | ||
| 2747 | * | ||
| 2748 | * Allow the regulator to go into bypass mode if all other consumers | ||
| 2749 | * for the regulator also enable bypass mode and the machine | ||
| 2750 | * constraints allow this. Bypass mode means that the regulator is | ||
| 2751 | * simply passing the input directly to the output with no regulation. | ||
| 2752 | */ | ||
| 2753 | int regulator_allow_bypass(struct regulator *regulator, bool enable) | ||
| 2754 | { | ||
| 2755 | struct regulator_dev *rdev = regulator->rdev; | ||
| 2756 | int ret = 0; | ||
| 2757 | |||
| 2758 | if (!rdev->desc->ops->set_bypass) | ||
| 2759 | return 0; | ||
| 2760 | |||
| 2761 | if (rdev->constraints && | ||
| 2762 | !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) | ||
| 2763 | return 0; | ||
| 2764 | |||
| 2765 | mutex_lock(&rdev->mutex); | ||
| 2766 | |||
| 2767 | if (enable && !regulator->bypass) { | ||
| 2768 | rdev->bypass_count++; | ||
| 2769 | |||
| 2770 | if (rdev->bypass_count == rdev->open_count) { | ||
| 2771 | ret = rdev->desc->ops->set_bypass(rdev, enable); | ||
| 2772 | if (ret != 0) | ||
| 2773 | rdev->bypass_count--; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | } else if (!enable && regulator->bypass) { | ||
| 2777 | rdev->bypass_count--; | ||
| 2778 | |||
| 2779 | if (rdev->bypass_count != rdev->open_count) { | ||
| 2780 | ret = rdev->desc->ops->set_bypass(rdev, enable); | ||
| 2781 | if (ret != 0) | ||
| 2782 | rdev->bypass_count++; | ||
| 2783 | } | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | if (ret == 0) | ||
| 2787 | regulator->bypass = enable; | ||
| 2788 | |||
| 2789 | mutex_unlock(&rdev->mutex); | ||
| 2790 | |||
| 2791 | return ret; | ||
| 2792 | } | ||
| 2793 | EXPORT_SYMBOL_GPL(regulator_allow_bypass); | ||
| 2794 | |||
| 2795 | /** | ||
| 2677 | * regulator_register_notifier - register regulator event notifier | 2796 | * regulator_register_notifier - register regulator event notifier |
| 2678 | * @regulator: regulator source | 2797 | * @regulator: regulator source |
| 2679 | * @nb: notifier block | 2798 | * @nb: notifier block |
| @@ -3036,6 +3155,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
| 3036 | if (status < 0) | 3155 | if (status < 0) |
| 3037 | return status; | 3156 | return status; |
| 3038 | } | 3157 | } |
| 3158 | if (ops->get_bypass) { | ||
| 3159 | status = device_create_file(dev, &dev_attr_bypass); | ||
| 3160 | if (status < 0) | ||
| 3161 | return status; | ||
| 3162 | } | ||
| 3039 | 3163 | ||
| 3040 | /* some attributes are type-specific */ | 3164 | /* some attributes are type-specific */ |
| 3041 | if (rdev->desc->type == REGULATOR_CURRENT) { | 3165 | if (rdev->desc->type == REGULATOR_CURRENT) { |
| @@ -3124,6 +3248,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) | |||
| 3124 | &rdev->use_count); | 3248 | &rdev->use_count); |
| 3125 | debugfs_create_u32("open_count", 0444, rdev->debugfs, | 3249 | debugfs_create_u32("open_count", 0444, rdev->debugfs, |
| 3126 | &rdev->open_count); | 3250 | &rdev->open_count); |
| 3251 | debugfs_create_u32("bypass_count", 0444, rdev->debugfs, | ||
| 3252 | &rdev->bypass_count); | ||
| 3127 | } | 3253 | } |
| 3128 | 3254 | ||
| 3129 | /** | 3255 | /** |
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5cb70ca1e98d..f203a972dedf 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
| @@ -237,6 +237,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = { | |||
| 237 | .set_mode = wm831x_gp_ldo_set_mode, | 237 | .set_mode = wm831x_gp_ldo_set_mode, |
| 238 | .get_status = wm831x_gp_ldo_get_status, | 238 | .get_status = wm831x_gp_ldo_get_status, |
| 239 | .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, | 239 | .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode, |
| 240 | .get_bypass = regulator_get_bypass_regmap, | ||
| 241 | .set_bypass = regulator_set_bypass_regmap, | ||
| 240 | 242 | ||
| 241 | .is_enabled = regulator_is_enabled_regmap, | 243 | .is_enabled = regulator_is_enabled_regmap, |
| 242 | .enable = regulator_enable_regmap, | 244 | .enable = regulator_enable_regmap, |
| @@ -293,6 +295,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) | |||
| 293 | ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; | 295 | ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK; |
| 294 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; | 296 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
| 295 | ldo->desc.enable_mask = 1 << id; | 297 | ldo->desc.enable_mask = 1 << id; |
| 298 | ldo->desc.bypass_reg = ldo->base; | ||
| 299 | ldo->desc.bypass_mask = WM831X_LDO1_SWI; | ||
| 296 | 300 | ||
| 297 | config.dev = pdev->dev.parent; | 301 | config.dev = pdev->dev.parent; |
| 298 | if (pdata) | 302 | if (pdata) |
| @@ -488,6 +492,8 @@ static struct regulator_ops wm831x_aldo_ops = { | |||
| 488 | .get_mode = wm831x_aldo_get_mode, | 492 | .get_mode = wm831x_aldo_get_mode, |
| 489 | .set_mode = wm831x_aldo_set_mode, | 493 | .set_mode = wm831x_aldo_set_mode, |
| 490 | .get_status = wm831x_aldo_get_status, | 494 | .get_status = wm831x_aldo_get_status, |
| 495 | .set_bypass = regulator_set_bypass_regmap, | ||
| 496 | .get_bypass = regulator_get_bypass_regmap, | ||
| 491 | 497 | ||
| 492 | .is_enabled = regulator_is_enabled_regmap, | 498 | .is_enabled = regulator_is_enabled_regmap, |
| 493 | .enable = regulator_enable_regmap, | 499 | .enable = regulator_enable_regmap, |
| @@ -544,6 +550,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) | |||
| 544 | ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; | 550 | ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK; |
| 545 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; | 551 | ldo->desc.enable_reg = WM831X_LDO_ENABLE; |
| 546 | ldo->desc.enable_mask = 1 << id; | 552 | ldo->desc.enable_mask = 1 << id; |
| 553 | ldo->desc.bypass_reg = ldo->base; | ||
| 554 | ldo->desc.bypass_mask = WM831X_LDO7_SWI; | ||
| 547 | 555 | ||
| 548 | config.dev = pdev->dev.parent; | 556 | config.dev = pdev->dev.parent; |
| 549 | if (pdata) | 557 | if (pdata) |
diff --git a/include/linux/mfd/abx500/ab8500-codec.h b/include/linux/mfd/abx500/ab8500-codec.h index dc6529202cdd..d7079413def0 100644 --- a/include/linux/mfd/abx500/ab8500-codec.h +++ b/include/linux/mfd/abx500/ab8500-codec.h | |||
| @@ -23,7 +23,8 @@ enum amic_type { | |||
| 23 | /* Mic-biases */ | 23 | /* Mic-biases */ |
| 24 | enum amic_micbias { | 24 | enum amic_micbias { |
| 25 | AMIC_MICBIAS_VAMIC1, | 25 | AMIC_MICBIAS_VAMIC1, |
| 26 | AMIC_MICBIAS_VAMIC2 | 26 | AMIC_MICBIAS_VAMIC2, |
| 27 | AMIC_MICBIAS_UNKNOWN | ||
| 27 | }; | 28 | }; |
| 28 | 29 | ||
| 29 | /* Bias-voltage */ | 30 | /* Bias-voltage */ |
| @@ -31,7 +32,8 @@ enum ear_cm_voltage { | |||
| 31 | EAR_CMV_0_95V, | 32 | EAR_CMV_0_95V, |
| 32 | EAR_CMV_1_10V, | 33 | EAR_CMV_1_10V, |
| 33 | EAR_CMV_1_27V, | 34 | EAR_CMV_1_27V, |
| 34 | EAR_CMV_1_58V | 35 | EAR_CMV_1_58V, |
| 36 | EAR_CMV_UNKNOWN | ||
| 35 | }; | 37 | }; |
| 36 | 38 | ||
| 37 | /* Analog microphone settings */ | 39 | /* Analog microphone settings */ |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index da339fd8c755..ea3e35816621 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
| @@ -177,6 +177,8 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode); | |||
| 177 | unsigned int regulator_get_mode(struct regulator *regulator); | 177 | unsigned int regulator_get_mode(struct regulator *regulator); |
| 178 | int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); | 178 | int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); |
| 179 | 179 | ||
| 180 | int regulator_allow_bypass(struct regulator *regulator, bool allow); | ||
| 181 | |||
| 180 | /* regulator notifier block */ | 182 | /* regulator notifier block */ |
| 181 | int regulator_register_notifier(struct regulator *regulator, | 183 | int regulator_register_notifier(struct regulator *regulator, |
| 182 | struct notifier_block *nb); | 184 | struct notifier_block *nb); |
| @@ -328,6 +330,12 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator, | |||
| 328 | return REGULATOR_MODE_NORMAL; | 330 | return REGULATOR_MODE_NORMAL; |
| 329 | } | 331 | } |
| 330 | 332 | ||
| 333 | static inline int regulator_allow_bypass(struct regulator *regulator, | ||
| 334 | bool allow) | ||
| 335 | { | ||
| 336 | return 0; | ||
| 337 | } | ||
| 338 | |||
| 331 | static inline int regulator_register_notifier(struct regulator *regulator, | 339 | static inline int regulator_register_notifier(struct regulator *regulator, |
| 332 | struct notifier_block *nb) | 340 | struct notifier_block *nb) |
| 333 | { | 341 | { |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index bac4c871f3bd..7274a469e8d9 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
| @@ -32,6 +32,8 @@ enum regulator_status { | |||
| 32 | REGULATOR_STATUS_NORMAL, | 32 | REGULATOR_STATUS_NORMAL, |
| 33 | REGULATOR_STATUS_IDLE, | 33 | REGULATOR_STATUS_IDLE, |
| 34 | REGULATOR_STATUS_STANDBY, | 34 | REGULATOR_STATUS_STANDBY, |
| 35 | /* The regulator is enabled but not regulating */ | ||
| 36 | REGULATOR_STATUS_BYPASS, | ||
| 35 | /* in case that any other status doesn't apply */ | 37 | /* in case that any other status doesn't apply */ |
| 36 | REGULATOR_STATUS_UNDEFINED, | 38 | REGULATOR_STATUS_UNDEFINED, |
| 37 | }; | 39 | }; |
| @@ -67,6 +69,9 @@ enum regulator_status { | |||
| 67 | * @get_optimum_mode: Get the most efficient operating mode for the regulator | 69 | * @get_optimum_mode: Get the most efficient operating mode for the regulator |
| 68 | * when running with the specified parameters. | 70 | * when running with the specified parameters. |
| 69 | * | 71 | * |
| 72 | * @set_bypass: Set the regulator in bypass mode. | ||
| 73 | * @get_bypass: Get the regulator bypass mode state. | ||
| 74 | * | ||
| 70 | * @enable_time: Time taken for the regulator voltage output voltage to | 75 | * @enable_time: Time taken for the regulator voltage output voltage to |
| 71 | * stabilise after being enabled, in microseconds. | 76 | * stabilise after being enabled, in microseconds. |
| 72 | * @set_ramp_delay: Set the ramp delay for the regulator. The driver should | 77 | * @set_ramp_delay: Set the ramp delay for the regulator. The driver should |
| @@ -133,6 +138,10 @@ struct regulator_ops { | |||
| 133 | unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, | 138 | unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV, |
| 134 | int output_uV, int load_uA); | 139 | int output_uV, int load_uA); |
| 135 | 140 | ||
| 141 | /* control and report on bypass mode */ | ||
| 142 | int (*set_bypass)(struct regulator_dev *dev, bool enable); | ||
| 143 | int (*get_bypass)(struct regulator_dev *dev, bool *enable); | ||
| 144 | |||
| 136 | /* the operations below are for configuration of regulator state when | 145 | /* the operations below are for configuration of regulator state when |
| 137 | * its parent PMIC enters a global STANDBY/HIBERNATE state */ | 146 | * its parent PMIC enters a global STANDBY/HIBERNATE state */ |
| 138 | 147 | ||
| @@ -205,6 +214,8 @@ struct regulator_desc { | |||
| 205 | unsigned int vsel_mask; | 214 | unsigned int vsel_mask; |
| 206 | unsigned int enable_reg; | 215 | unsigned int enable_reg; |
| 207 | unsigned int enable_mask; | 216 | unsigned int enable_mask; |
| 217 | unsigned int bypass_reg; | ||
| 218 | unsigned int bypass_mask; | ||
| 208 | 219 | ||
| 209 | unsigned int enable_time; | 220 | unsigned int enable_time; |
| 210 | }; | 221 | }; |
| @@ -253,6 +264,7 @@ struct regulator_dev { | |||
| 253 | int exclusive; | 264 | int exclusive; |
| 254 | u32 use_count; | 265 | u32 use_count; |
| 255 | u32 open_count; | 266 | u32 open_count; |
| 267 | u32 bypass_count; | ||
| 256 | 268 | ||
| 257 | /* lists we belong to */ | 269 | /* lists we belong to */ |
| 258 | struct list_head list; /* list of all regulators */ | 270 | struct list_head list; /* list of all regulators */ |
| @@ -310,6 +322,8 @@ int regulator_disable_regmap(struct regulator_dev *rdev); | |||
| 310 | int regulator_set_voltage_time_sel(struct regulator_dev *rdev, | 322 | int regulator_set_voltage_time_sel(struct regulator_dev *rdev, |
| 311 | unsigned int old_selector, | 323 | unsigned int old_selector, |
| 312 | unsigned int new_selector); | 324 | unsigned int new_selector); |
| 325 | int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable); | ||
| 326 | int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable); | ||
| 313 | 327 | ||
| 314 | void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); | 328 | void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); |
| 315 | 329 | ||
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 40dd0a394cfa..36adbc82de6a 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
| @@ -32,6 +32,7 @@ struct regulator; | |||
| 32 | * board/machine. | 32 | * board/machine. |
| 33 | * STATUS: Regulator can be enabled and disabled. | 33 | * STATUS: Regulator can be enabled and disabled. |
| 34 | * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator. | 34 | * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator. |
| 35 | * BYPASS: Regulator can be put into bypass mode | ||
| 35 | */ | 36 | */ |
| 36 | 37 | ||
| 37 | #define REGULATOR_CHANGE_VOLTAGE 0x1 | 38 | #define REGULATOR_CHANGE_VOLTAGE 0x1 |
| @@ -39,6 +40,7 @@ struct regulator; | |||
| 39 | #define REGULATOR_CHANGE_MODE 0x4 | 40 | #define REGULATOR_CHANGE_MODE 0x4 |
| 40 | #define REGULATOR_CHANGE_STATUS 0x8 | 41 | #define REGULATOR_CHANGE_STATUS 0x8 |
| 41 | #define REGULATOR_CHANGE_DRMS 0x10 | 42 | #define REGULATOR_CHANGE_DRMS 0x10 |
| 43 | #define REGULATOR_CHANGE_BYPASS 0x20 | ||
| 42 | 44 | ||
| 43 | /** | 45 | /** |
| 44 | * struct regulator_state - regulator state during low power system states | 46 | * struct regulator_state - regulator state during low power system states |
diff --git a/include/sound/da9055.h b/include/sound/da9055.h new file mode 100644 index 000000000000..cf1241b64d89 --- /dev/null +++ b/include/sound/da9055.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* | ||
| 2 | * DA9055 ALSA Soc codec driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Dialog Semiconductor | ||
| 5 | * | ||
| 6 | * Tested on (Samsung SMDK6410 board + DA9055 EVB) using I2S and I2C | ||
| 7 | * Written by David Chen <david.chen@diasemi.com> and | ||
| 8 | * Ashish Chavan <ashish.chavan@kpitcummins.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 13 | * option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __SOUND_DA9055_H__ | ||
| 17 | #define __SOUND_DA9055_H__ | ||
| 18 | |||
| 19 | enum da9055_micbias_voltage { | ||
| 20 | DA9055_MICBIAS_1_6V = 0, | ||
| 21 | DA9055_MICBIAS_1_8V = 1, | ||
| 22 | DA9055_MICBIAS_2_1V = 2, | ||
| 23 | DA9055_MICBIAS_2_2V = 3, | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct da9055_platform_data { | ||
| 27 | /* Selects which of the two MicBias pins acts as the bias source */ | ||
| 28 | bool micbias_source; | ||
| 29 | /* Selects the micbias voltage */ | ||
| 30 | enum da9055_micbias_voltage micbias; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #endif | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index c96bf5ae80a6..e1ef63d4a5c4 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
| @@ -320,6 +320,9 @@ struct device; | |||
| 320 | #define SND_SOC_DAPM_EVENT_OFF(e) \ | 320 | #define SND_SOC_DAPM_EVENT_OFF(e) \ |
| 321 | (e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)) | 321 | (e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)) |
| 322 | 322 | ||
| 323 | /* regulator widget flags */ | ||
| 324 | #define SND_SOC_DAPM_REGULATOR_BYPASS 0x1 /* bypass when disabled */ | ||
| 325 | |||
| 323 | struct snd_soc_dapm_widget; | 326 | struct snd_soc_dapm_widget; |
| 324 | enum snd_soc_dapm_type; | 327 | enum snd_soc_dapm_type; |
| 325 | struct snd_soc_dapm_path; | 328 | struct snd_soc_dapm_path; |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 3684255e5fba..b92759a39361 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
| @@ -37,6 +37,7 @@ config SND_SOC_ALL_CODECS | |||
| 37 | select SND_SOC_CX20442 | 37 | select SND_SOC_CX20442 |
| 38 | select SND_SOC_DA7210 if I2C | 38 | select SND_SOC_DA7210 if I2C |
| 39 | select SND_SOC_DA732X if I2C | 39 | select SND_SOC_DA732X if I2C |
| 40 | select SND_SOC_DA9055 if I2C | ||
| 40 | select SND_SOC_DFBMCS320 | 41 | select SND_SOC_DFBMCS320 |
| 41 | select SND_SOC_ISABELLE if I2C | 42 | select SND_SOC_ISABELLE if I2C |
| 42 | select SND_SOC_JZ4740_CODEC | 43 | select SND_SOC_JZ4740_CODEC |
| @@ -239,6 +240,9 @@ config SND_SOC_DA7210 | |||
| 239 | config SND_SOC_DA732X | 240 | config SND_SOC_DA732X |
| 240 | tristate | 241 | tristate |
| 241 | 242 | ||
| 243 | config SND_SOC_DA9055 | ||
| 244 | tristate | ||
| 245 | |||
| 242 | config SND_SOC_DFBMCS320 | 246 | config SND_SOC_DFBMCS320 |
| 243 | tristate | 247 | tristate |
| 244 | 248 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index ca508b251df7..9bd4d95aab4f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
| @@ -24,6 +24,7 @@ snd-soc-cs4271-objs := cs4271.o | |||
| 24 | snd-soc-cx20442-objs := cx20442.o | 24 | snd-soc-cx20442-objs := cx20442.o |
| 25 | snd-soc-da7210-objs := da7210.o | 25 | snd-soc-da7210-objs := da7210.o |
| 26 | snd-soc-da732x-objs := da732x.o | 26 | snd-soc-da732x-objs := da732x.o |
| 27 | snd-soc-da9055-objs := da9055.o | ||
| 27 | snd-soc-dfbmcs320-objs := dfbmcs320.o | 28 | snd-soc-dfbmcs320-objs := dfbmcs320.o |
| 28 | snd-soc-dmic-objs := dmic.o | 29 | snd-soc-dmic-objs := dmic.o |
| 29 | snd-soc-isabelle-objs := isabelle.o | 30 | snd-soc-isabelle-objs := isabelle.o |
| @@ -144,6 +145,7 @@ obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | |||
| 144 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 145 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
| 145 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 146 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
| 146 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | 147 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o |
| 148 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | ||
| 147 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o | 149 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o |
| 148 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 150 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
| 149 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 151 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 2c1c2524ef8c..af547490b4f7 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/mfd/abx500/ab8500-sysctrl.h> | 34 | #include <linux/mfd/abx500/ab8500-sysctrl.h> |
| 35 | #include <linux/mfd/abx500/ab8500-codec.h> | 35 | #include <linux/mfd/abx500/ab8500-codec.h> |
| 36 | #include <linux/regulator/consumer.h> | 36 | #include <linux/regulator/consumer.h> |
| 37 | #include <linux/of.h> | ||
| 37 | 38 | ||
| 38 | #include <sound/core.h> | 39 | #include <sound/core.h> |
| 39 | #include <sound/pcm.h> | 40 | #include <sound/pcm.h> |
| @@ -2394,9 +2395,65 @@ struct snd_soc_dai_driver ab8500_codec_dai[] = { | |||
| 2394 | } | 2395 | } |
| 2395 | }; | 2396 | }; |
| 2396 | 2397 | ||
| 2398 | static void ab8500_codec_of_probe(struct device *dev, struct device_node *np, | ||
| 2399 | struct ab8500_codec_platform_data *codec) | ||
| 2400 | { | ||
| 2401 | u32 value; | ||
| 2402 | |||
| 2403 | if (of_get_property(np, "stericsson,amic1-type-single-ended", NULL)) | ||
| 2404 | codec->amics.mic1_type = AMIC_TYPE_SINGLE_ENDED; | ||
| 2405 | else | ||
| 2406 | codec->amics.mic1_type = AMIC_TYPE_DIFFERENTIAL; | ||
| 2407 | |||
| 2408 | if (of_get_property(np, "stericsson,amic2-type-single-ended", NULL)) | ||
| 2409 | codec->amics.mic2_type = AMIC_TYPE_SINGLE_ENDED; | ||
| 2410 | else | ||
| 2411 | codec->amics.mic2_type = AMIC_TYPE_DIFFERENTIAL; | ||
| 2412 | |||
| 2413 | /* Has a non-standard Vamic been requested? */ | ||
| 2414 | if (of_get_property(np, "stericsson,amic1a-bias-vamic2", NULL)) | ||
| 2415 | codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC2; | ||
| 2416 | else | ||
| 2417 | codec->amics.mic1a_micbias = AMIC_MICBIAS_VAMIC1; | ||
| 2418 | |||
| 2419 | if (of_get_property(np, "stericsson,amic1b-bias-vamic2", NULL)) | ||
| 2420 | codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC2; | ||
| 2421 | else | ||
| 2422 | codec->amics.mic1b_micbias = AMIC_MICBIAS_VAMIC1; | ||
| 2423 | |||
| 2424 | if (of_get_property(np, "stericsson,amic2-bias-vamic1", NULL)) | ||
| 2425 | codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC1; | ||
| 2426 | else | ||
| 2427 | codec->amics.mic2_micbias = AMIC_MICBIAS_VAMIC2; | ||
| 2428 | |||
| 2429 | if (!of_property_read_u32(np, "stericsson,earpeice-cmv", &value)) { | ||
| 2430 | switch (value) { | ||
| 2431 | case 950 : | ||
| 2432 | codec->ear_cmv = EAR_CMV_0_95V; | ||
| 2433 | break; | ||
| 2434 | case 1100 : | ||
| 2435 | codec->ear_cmv = EAR_CMV_1_10V; | ||
| 2436 | break; | ||
| 2437 | case 1270 : | ||
| 2438 | codec->ear_cmv = EAR_CMV_1_27V; | ||
| 2439 | break; | ||
| 2440 | case 1580 : | ||
| 2441 | codec->ear_cmv = EAR_CMV_1_58V; | ||
| 2442 | break; | ||
| 2443 | default : | ||
| 2444 | codec->ear_cmv = EAR_CMV_UNKNOWN; | ||
| 2445 | dev_err(dev, "Unsuitable earpiece voltage found in DT\n"); | ||
| 2446 | } | ||
| 2447 | } else { | ||
| 2448 | dev_warn(dev, "No earpiece voltage found in DT - using default\n"); | ||
| 2449 | codec->ear_cmv = EAR_CMV_0_95V; | ||
| 2450 | } | ||
| 2451 | } | ||
| 2452 | |||
| 2397 | static int ab8500_codec_probe(struct snd_soc_codec *codec) | 2453 | static int ab8500_codec_probe(struct snd_soc_codec *codec) |
| 2398 | { | 2454 | { |
| 2399 | struct device *dev = codec->dev; | 2455 | struct device *dev = codec->dev; |
| 2456 | struct device_node *np = dev->of_node; | ||
| 2400 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); | 2457 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev); |
| 2401 | struct ab8500_platform_data *pdata; | 2458 | struct ab8500_platform_data *pdata; |
| 2402 | struct filter_control *fc; | 2459 | struct filter_control *fc; |
| @@ -2407,6 +2464,30 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
| 2407 | /* Setup AB8500 according to board-settings */ | 2464 | /* Setup AB8500 according to board-settings */ |
| 2408 | pdata = dev_get_platdata(dev->parent); | 2465 | pdata = dev_get_platdata(dev->parent); |
| 2409 | 2466 | ||
| 2467 | if (np) { | ||
| 2468 | if (!pdata) | ||
| 2469 | pdata = devm_kzalloc(dev, | ||
| 2470 | sizeof(struct ab8500_platform_data), | ||
| 2471 | GFP_KERNEL); | ||
| 2472 | |||
| 2473 | if (pdata && !pdata->codec) | ||
| 2474 | pdata->codec | ||
| 2475 | = devm_kzalloc(dev, | ||
| 2476 | sizeof(struct ab8500_codec_platform_data), | ||
| 2477 | GFP_KERNEL); | ||
| 2478 | |||
| 2479 | if (!(pdata && pdata->codec)) | ||
| 2480 | return -ENOMEM; | ||
| 2481 | |||
| 2482 | ab8500_codec_of_probe(dev, np, pdata->codec); | ||
| 2483 | |||
| 2484 | } else { | ||
| 2485 | if (!(pdata && pdata->codec)) { | ||
| 2486 | dev_err(dev, "No codec platform data or DT found\n"); | ||
| 2487 | return -EINVAL; | ||
| 2488 | } | ||
| 2489 | } | ||
| 2490 | |||
| 2410 | status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); | 2491 | status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); |
| 2411 | if (status < 0) { | 2492 | if (status < 0) { |
| 2412 | pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); | 2493 | pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index c167c896eaee..c03b65af3059 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
| @@ -119,6 +119,24 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | |||
| 119 | "DSP1.4", | 119 | "DSP1.4", |
| 120 | "DSP1.5", | 120 | "DSP1.5", |
| 121 | "DSP1.6", | 121 | "DSP1.6", |
| 122 | "DSP2.1", | ||
| 123 | "DSP2.2", | ||
| 124 | "DSP2.3", | ||
| 125 | "DSP2.4", | ||
| 126 | "DSP2.5", | ||
| 127 | "DSP2.6", | ||
| 128 | "DSP3.1", | ||
| 129 | "DSP3.2", | ||
| 130 | "DSP3.3", | ||
| 131 | "DSP3.4", | ||
| 132 | "DSP3.5", | ||
| 133 | "DSP3.6", | ||
| 134 | "DSP4.1", | ||
| 135 | "DSP4.2", | ||
| 136 | "DSP4.3", | ||
| 137 | "DSP4.4", | ||
| 138 | "DSP4.5", | ||
| 139 | "DSP4.6", | ||
| 122 | "ASRC1L", | 140 | "ASRC1L", |
| 123 | "ASRC1R", | 141 | "ASRC1R", |
| 124 | "ASRC2L", | 142 | "ASRC2L", |
| @@ -180,6 +198,24 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { | |||
| 180 | 0x6b, | 198 | 0x6b, |
| 181 | 0x6c, | 199 | 0x6c, |
| 182 | 0x6d, | 200 | 0x6d, |
| 201 | 0x70, /* DSP2.1 */ | ||
| 202 | 0x71, | ||
| 203 | 0x72, | ||
| 204 | 0x73, | ||
| 205 | 0x74, | ||
| 206 | 0x75, | ||
| 207 | 0x78, /* DSP3.1 */ | ||
| 208 | 0x79, | ||
| 209 | 0x7a, | ||
| 210 | 0x7b, | ||
| 211 | 0x7c, | ||
| 212 | 0x7d, | ||
| 213 | 0x80, /* DSP4.1 */ | ||
| 214 | 0x81, | ||
| 215 | 0x82, | ||
| 216 | 0x83, | ||
| 217 | 0x84, | ||
| 218 | 0x85, | ||
| 183 | 0x90, /* ASRC1L */ | 219 | 0x90, /* ASRC1L */ |
| 184 | 0x91, | 220 | 0x91, |
| 185 | 0x92, | 221 | 0x92, |
| @@ -234,6 +270,9 @@ static unsigned int arizona_sysclk_48k_rates[] = { | |||
| 234 | 12288000, | 270 | 12288000, |
| 235 | 22579200, | 271 | 22579200, |
| 236 | 49152000, | 272 | 49152000, |
| 273 | 73728000, | ||
| 274 | 98304000, | ||
| 275 | 147456000, | ||
| 237 | }; | 276 | }; |
| 238 | 277 | ||
| 239 | static unsigned int arizona_sysclk_44k1_rates[] = { | 278 | static unsigned int arizona_sysclk_44k1_rates[] = { |
| @@ -241,6 +280,9 @@ static unsigned int arizona_sysclk_44k1_rates[] = { | |||
| 241 | 11289600, | 280 | 11289600, |
| 242 | 24576000, | 281 | 24576000, |
| 243 | 45158400, | 282 | 45158400, |
| 283 | 67737600, | ||
| 284 | 90316800, | ||
| 285 | 135475200, | ||
| 244 | }; | 286 | }; |
| 245 | 287 | ||
| 246 | static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, | 288 | static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index eb66b52777c9..36ec64946120 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
| @@ -61,7 +61,7 @@ struct arizona_priv { | |||
| 61 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; | 61 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | #define ARIZONA_NUM_MIXER_INPUTS 57 | 64 | #define ARIZONA_NUM_MIXER_INPUTS 75 |
| 65 | 65 | ||
| 66 | extern const unsigned int arizona_mixer_tlv[]; | 66 | extern const unsigned int arizona_mixer_tlv[]; |
| 67 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; | 67 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 815b53bc2d27..8e4779812b96 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
| @@ -459,7 +459,7 @@ static struct snd_soc_dai_driver cs4270_dai = { | |||
| 459 | .name = "cs4270-hifi", | 459 | .name = "cs4270-hifi", |
| 460 | .playback = { | 460 | .playback = { |
| 461 | .stream_name = "Playback", | 461 | .stream_name = "Playback", |
| 462 | .channels_min = 1, | 462 | .channels_min = 2, |
| 463 | .channels_max = 2, | 463 | .channels_max = 2, |
| 464 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 464 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
| 465 | .rate_min = 4000, | 465 | .rate_min = 4000, |
| @@ -468,7 +468,7 @@ static struct snd_soc_dai_driver cs4270_dai = { | |||
| 468 | }, | 468 | }, |
| 469 | .capture = { | 469 | .capture = { |
| 470 | .stream_name = "Capture", | 470 | .stream_name = "Capture", |
| 471 | .channels_min = 1, | 471 | .channels_min = 2, |
| 472 | .channels_max = 2, | 472 | .channels_max = 2, |
| 473 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 473 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
| 474 | .rate_min = 4000, | 474 | .rate_min = 4000, |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 9eb01d7d58a3..f994af34f552 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
| @@ -22,12 +22,14 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <sound/pcm.h> | ||
| 26 | #include <sound/soc.h> | ||
| 27 | #include <sound/tlv.h> | ||
| 28 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
| 29 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
| 30 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
| 28 | #include <linux/of_device.h> | ||
| 29 | #include <linux/of_gpio.h> | ||
| 30 | #include <sound/pcm.h> | ||
| 31 | #include <sound/soc.h> | ||
| 32 | #include <sound/tlv.h> | ||
| 31 | #include <sound/cs4271.h> | 33 | #include <sound/cs4271.h> |
| 32 | 34 | ||
| 33 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 35 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| @@ -458,6 +460,14 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec) | |||
| 458 | #define cs4271_soc_resume NULL | 460 | #define cs4271_soc_resume NULL |
| 459 | #endif /* CONFIG_PM */ | 461 | #endif /* CONFIG_PM */ |
| 460 | 462 | ||
| 463 | #ifdef CONFIG_OF | ||
| 464 | static const struct of_device_id cs4271_dt_ids[] = { | ||
| 465 | { .compatible = "cirrus,cs4271", }, | ||
| 466 | { } | ||
| 467 | }; | ||
| 468 | MODULE_DEVICE_TABLE(of, cs4271_dt_ids); | ||
| 469 | #endif | ||
| 470 | |||
| 461 | static int cs4271_probe(struct snd_soc_codec *codec) | 471 | static int cs4271_probe(struct snd_soc_codec *codec) |
| 462 | { | 472 | { |
| 463 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 473 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
| @@ -465,6 +475,12 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
| 465 | int ret; | 475 | int ret; |
| 466 | int gpio_nreset = -EINVAL; | 476 | int gpio_nreset = -EINVAL; |
| 467 | 477 | ||
| 478 | #ifdef CONFIG_OF | ||
| 479 | if (of_match_device(cs4271_dt_ids, codec->dev)) | ||
| 480 | gpio_nreset = of_get_named_gpio(codec->dev->of_node, | ||
| 481 | "reset-gpio", 0); | ||
| 482 | #endif | ||
| 483 | |||
| 468 | if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) | 484 | if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) |
| 469 | gpio_nreset = cs4271plat->gpio_nreset; | 485 | gpio_nreset = cs4271plat->gpio_nreset; |
| 470 | 486 | ||
| @@ -569,6 +585,7 @@ static struct spi_driver cs4271_spi_driver = { | |||
| 569 | .driver = { | 585 | .driver = { |
| 570 | .name = "cs4271", | 586 | .name = "cs4271", |
| 571 | .owner = THIS_MODULE, | 587 | .owner = THIS_MODULE, |
| 588 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
| 572 | }, | 589 | }, |
| 573 | .probe = cs4271_spi_probe, | 590 | .probe = cs4271_spi_probe, |
| 574 | .remove = __devexit_p(cs4271_spi_remove), | 591 | .remove = __devexit_p(cs4271_spi_remove), |
| @@ -608,6 +625,7 @@ static struct i2c_driver cs4271_i2c_driver = { | |||
| 608 | .driver = { | 625 | .driver = { |
| 609 | .name = "cs4271", | 626 | .name = "cs4271", |
| 610 | .owner = THIS_MODULE, | 627 | .owner = THIS_MODULE, |
| 628 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
| 611 | }, | 629 | }, |
| 612 | .id_table = cs4271_i2c_id, | 630 | .id_table = cs4271_i2c_id, |
| 613 | .probe = cs4271_i2c_probe, | 631 | .probe = cs4271_i2c_probe, |
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c new file mode 100644 index 000000000000..185d8dd36399 --- /dev/null +++ b/sound/soc/codecs/da9055.c | |||
| @@ -0,0 +1,1510 @@ | |||
| 1 | /* | ||
| 2 | * DA9055 ALSA Soc codec driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Dialog Semiconductor | ||
| 5 | * | ||
| 6 | * Tested on (Samsung SMDK6410 board + DA9055 EVB) using I2S and I2C | ||
| 7 | * Written by David Chen <david.chen@diasemi.com> and | ||
| 8 | * Ashish Chavan <ashish.chavan@kpitcummins.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 13 | * option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/regmap.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <sound/pcm.h> | ||
| 22 | #include <sound/pcm_params.h> | ||
| 23 | #include <sound/soc.h> | ||
| 24 | #include <sound/initval.h> | ||
| 25 | #include <sound/tlv.h> | ||
| 26 | #include <sound/da9055.h> | ||
| 27 | |||
| 28 | /* DA9055 register space */ | ||
| 29 | |||
| 30 | /* Status Registers */ | ||
| 31 | #define DA9055_STATUS1 0x02 | ||
| 32 | #define DA9055_PLL_STATUS 0x03 | ||
| 33 | #define DA9055_AUX_L_GAIN_STATUS 0x04 | ||
| 34 | #define DA9055_AUX_R_GAIN_STATUS 0x05 | ||
| 35 | #define DA9055_MIC_L_GAIN_STATUS 0x06 | ||
| 36 | #define DA9055_MIC_R_GAIN_STATUS 0x07 | ||
| 37 | #define DA9055_MIXIN_L_GAIN_STATUS 0x08 | ||
| 38 | #define DA9055_MIXIN_R_GAIN_STATUS 0x09 | ||
| 39 | #define DA9055_ADC_L_GAIN_STATUS 0x0A | ||
| 40 | #define DA9055_ADC_R_GAIN_STATUS 0x0B | ||
| 41 | #define DA9055_DAC_L_GAIN_STATUS 0x0C | ||
| 42 | #define DA9055_DAC_R_GAIN_STATUS 0x0D | ||
| 43 | #define DA9055_HP_L_GAIN_STATUS 0x0E | ||
| 44 | #define DA9055_HP_R_GAIN_STATUS 0x0F | ||
| 45 | #define DA9055_LINE_GAIN_STATUS 0x10 | ||
| 46 | |||
| 47 | /* System Initialisation Registers */ | ||
| 48 | #define DA9055_CIF_CTRL 0x20 | ||
| 49 | #define DA9055_DIG_ROUTING_AIF 0X21 | ||
| 50 | #define DA9055_SR 0x22 | ||
| 51 | #define DA9055_REFERENCES 0x23 | ||
| 52 | #define DA9055_PLL_FRAC_TOP 0x24 | ||
| 53 | #define DA9055_PLL_FRAC_BOT 0x25 | ||
| 54 | #define DA9055_PLL_INTEGER 0x26 | ||
| 55 | #define DA9055_PLL_CTRL 0x27 | ||
| 56 | #define DA9055_AIF_CLK_MODE 0x28 | ||
| 57 | #define DA9055_AIF_CTRL 0x29 | ||
| 58 | #define DA9055_DIG_ROUTING_DAC 0x2A | ||
| 59 | #define DA9055_ALC_CTRL1 0x2B | ||
| 60 | |||
| 61 | /* Input - Gain, Select and Filter Registers */ | ||
| 62 | #define DA9055_AUX_L_GAIN 0x30 | ||
| 63 | #define DA9055_AUX_R_GAIN 0x31 | ||
| 64 | #define DA9055_MIXIN_L_SELECT 0x32 | ||
| 65 | #define DA9055_MIXIN_R_SELECT 0x33 | ||
| 66 | #define DA9055_MIXIN_L_GAIN 0x34 | ||
| 67 | #define DA9055_MIXIN_R_GAIN 0x35 | ||
| 68 | #define DA9055_ADC_L_GAIN 0x36 | ||
| 69 | #define DA9055_ADC_R_GAIN 0x37 | ||
| 70 | #define DA9055_ADC_FILTERS1 0x38 | ||
| 71 | #define DA9055_MIC_L_GAIN 0x39 | ||
| 72 | #define DA9055_MIC_R_GAIN 0x3A | ||
| 73 | |||
| 74 | /* Output - Gain, Select and Filter Registers */ | ||
| 75 | #define DA9055_DAC_FILTERS5 0x40 | ||
| 76 | #define DA9055_DAC_FILTERS2 0x41 | ||
| 77 | #define DA9055_DAC_FILTERS3 0x42 | ||
| 78 | #define DA9055_DAC_FILTERS4 0x43 | ||
| 79 | #define DA9055_DAC_FILTERS1 0x44 | ||
| 80 | #define DA9055_DAC_L_GAIN 0x45 | ||
| 81 | #define DA9055_DAC_R_GAIN 0x46 | ||
| 82 | #define DA9055_CP_CTRL 0x47 | ||
| 83 | #define DA9055_HP_L_GAIN 0x48 | ||
| 84 | #define DA9055_HP_R_GAIN 0x49 | ||
| 85 | #define DA9055_LINE_GAIN 0x4A | ||
| 86 | #define DA9055_MIXOUT_L_SELECT 0x4B | ||
| 87 | #define DA9055_MIXOUT_R_SELECT 0x4C | ||
| 88 | |||
| 89 | /* System Controller Registers */ | ||
| 90 | #define DA9055_SYSTEM_MODES_INPUT 0x50 | ||
| 91 | #define DA9055_SYSTEM_MODES_OUTPUT 0x51 | ||
| 92 | |||
| 93 | /* Control Registers */ | ||
| 94 | #define DA9055_AUX_L_CTRL 0x60 | ||
| 95 | #define DA9055_AUX_R_CTRL 0x61 | ||
| 96 | #define DA9055_MIC_BIAS_CTRL 0x62 | ||
| 97 | #define DA9055_MIC_L_CTRL 0x63 | ||
| 98 | #define DA9055_MIC_R_CTRL 0x64 | ||
| 99 | #define DA9055_MIXIN_L_CTRL 0x65 | ||
| 100 | #define DA9055_MIXIN_R_CTRL 0x66 | ||
| 101 | #define DA9055_ADC_L_CTRL 0x67 | ||
| 102 | #define DA9055_ADC_R_CTRL 0x68 | ||
| 103 | #define DA9055_DAC_L_CTRL 0x69 | ||
| 104 | #define DA9055_DAC_R_CTRL 0x6A | ||
| 105 | #define DA9055_HP_L_CTRL 0x6B | ||
| 106 | #define DA9055_HP_R_CTRL 0x6C | ||
| 107 | #define DA9055_LINE_CTRL 0x6D | ||
| 108 | #define DA9055_MIXOUT_L_CTRL 0x6E | ||
| 109 | #define DA9055_MIXOUT_R_CTRL 0x6F | ||
| 110 | |||
| 111 | /* Configuration Registers */ | ||
| 112 | #define DA9055_LDO_CTRL 0x90 | ||
| 113 | #define DA9055_IO_CTRL 0x91 | ||
| 114 | #define DA9055_GAIN_RAMP_CTRL 0x92 | ||
| 115 | #define DA9055_MIC_CONFIG 0x93 | ||
| 116 | #define DA9055_PC_COUNT 0x94 | ||
| 117 | #define DA9055_CP_VOL_THRESHOLD1 0x95 | ||
| 118 | #define DA9055_CP_DELAY 0x96 | ||
| 119 | #define DA9055_CP_DETECTOR 0x97 | ||
| 120 | #define DA9055_AIF_OFFSET 0x98 | ||
| 121 | #define DA9055_DIG_CTRL 0x99 | ||
| 122 | #define DA9055_ALC_CTRL2 0x9A | ||
| 123 | #define DA9055_ALC_CTRL3 0x9B | ||
| 124 | #define DA9055_ALC_NOISE 0x9C | ||
| 125 | #define DA9055_ALC_TARGET_MIN 0x9D | ||
| 126 | #define DA9055_ALC_TARGET_MAX 0x9E | ||
| 127 | #define DA9055_ALC_GAIN_LIMITS 0x9F | ||
| 128 | #define DA9055_ALC_ANA_GAIN_LIMITS 0xA0 | ||
| 129 | #define DA9055_ALC_ANTICLIP_CTRL 0xA1 | ||
| 130 | #define DA9055_ALC_ANTICLIP_LEVEL 0xA2 | ||
| 131 | #define DA9055_ALC_OFFSET_OP2M_L 0xA6 | ||
| 132 | #define DA9055_ALC_OFFSET_OP2U_L 0xA7 | ||
| 133 | #define DA9055_ALC_OFFSET_OP2M_R 0xAB | ||
| 134 | #define DA9055_ALC_OFFSET_OP2U_R 0xAC | ||
| 135 | #define DA9055_ALC_CIC_OP_LVL_CTRL 0xAD | ||
| 136 | #define DA9055_ALC_CIC_OP_LVL_DATA 0xAE | ||
| 137 | #define DA9055_DAC_NG_SETUP_TIME 0xAF | ||
| 138 | #define DA9055_DAC_NG_OFF_THRESHOLD 0xB0 | ||
| 139 | #define DA9055_DAC_NG_ON_THRESHOLD 0xB1 | ||
| 140 | #define DA9055_DAC_NG_CTRL 0xB2 | ||
| 141 | |||
| 142 | /* SR bit fields */ | ||
| 143 | #define DA9055_SR_8000 (0x1 << 0) | ||
| 144 | #define DA9055_SR_11025 (0x2 << 0) | ||
| 145 | #define DA9055_SR_12000 (0x3 << 0) | ||
| 146 | #define DA9055_SR_16000 (0x5 << 0) | ||
| 147 | #define DA9055_SR_22050 (0x6 << 0) | ||
| 148 | #define DA9055_SR_24000 (0x7 << 0) | ||
| 149 | #define DA9055_SR_32000 (0x9 << 0) | ||
| 150 | #define DA9055_SR_44100 (0xA << 0) | ||
| 151 | #define DA9055_SR_48000 (0xB << 0) | ||
| 152 | #define DA9055_SR_88200 (0xE << 0) | ||
| 153 | #define DA9055_SR_96000 (0xF << 0) | ||
| 154 | |||
| 155 | /* REFERENCES bit fields */ | ||
| 156 | #define DA9055_BIAS_EN (1 << 3) | ||
| 157 | #define DA9055_VMID_EN (1 << 7) | ||
| 158 | |||
| 159 | /* PLL_CTRL bit fields */ | ||
| 160 | #define DA9055_PLL_INDIV_10_20_MHZ (1 << 2) | ||
| 161 | #define DA9055_PLL_SRM_EN (1 << 6) | ||
| 162 | #define DA9055_PLL_EN (1 << 7) | ||
| 163 | |||
| 164 | /* AIF_CLK_MODE bit fields */ | ||
| 165 | #define DA9055_AIF_BCLKS_PER_WCLK_32 (0 << 0) | ||
| 166 | #define DA9055_AIF_BCLKS_PER_WCLK_64 (1 << 0) | ||
| 167 | #define DA9055_AIF_BCLKS_PER_WCLK_128 (2 << 0) | ||
| 168 | #define DA9055_AIF_BCLKS_PER_WCLK_256 (3 << 0) | ||
| 169 | #define DA9055_AIF_CLK_EN_SLAVE_MODE (0 << 7) | ||
| 170 | #define DA9055_AIF_CLK_EN_MASTER_MODE (1 << 7) | ||
| 171 | |||
| 172 | /* AIF_CTRL bit fields */ | ||
| 173 | #define DA9055_AIF_FORMAT_I2S_MODE (0 << 0) | ||
| 174 | #define DA9055_AIF_FORMAT_LEFT_J (1 << 0) | ||
| 175 | #define DA9055_AIF_FORMAT_RIGHT_J (2 << 0) | ||
| 176 | #define DA9055_AIF_WORD_S16_LE (0 << 2) | ||
| 177 | #define DA9055_AIF_WORD_S20_3LE (1 << 2) | ||
| 178 | #define DA9055_AIF_WORD_S24_LE (2 << 2) | ||
| 179 | #define DA9055_AIF_WORD_S32_LE (3 << 2) | ||
| 180 | |||
| 181 | /* MIXIN_L_CTRL bit fields */ | ||
| 182 | #define DA9055_MIXIN_L_MIX_EN (1 << 3) | ||
| 183 | |||
| 184 | /* MIXIN_R_CTRL bit fields */ | ||
| 185 | #define DA9055_MIXIN_R_MIX_EN (1 << 3) | ||
| 186 | |||
| 187 | /* ADC_L_CTRL bit fields */ | ||
| 188 | #define DA9055_ADC_L_EN (1 << 7) | ||
| 189 | |||
| 190 | /* ADC_R_CTRL bit fields */ | ||
| 191 | #define DA9055_ADC_R_EN (1 << 7) | ||
| 192 | |||
| 193 | /* DAC_L_CTRL bit fields */ | ||
| 194 | #define DA9055_DAC_L_MUTE_EN (1 << 6) | ||
| 195 | |||
| 196 | /* DAC_R_CTRL bit fields */ | ||
| 197 | #define DA9055_DAC_R_MUTE_EN (1 << 6) | ||
| 198 | |||
| 199 | /* HP_L_CTRL bit fields */ | ||
| 200 | #define DA9055_HP_L_AMP_OE (1 << 3) | ||
| 201 | |||
| 202 | /* HP_R_CTRL bit fields */ | ||
| 203 | #define DA9055_HP_R_AMP_OE (1 << 3) | ||
| 204 | |||
| 205 | /* LINE_CTRL bit fields */ | ||
| 206 | #define DA9055_LINE_AMP_OE (1 << 3) | ||
| 207 | |||
| 208 | /* MIXOUT_L_CTRL bit fields */ | ||
| 209 | #define DA9055_MIXOUT_L_MIX_EN (1 << 3) | ||
| 210 | |||
| 211 | /* MIXOUT_R_CTRL bit fields */ | ||
| 212 | #define DA9055_MIXOUT_R_MIX_EN (1 << 3) | ||
| 213 | |||
| 214 | /* MIC bias select bit fields */ | ||
| 215 | #define DA9055_MICBIAS2_EN (1 << 6) | ||
| 216 | |||
| 217 | /* ALC_CIC_OP_LEVEL_CTRL bit fields */ | ||
| 218 | #define DA9055_ALC_DATA_MIDDLE (2 << 0) | ||
| 219 | #define DA9055_ALC_DATA_TOP (3 << 0) | ||
| 220 | #define DA9055_ALC_CIC_OP_CHANNEL_LEFT (0 << 7) | ||
| 221 | #define DA9055_ALC_CIC_OP_CHANNEL_RIGHT (1 << 7) | ||
| 222 | |||
| 223 | #define DA9055_AIF_BCLK_MASK (3 << 0) | ||
| 224 | #define DA9055_AIF_CLK_MODE_MASK (1 << 7) | ||
| 225 | #define DA9055_AIF_FORMAT_MASK (3 << 0) | ||
| 226 | #define DA9055_AIF_WORD_LENGTH_MASK (3 << 2) | ||
| 227 | #define DA9055_GAIN_RAMPING_EN (1 << 5) | ||
| 228 | #define DA9055_MICBIAS_LEVEL_MASK (3 << 4) | ||
| 229 | |||
| 230 | #define DA9055_ALC_OFFSET_15_8 0x00FF00 | ||
| 231 | #define DA9055_ALC_OFFSET_17_16 0x030000 | ||
| 232 | #define DA9055_ALC_AVG_ITERATIONS 5 | ||
| 233 | |||
| 234 | struct pll_div { | ||
| 235 | int fref; | ||
| 236 | int fout; | ||
| 237 | u8 frac_top; | ||
| 238 | u8 frac_bot; | ||
| 239 | u8 integer; | ||
| 240 | u8 mode; /* 0 = slave, 1 = master */ | ||
| 241 | }; | ||
| 242 | |||
| 243 | /* PLL divisor table */ | ||
| 244 | static const struct pll_div da9055_pll_div[] = { | ||
| 245 | /* for MASTER mode, fs = 44.1Khz and its harmonics */ | ||
| 246 | {11289600, 2822400, 0x00, 0x00, 0x20, 1}, /* MCLK=11.2896Mhz */ | ||
| 247 | {12000000, 2822400, 0x03, 0x61, 0x1E, 1}, /* MCLK=12Mhz */ | ||
| 248 | {12288000, 2822400, 0x0C, 0xCC, 0x1D, 1}, /* MCLK=12.288Mhz */ | ||
| 249 | {13000000, 2822400, 0x19, 0x45, 0x1B, 1}, /* MCLK=13Mhz */ | ||
| 250 | {13500000, 2822400, 0x18, 0x56, 0x1A, 1}, /* MCLK=13.5Mhz */ | ||
| 251 | {14400000, 2822400, 0x02, 0xD0, 0x19, 1}, /* MCLK=14.4Mhz */ | ||
| 252 | {19200000, 2822400, 0x1A, 0x1C, 0x12, 1}, /* MCLK=19.2Mhz */ | ||
| 253 | {19680000, 2822400, 0x0B, 0x6D, 0x12, 1}, /* MCLK=19.68Mhz */ | ||
| 254 | {19800000, 2822400, 0x07, 0xDD, 0x12, 1}, /* MCLK=19.8Mhz */ | ||
| 255 | /* for MASTER mode, fs = 48Khz and its harmonics */ | ||
| 256 | {11289600, 3072000, 0x1A, 0x8E, 0x22, 1}, /* MCLK=11.2896Mhz */ | ||
| 257 | {12000000, 3072000, 0x18, 0x93, 0x20, 1}, /* MCLK=12Mhz */ | ||
| 258 | {12288000, 3072000, 0x00, 0x00, 0x20, 1}, /* MCLK=12.288Mhz */ | ||
| 259 | {13000000, 3072000, 0x07, 0xEA, 0x1E, 1}, /* MCLK=13Mhz */ | ||
| 260 | {13500000, 3072000, 0x04, 0x11, 0x1D, 1}, /* MCLK=13.5Mhz */ | ||
| 261 | {14400000, 3072000, 0x09, 0xD0, 0x1B, 1}, /* MCLK=14.4Mhz */ | ||
| 262 | {19200000, 3072000, 0x0F, 0x5C, 0x14, 1}, /* MCLK=19.2Mhz */ | ||
| 263 | {19680000, 3072000, 0x1F, 0x60, 0x13, 1}, /* MCLK=19.68Mhz */ | ||
| 264 | {19800000, 3072000, 0x1B, 0x80, 0x13, 1}, /* MCLK=19.8Mhz */ | ||
| 265 | /* for SLAVE mode with SRM */ | ||
| 266 | {11289600, 2822400, 0x0D, 0x47, 0x21, 0}, /* MCLK=11.2896Mhz */ | ||
| 267 | {12000000, 2822400, 0x0D, 0xFA, 0x1F, 0}, /* MCLK=12Mhz */ | ||
| 268 | {12288000, 2822400, 0x16, 0x66, 0x1E, 0}, /* MCLK=12.288Mhz */ | ||
| 269 | {13000000, 2822400, 0x00, 0x98, 0x1D, 0}, /* MCLK=13Mhz */ | ||
| 270 | {13500000, 2822400, 0x1E, 0x33, 0x1B, 0}, /* MCLK=13.5Mhz */ | ||
| 271 | {14400000, 2822400, 0x06, 0x50, 0x1A, 0}, /* MCLK=14.4Mhz */ | ||
| 272 | {19200000, 2822400, 0x14, 0xBC, 0x13, 0}, /* MCLK=19.2Mhz */ | ||
| 273 | {19680000, 2822400, 0x05, 0x66, 0x13, 0}, /* MCLK=19.68Mhz */ | ||
| 274 | {19800000, 2822400, 0x01, 0xAE, 0x13, 0}, /* MCLK=19.8Mhz */ | ||
| 275 | }; | ||
| 276 | |||
| 277 | enum clk_src { | ||
| 278 | DA9055_CLKSRC_MCLK | ||
| 279 | }; | ||
| 280 | |||
| 281 | /* Gain and Volume */ | ||
| 282 | |||
| 283 | static const unsigned int aux_vol_tlv[] = { | ||
| 284 | TLV_DB_RANGE_HEAD(2), | ||
| 285 | 0x0, 0x10, TLV_DB_SCALE_ITEM(-5400, 0, 0), | ||
| 286 | /* -54dB to 15dB */ | ||
| 287 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) | ||
| 288 | }; | ||
| 289 | |||
| 290 | static const unsigned int digital_gain_tlv[] = { | ||
| 291 | TLV_DB_RANGE_HEAD(2), | ||
| 292 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | ||
| 293 | /* -78dB to 12dB */ | ||
| 294 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0) | ||
| 295 | }; | ||
| 296 | |||
| 297 | static const unsigned int alc_analog_gain_tlv[] = { | ||
| 298 | TLV_DB_RANGE_HEAD(2), | ||
| 299 | 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | ||
| 300 | /* 0dB to 36dB */ | ||
| 301 | 0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0) | ||
| 302 | }; | ||
| 303 | |||
| 304 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); | ||
| 305 | static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0); | ||
| 306 | static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0); | ||
| 307 | static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -5700, 100, 0); | ||
| 308 | static const DECLARE_TLV_DB_SCALE(lineout_vol_tlv, -4800, 100, 0); | ||
| 309 | static const DECLARE_TLV_DB_SCALE(alc_threshold_tlv, -9450, 150, 0); | ||
| 310 | static const DECLARE_TLV_DB_SCALE(alc_gain_tlv, 0, 600, 0); | ||
| 311 | |||
| 312 | /* ADC and DAC high pass filter cutoff value */ | ||
| 313 | static const char * const da9055_hpf_cutoff_txt[] = { | ||
| 314 | "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" | ||
| 315 | }; | ||
| 316 | |||
| 317 | static const struct soc_enum da9055_dac_hpf_cutoff = | ||
| 318 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); | ||
| 319 | |||
| 320 | static const struct soc_enum da9055_adc_hpf_cutoff = | ||
| 321 | SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); | ||
| 322 | |||
| 323 | /* ADC and DAC voice mode (8kHz) high pass cutoff value */ | ||
| 324 | static const char * const da9055_vf_cutoff_txt[] = { | ||
| 325 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | ||
| 326 | }; | ||
| 327 | |||
| 328 | static const struct soc_enum da9055_dac_vf_cutoff = | ||
| 329 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); | ||
| 330 | |||
| 331 | static const struct soc_enum da9055_adc_vf_cutoff = | ||
| 332 | SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); | ||
| 333 | |||
| 334 | /* Gain ramping rate value */ | ||
| 335 | static const char * const da9055_gain_ramping_txt[] = { | ||
| 336 | "nominal rate", "nominal rate * 4", "nominal rate * 8", | ||
| 337 | "nominal rate / 8" | ||
| 338 | }; | ||
| 339 | |||
| 340 | static const struct soc_enum da9055_gain_ramping_rate = | ||
| 341 | SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt); | ||
| 342 | |||
| 343 | /* DAC noise gate setup time value */ | ||
| 344 | static const char * const da9055_dac_ng_setup_time_txt[] = { | ||
| 345 | "256 samples", "512 samples", "1024 samples", "2048 samples" | ||
| 346 | }; | ||
| 347 | |||
| 348 | static const struct soc_enum da9055_dac_ng_setup_time = | ||
| 349 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4, | ||
| 350 | da9055_dac_ng_setup_time_txt); | ||
| 351 | |||
| 352 | /* DAC noise gate rampup rate value */ | ||
| 353 | static const char * const da9055_dac_ng_rampup_txt[] = { | ||
| 354 | "0.02 ms/dB", "0.16 ms/dB" | ||
| 355 | }; | ||
| 356 | |||
| 357 | static const struct soc_enum da9055_dac_ng_rampup_rate = | ||
| 358 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2, | ||
| 359 | da9055_dac_ng_rampup_txt); | ||
| 360 | |||
| 361 | /* DAC noise gate rampdown rate value */ | ||
| 362 | static const char * const da9055_dac_ng_rampdown_txt[] = { | ||
| 363 | "0.64 ms/dB", "20.48 ms/dB" | ||
| 364 | }; | ||
| 365 | |||
| 366 | static const struct soc_enum da9055_dac_ng_rampdown_rate = | ||
| 367 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2, | ||
| 368 | da9055_dac_ng_rampdown_txt); | ||
| 369 | |||
| 370 | /* DAC soft mute rate value */ | ||
| 371 | static const char * const da9055_dac_soft_mute_rate_txt[] = { | ||
| 372 | "1", "2", "4", "8", "16", "32", "64" | ||
| 373 | }; | ||
| 374 | |||
| 375 | static const struct soc_enum da9055_dac_soft_mute_rate = | ||
| 376 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7, | ||
| 377 | da9055_dac_soft_mute_rate_txt); | ||
| 378 | |||
| 379 | /* DAC routing select */ | ||
| 380 | static const char * const da9055_dac_src_txt[] = { | ||
| 381 | "ADC output left", "ADC output right", "AIF input left", | ||
| 382 | "AIF input right" | ||
| 383 | }; | ||
| 384 | |||
| 385 | static const struct soc_enum da9055_dac_l_src = | ||
| 386 | SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt); | ||
| 387 | |||
| 388 | static const struct soc_enum da9055_dac_r_src = | ||
| 389 | SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt); | ||
| 390 | |||
| 391 | /* MIC PGA Left source select */ | ||
| 392 | static const char * const da9055_mic_l_src_txt[] = { | ||
| 393 | "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" | ||
| 394 | }; | ||
| 395 | |||
| 396 | static const struct soc_enum da9055_mic_l_src = | ||
| 397 | SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt); | ||
| 398 | |||
| 399 | /* MIC PGA Right source select */ | ||
| 400 | static const char * const da9055_mic_r_src_txt[] = { | ||
| 401 | "MIC2_R_L", "MIC2_R", "MIC2_L" | ||
| 402 | }; | ||
| 403 | |||
| 404 | static const struct soc_enum da9055_mic_r_src = | ||
| 405 | SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt); | ||
| 406 | |||
| 407 | /* ALC Input Signal Tracking rate select */ | ||
| 408 | static const char * const da9055_signal_tracking_rate_txt[] = { | ||
| 409 | "1/4", "1/16", "1/256", "1/65536" | ||
| 410 | }; | ||
| 411 | |||
| 412 | static const struct soc_enum da9055_integ_attack_rate = | ||
| 413 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4, | ||
| 414 | da9055_signal_tracking_rate_txt); | ||
| 415 | |||
| 416 | static const struct soc_enum da9055_integ_release_rate = | ||
| 417 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4, | ||
| 418 | da9055_signal_tracking_rate_txt); | ||
| 419 | |||
| 420 | /* ALC Attack Rate select */ | ||
| 421 | static const char * const da9055_attack_rate_txt[] = { | ||
| 422 | "44/fs", "88/fs", "176/fs", "352/fs", "704/fs", "1408/fs", "2816/fs", | ||
| 423 | "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | ||
| 424 | }; | ||
| 425 | |||
| 426 | static const struct soc_enum da9055_attack_rate = | ||
| 427 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt); | ||
| 428 | |||
| 429 | /* ALC Release Rate select */ | ||
| 430 | static const char * const da9055_release_rate_txt[] = { | ||
| 431 | "176/fs", "352/fs", "704/fs", "1408/fs", "2816/fs", "5632/fs", | ||
| 432 | "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | ||
| 433 | }; | ||
| 434 | |||
| 435 | static const struct soc_enum da9055_release_rate = | ||
| 436 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt); | ||
| 437 | |||
| 438 | /* ALC Hold Time select */ | ||
| 439 | static const char * const da9055_hold_time_txt[] = { | ||
| 440 | "62/fs", "124/fs", "248/fs", "496/fs", "992/fs", "1984/fs", "3968/fs", | ||
| 441 | "7936/fs", "15872/fs", "31744/fs", "63488/fs", "126976/fs", | ||
| 442 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" | ||
| 443 | }; | ||
| 444 | |||
| 445 | static const struct soc_enum da9055_hold_time = | ||
| 446 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt); | ||
| 447 | |||
| 448 | static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) | ||
| 449 | { | ||
| 450 | int mid_data, top_data; | ||
| 451 | int sum = 0; | ||
| 452 | u8 iteration; | ||
| 453 | |||
| 454 | for (iteration = 0; iteration < DA9055_ALC_AVG_ITERATIONS; | ||
| 455 | iteration++) { | ||
| 456 | /* Select the left or right channel and capture data */ | ||
| 457 | snd_soc_write(codec, DA9055_ALC_CIC_OP_LVL_CTRL, reg_val); | ||
| 458 | |||
| 459 | /* Select middle 8 bits for read back from data register */ | ||
| 460 | snd_soc_write(codec, DA9055_ALC_CIC_OP_LVL_CTRL, | ||
| 461 | reg_val | DA9055_ALC_DATA_MIDDLE); | ||
| 462 | mid_data = snd_soc_read(codec, DA9055_ALC_CIC_OP_LVL_DATA); | ||
| 463 | |||
| 464 | /* Select top 8 bits for read back from data register */ | ||
| 465 | snd_soc_write(codec, DA9055_ALC_CIC_OP_LVL_CTRL, | ||
| 466 | reg_val | DA9055_ALC_DATA_TOP); | ||
| 467 | top_data = snd_soc_read(codec, DA9055_ALC_CIC_OP_LVL_DATA); | ||
| 468 | |||
| 469 | sum += ((mid_data << 8) | (top_data << 16)); | ||
| 470 | } | ||
| 471 | |||
| 472 | return sum / DA9055_ALC_AVG_ITERATIONS; | ||
| 473 | } | ||
| 474 | |||
| 475 | static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, | ||
| 476 | struct snd_ctl_elem_value *ucontrol) | ||
| 477 | { | ||
| 478 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 479 | u8 reg_val, adc_left, adc_right; | ||
| 480 | int avg_left_data, avg_right_data, offset_l, offset_r; | ||
| 481 | |||
| 482 | if (ucontrol->value.integer.value[0]) { | ||
| 483 | /* | ||
| 484 | * While enabling ALC (or ALC sync mode), calibration of the DC | ||
| 485 | * offsets must be done first | ||
| 486 | */ | ||
| 487 | |||
| 488 | /* Save current values from ADC control registers */ | ||
| 489 | adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL); | ||
| 490 | adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL); | ||
| 491 | |||
| 492 | /* Enable ADC Left and Right */ | ||
| 493 | snd_soc_update_bits(codec, DA9055_ADC_L_CTRL, | ||
| 494 | DA9055_ADC_L_EN, DA9055_ADC_L_EN); | ||
| 495 | snd_soc_update_bits(codec, DA9055_ADC_R_CTRL, | ||
| 496 | DA9055_ADC_R_EN, DA9055_ADC_R_EN); | ||
| 497 | |||
| 498 | /* Calculate average for Left and Right data */ | ||
| 499 | /* Left Data */ | ||
| 500 | avg_left_data = da9055_get_alc_data(codec, | ||
| 501 | DA9055_ALC_CIC_OP_CHANNEL_LEFT); | ||
| 502 | /* Right Data */ | ||
| 503 | avg_right_data = da9055_get_alc_data(codec, | ||
| 504 | DA9055_ALC_CIC_OP_CHANNEL_RIGHT); | ||
| 505 | |||
| 506 | /* Calculate DC offset */ | ||
| 507 | offset_l = -avg_left_data; | ||
| 508 | offset_r = -avg_right_data; | ||
| 509 | |||
| 510 | reg_val = (offset_l & DA9055_ALC_OFFSET_15_8) >> 8; | ||
| 511 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2M_L, reg_val); | ||
| 512 | reg_val = (offset_l & DA9055_ALC_OFFSET_17_16) >> 16; | ||
| 513 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2U_L, reg_val); | ||
| 514 | |||
| 515 | reg_val = (offset_r & DA9055_ALC_OFFSET_15_8) >> 8; | ||
| 516 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2M_R, reg_val); | ||
| 517 | reg_val = (offset_r & DA9055_ALC_OFFSET_17_16) >> 16; | ||
| 518 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2U_R, reg_val); | ||
| 519 | |||
| 520 | /* Restore original values of ADC control registers */ | ||
| 521 | snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left); | ||
| 522 | snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right); | ||
| 523 | } | ||
| 524 | |||
| 525 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
| 526 | } | ||
| 527 | |||
| 528 | static const struct snd_kcontrol_new da9055_snd_controls[] = { | ||
| 529 | |||
| 530 | /* Volume controls */ | ||
| 531 | SOC_DOUBLE_R_TLV("Mic Volume", | ||
| 532 | DA9055_MIC_L_GAIN, DA9055_MIC_R_GAIN, | ||
| 533 | 0, 0x7, 0, mic_vol_tlv), | ||
| 534 | SOC_DOUBLE_R_TLV("Aux Volume", | ||
| 535 | DA9055_AUX_L_GAIN, DA9055_AUX_R_GAIN, | ||
| 536 | 0, 0x3f, 0, aux_vol_tlv), | ||
| 537 | SOC_DOUBLE_R_TLV("Mixin PGA Volume", | ||
| 538 | DA9055_MIXIN_L_GAIN, DA9055_MIXIN_R_GAIN, | ||
| 539 | 0, 0xf, 0, mixin_gain_tlv), | ||
| 540 | SOC_DOUBLE_R_TLV("ADC Volume", | ||
| 541 | DA9055_ADC_L_GAIN, DA9055_ADC_R_GAIN, | ||
| 542 | 0, 0x7f, 0, digital_gain_tlv), | ||
| 543 | |||
| 544 | SOC_DOUBLE_R_TLV("DAC Volume", | ||
| 545 | DA9055_DAC_L_GAIN, DA9055_DAC_R_GAIN, | ||
| 546 | 0, 0x7f, 0, digital_gain_tlv), | ||
| 547 | SOC_DOUBLE_R_TLV("Headphone Volume", | ||
| 548 | DA9055_HP_L_GAIN, DA9055_HP_R_GAIN, | ||
| 549 | 0, 0x3f, 0, hp_vol_tlv), | ||
| 550 | SOC_SINGLE_TLV("Lineout Volume", DA9055_LINE_GAIN, 0, 0x3f, 0, | ||
| 551 | lineout_vol_tlv), | ||
| 552 | |||
| 553 | /* DAC Equalizer controls */ | ||
| 554 | SOC_SINGLE("DAC EQ Switch", DA9055_DAC_FILTERS4, 7, 1, 0), | ||
| 555 | SOC_SINGLE_TLV("DAC EQ1 Volume", DA9055_DAC_FILTERS2, 0, 0xf, 0, | ||
| 556 | eq_gain_tlv), | ||
| 557 | SOC_SINGLE_TLV("DAC EQ2 Volume", DA9055_DAC_FILTERS2, 4, 0xf, 0, | ||
| 558 | eq_gain_tlv), | ||
| 559 | SOC_SINGLE_TLV("DAC EQ3 Volume", DA9055_DAC_FILTERS3, 0, 0xf, 0, | ||
| 560 | eq_gain_tlv), | ||
| 561 | SOC_SINGLE_TLV("DAC EQ4 Volume", DA9055_DAC_FILTERS3, 4, 0xf, 0, | ||
| 562 | eq_gain_tlv), | ||
| 563 | SOC_SINGLE_TLV("DAC EQ5 Volume", DA9055_DAC_FILTERS4, 0, 0xf, 0, | ||
| 564 | eq_gain_tlv), | ||
| 565 | |||
| 566 | /* High Pass Filter and Voice Mode controls */ | ||
| 567 | SOC_SINGLE("ADC HPF Switch", DA9055_ADC_FILTERS1, 7, 1, 0), | ||
| 568 | SOC_ENUM("ADC HPF Cutoff", da9055_adc_hpf_cutoff), | ||
| 569 | SOC_SINGLE("ADC Voice Mode Switch", DA9055_ADC_FILTERS1, 3, 1, 0), | ||
| 570 | SOC_ENUM("ADC Voice Cutoff", da9055_adc_vf_cutoff), | ||
| 571 | |||
| 572 | SOC_SINGLE("DAC HPF Switch", DA9055_DAC_FILTERS1, 7, 1, 0), | ||
| 573 | SOC_ENUM("DAC HPF Cutoff", da9055_dac_hpf_cutoff), | ||
| 574 | SOC_SINGLE("DAC Voice Mode Switch", DA9055_DAC_FILTERS1, 3, 1, 0), | ||
| 575 | SOC_ENUM("DAC Voice Cutoff", da9055_dac_vf_cutoff), | ||
| 576 | |||
| 577 | /* Mute controls */ | ||
| 578 | SOC_DOUBLE_R("Mic Switch", DA9055_MIC_L_CTRL, | ||
| 579 | DA9055_MIC_R_CTRL, 6, 1, 0), | ||
| 580 | SOC_DOUBLE_R("Aux Switch", DA9055_AUX_L_CTRL, | ||
| 581 | DA9055_AUX_R_CTRL, 6, 1, 0), | ||
| 582 | SOC_DOUBLE_R("Mixin PGA Switch", DA9055_MIXIN_L_CTRL, | ||
| 583 | DA9055_MIXIN_R_CTRL, 6, 1, 0), | ||
| 584 | SOC_DOUBLE_R("ADC Switch", DA9055_ADC_L_CTRL, | ||
| 585 | DA9055_ADC_R_CTRL, 6, 1, 0), | ||
| 586 | SOC_DOUBLE_R("Headphone Switch", DA9055_HP_L_CTRL, | ||
| 587 | DA9055_HP_R_CTRL, 6, 1, 0), | ||
| 588 | SOC_SINGLE("Lineout Switch", DA9055_LINE_CTRL, 6, 1, 0), | ||
| 589 | SOC_SINGLE("DAC Soft Mute Switch", DA9055_DAC_FILTERS5, 7, 1, 0), | ||
| 590 | SOC_ENUM("DAC Soft Mute Rate", da9055_dac_soft_mute_rate), | ||
| 591 | |||
| 592 | /* Zero Cross controls */ | ||
| 593 | SOC_DOUBLE_R("Aux ZC Switch", DA9055_AUX_L_CTRL, | ||
| 594 | DA9055_AUX_R_CTRL, 4, 1, 0), | ||
| 595 | SOC_DOUBLE_R("Mixin PGA ZC Switch", DA9055_MIXIN_L_CTRL, | ||
| 596 | DA9055_MIXIN_R_CTRL, 4, 1, 0), | ||
| 597 | SOC_DOUBLE_R("Headphone ZC Switch", DA9055_HP_L_CTRL, | ||
| 598 | DA9055_HP_R_CTRL, 4, 1, 0), | ||
| 599 | SOC_SINGLE("Lineout ZC Switch", DA9055_LINE_CTRL, 4, 1, 0), | ||
| 600 | |||
| 601 | /* Gain Ramping controls */ | ||
| 602 | SOC_DOUBLE_R("Aux Gain Ramping Switch", DA9055_AUX_L_CTRL, | ||
| 603 | DA9055_AUX_R_CTRL, 5, 1, 0), | ||
| 604 | SOC_DOUBLE_R("Mixin Gain Ramping Switch", DA9055_MIXIN_L_CTRL, | ||
| 605 | DA9055_MIXIN_R_CTRL, 5, 1, 0), | ||
| 606 | SOC_DOUBLE_R("ADC Gain Ramping Switch", DA9055_ADC_L_CTRL, | ||
| 607 | DA9055_ADC_R_CTRL, 5, 1, 0), | ||
| 608 | SOC_DOUBLE_R("DAC Gain Ramping Switch", DA9055_DAC_L_CTRL, | ||
| 609 | DA9055_DAC_R_CTRL, 5, 1, 0), | ||
| 610 | SOC_DOUBLE_R("Headphone Gain Ramping Switch", DA9055_HP_L_CTRL, | ||
| 611 | DA9055_HP_R_CTRL, 5, 1, 0), | ||
| 612 | SOC_SINGLE("Lineout Gain Ramping Switch", DA9055_LINE_CTRL, 5, 1, 0), | ||
| 613 | SOC_ENUM("Gain Ramping Rate", da9055_gain_ramping_rate), | ||
| 614 | |||
| 615 | /* DAC Noise Gate controls */ | ||
| 616 | SOC_SINGLE("DAC NG Switch", DA9055_DAC_NG_CTRL, 7, 1, 0), | ||
| 617 | SOC_SINGLE("DAC NG ON Threshold", DA9055_DAC_NG_ON_THRESHOLD, | ||
| 618 | 0, 0x7, 0), | ||
| 619 | SOC_SINGLE("DAC NG OFF Threshold", DA9055_DAC_NG_OFF_THRESHOLD, | ||
| 620 | 0, 0x7, 0), | ||
| 621 | SOC_ENUM("DAC NG Setup Time", da9055_dac_ng_setup_time), | ||
| 622 | SOC_ENUM("DAC NG Rampup Rate", da9055_dac_ng_rampup_rate), | ||
| 623 | SOC_ENUM("DAC NG Rampdown Rate", da9055_dac_ng_rampdown_rate), | ||
| 624 | |||
| 625 | /* DAC Invertion control */ | ||
| 626 | SOC_SINGLE("DAC Left Invert", DA9055_DIG_CTRL, 3, 1, 0), | ||
| 627 | SOC_SINGLE("DAC Right Invert", DA9055_DIG_CTRL, 7, 1, 0), | ||
| 628 | |||
| 629 | /* DMIC controls */ | ||
| 630 | SOC_DOUBLE_R("DMIC Switch", DA9055_MIXIN_L_SELECT, | ||
| 631 | DA9055_MIXIN_R_SELECT, 7, 1, 0), | ||
| 632 | |||
| 633 | /* ALC Controls */ | ||
| 634 | SOC_DOUBLE_EXT("ALC Switch", DA9055_ALC_CTRL1, 3, 7, 1, 0, | ||
| 635 | snd_soc_get_volsw, da9055_put_alc_sw), | ||
| 636 | SOC_SINGLE_EXT("ALC Sync Mode Switch", DA9055_ALC_CTRL1, 1, 1, 0, | ||
| 637 | snd_soc_get_volsw, da9055_put_alc_sw), | ||
| 638 | SOC_SINGLE("ALC Offset Switch", DA9055_ALC_CTRL1, 0, 1, 0), | ||
| 639 | SOC_SINGLE("ALC Anticlip Mode Switch", DA9055_ALC_ANTICLIP_CTRL, | ||
| 640 | 7, 1, 0), | ||
| 641 | SOC_SINGLE("ALC Anticlip Level", DA9055_ALC_ANTICLIP_LEVEL, | ||
| 642 | 0, 0x7f, 0), | ||
| 643 | SOC_SINGLE_TLV("ALC Min Threshold Volume", DA9055_ALC_TARGET_MIN, | ||
| 644 | 0, 0x3f, 1, alc_threshold_tlv), | ||
| 645 | SOC_SINGLE_TLV("ALC Max Threshold Volume", DA9055_ALC_TARGET_MAX, | ||
| 646 | 0, 0x3f, 1, alc_threshold_tlv), | ||
| 647 | SOC_SINGLE_TLV("ALC Noise Threshold Volume", DA9055_ALC_NOISE, | ||
| 648 | 0, 0x3f, 1, alc_threshold_tlv), | ||
| 649 | SOC_SINGLE_TLV("ALC Max Gain Volume", DA9055_ALC_GAIN_LIMITS, | ||
| 650 | 4, 0xf, 0, alc_gain_tlv), | ||
| 651 | SOC_SINGLE_TLV("ALC Max Attenuation Volume", DA9055_ALC_GAIN_LIMITS, | ||
| 652 | 0, 0xf, 0, alc_gain_tlv), | ||
| 653 | SOC_SINGLE_TLV("ALC Min Analog Gain Volume", | ||
| 654 | DA9055_ALC_ANA_GAIN_LIMITS, | ||
| 655 | 0, 0x7, 0, alc_analog_gain_tlv), | ||
| 656 | SOC_SINGLE_TLV("ALC Max Analog Gain Volume", | ||
| 657 | DA9055_ALC_ANA_GAIN_LIMITS, | ||
| 658 | 4, 0x7, 0, alc_analog_gain_tlv), | ||
| 659 | SOC_ENUM("ALC Attack Rate", da9055_attack_rate), | ||
| 660 | SOC_ENUM("ALC Release Rate", da9055_release_rate), | ||
| 661 | SOC_ENUM("ALC Hold Time", da9055_hold_time), | ||
| 662 | /* | ||
| 663 | * Rate at which input signal envelope is tracked as the signal gets | ||
| 664 | * larger | ||
| 665 | */ | ||
| 666 | SOC_ENUM("ALC Integ Attack Rate", da9055_integ_attack_rate), | ||
| 667 | /* | ||
| 668 | * Rate at which input signal envelope is tracked as the signal gets | ||
| 669 | * smaller | ||
| 670 | */ | ||
| 671 | SOC_ENUM("ALC Integ Release Rate", da9055_integ_release_rate), | ||
| 672 | }; | ||
| 673 | |||
| 674 | /* DAPM Controls */ | ||
| 675 | |||
| 676 | /* Mic PGA Left Source */ | ||
| 677 | static const struct snd_kcontrol_new da9055_mic_l_mux_controls = | ||
| 678 | SOC_DAPM_ENUM("Route", da9055_mic_l_src); | ||
| 679 | |||
| 680 | /* Mic PGA Right Source */ | ||
| 681 | static const struct snd_kcontrol_new da9055_mic_r_mux_controls = | ||
| 682 | SOC_DAPM_ENUM("Route", da9055_mic_r_src); | ||
| 683 | |||
| 684 | /* In Mixer Left */ | ||
| 685 | static const struct snd_kcontrol_new da9055_dapm_mixinl_controls[] = { | ||
| 686 | SOC_DAPM_SINGLE("Aux Left Switch", DA9055_MIXIN_L_SELECT, 0, 1, 0), | ||
| 687 | SOC_DAPM_SINGLE("Mic Left Switch", DA9055_MIXIN_L_SELECT, 1, 1, 0), | ||
| 688 | SOC_DAPM_SINGLE("Mic Right Switch", DA9055_MIXIN_L_SELECT, 2, 1, 0), | ||
| 689 | }; | ||
| 690 | |||
| 691 | /* In Mixer Right */ | ||
| 692 | static const struct snd_kcontrol_new da9055_dapm_mixinr_controls[] = { | ||
| 693 | SOC_DAPM_SINGLE("Aux Right Switch", DA9055_MIXIN_R_SELECT, 0, 1, 0), | ||
| 694 | SOC_DAPM_SINGLE("Mic Right Switch", DA9055_MIXIN_R_SELECT, 1, 1, 0), | ||
| 695 | SOC_DAPM_SINGLE("Mic Left Switch", DA9055_MIXIN_R_SELECT, 2, 1, 0), | ||
| 696 | SOC_DAPM_SINGLE("Mixin Left Switch", DA9055_MIXIN_R_SELECT, 3, 1, 0), | ||
| 697 | }; | ||
| 698 | |||
| 699 | /* DAC Left Source */ | ||
| 700 | static const struct snd_kcontrol_new da9055_dac_l_mux_controls = | ||
| 701 | SOC_DAPM_ENUM("Route", da9055_dac_l_src); | ||
| 702 | |||
| 703 | /* DAC Right Source */ | ||
| 704 | static const struct snd_kcontrol_new da9055_dac_r_mux_controls = | ||
| 705 | SOC_DAPM_ENUM("Route", da9055_dac_r_src); | ||
| 706 | |||
| 707 | /* Out Mixer Left */ | ||
| 708 | static const struct snd_kcontrol_new da9055_dapm_mixoutl_controls[] = { | ||
| 709 | SOC_DAPM_SINGLE("Aux Left Switch", DA9055_MIXOUT_L_SELECT, 0, 1, 0), | ||
| 710 | SOC_DAPM_SINGLE("Mixin Left Switch", DA9055_MIXOUT_L_SELECT, 1, 1, 0), | ||
| 711 | SOC_DAPM_SINGLE("Mixin Right Switch", DA9055_MIXOUT_L_SELECT, 2, 1, 0), | ||
| 712 | SOC_DAPM_SINGLE("DAC Left Switch", DA9055_MIXOUT_L_SELECT, 3, 1, 0), | ||
| 713 | SOC_DAPM_SINGLE("Aux Left Invert Switch", DA9055_MIXOUT_L_SELECT, | ||
| 714 | 4, 1, 0), | ||
| 715 | SOC_DAPM_SINGLE("Mixin Left Invert Switch", DA9055_MIXOUT_L_SELECT, | ||
| 716 | 5, 1, 0), | ||
| 717 | SOC_DAPM_SINGLE("Mixin Right Invert Switch", DA9055_MIXOUT_L_SELECT, | ||
| 718 | 6, 1, 0), | ||
| 719 | }; | ||
| 720 | |||
| 721 | /* Out Mixer Right */ | ||
| 722 | static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = { | ||
| 723 | SOC_DAPM_SINGLE("Aux Right Switch", DA9055_MIXOUT_R_SELECT, 0, 1, 0), | ||
| 724 | SOC_DAPM_SINGLE("Mixin Right Switch", DA9055_MIXOUT_R_SELECT, 1, 1, 0), | ||
| 725 | SOC_DAPM_SINGLE("Mixin Left Switch", DA9055_MIXOUT_R_SELECT, 2, 1, 0), | ||
| 726 | SOC_DAPM_SINGLE("DAC Right Switch", DA9055_MIXOUT_R_SELECT, 3, 1, 0), | ||
| 727 | SOC_DAPM_SINGLE("Aux Right Invert Switch", DA9055_MIXOUT_R_SELECT, | ||
| 728 | 4, 1, 0), | ||
| 729 | SOC_DAPM_SINGLE("Mixin Right Invert Switch", DA9055_MIXOUT_R_SELECT, | ||
| 730 | 5, 1, 0), | ||
| 731 | SOC_DAPM_SINGLE("Mixin Left Invert Switch", DA9055_MIXOUT_R_SELECT, | ||
| 732 | 6, 1, 0), | ||
| 733 | }; | ||
| 734 | |||
| 735 | /* DAPM widgets */ | ||
| 736 | static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = { | ||
| 737 | /* Input Side */ | ||
| 738 | |||
| 739 | /* Input Lines */ | ||
| 740 | SND_SOC_DAPM_INPUT("MIC1"), | ||
| 741 | SND_SOC_DAPM_INPUT("MIC2"), | ||
| 742 | SND_SOC_DAPM_INPUT("AUXL"), | ||
| 743 | SND_SOC_DAPM_INPUT("AUXR"), | ||
| 744 | |||
| 745 | /* MUXs for Mic PGA source selection */ | ||
| 746 | SND_SOC_DAPM_MUX("Mic Left Source", SND_SOC_NOPM, 0, 0, | ||
| 747 | &da9055_mic_l_mux_controls), | ||
| 748 | SND_SOC_DAPM_MUX("Mic Right Source", SND_SOC_NOPM, 0, 0, | ||
| 749 | &da9055_mic_r_mux_controls), | ||
| 750 | |||
| 751 | /* Input PGAs */ | ||
| 752 | SND_SOC_DAPM_PGA("Mic Left", DA9055_MIC_L_CTRL, 7, 0, NULL, 0), | ||
| 753 | SND_SOC_DAPM_PGA("Mic Right", DA9055_MIC_R_CTRL, 7, 0, NULL, 0), | ||
| 754 | SND_SOC_DAPM_PGA("Aux Left", DA9055_AUX_L_CTRL, 7, 0, NULL, 0), | ||
| 755 | SND_SOC_DAPM_PGA("Aux Right", DA9055_AUX_R_CTRL, 7, 0, NULL, 0), | ||
| 756 | SND_SOC_DAPM_PGA("MIXIN Left", DA9055_MIXIN_L_CTRL, 7, 0, NULL, 0), | ||
| 757 | SND_SOC_DAPM_PGA("MIXIN Right", DA9055_MIXIN_R_CTRL, 7, 0, NULL, 0), | ||
| 758 | |||
| 759 | SND_SOC_DAPM_SUPPLY("Mic Bias", DA9055_MIC_BIAS_CTRL, 7, 0, NULL, 0), | ||
| 760 | SND_SOC_DAPM_SUPPLY("AIF", DA9055_AIF_CTRL, 7, 0, NULL, 0), | ||
| 761 | SND_SOC_DAPM_SUPPLY("Charge Pump", DA9055_CP_CTRL, 7, 0, NULL, 0), | ||
| 762 | |||
| 763 | /* Input Mixers */ | ||
| 764 | SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0, | ||
| 765 | &da9055_dapm_mixinl_controls[0], | ||
| 766 | ARRAY_SIZE(da9055_dapm_mixinl_controls)), | ||
| 767 | SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0, | ||
| 768 | &da9055_dapm_mixinr_controls[0], | ||
| 769 | ARRAY_SIZE(da9055_dapm_mixinr_controls)), | ||
| 770 | |||
| 771 | /* ADCs */ | ||
| 772 | SND_SOC_DAPM_ADC("ADC Left", "Capture", DA9055_ADC_L_CTRL, 7, 0), | ||
| 773 | SND_SOC_DAPM_ADC("ADC Right", "Capture", DA9055_ADC_R_CTRL, 7, 0), | ||
| 774 | |||
| 775 | /* Output Side */ | ||
| 776 | |||
| 777 | /* MUXs for DAC source selection */ | ||
| 778 | SND_SOC_DAPM_MUX("DAC Left Source", SND_SOC_NOPM, 0, 0, | ||
| 779 | &da9055_dac_l_mux_controls), | ||
| 780 | SND_SOC_DAPM_MUX("DAC Right Source", SND_SOC_NOPM, 0, 0, | ||
| 781 | &da9055_dac_r_mux_controls), | ||
| 782 | |||
| 783 | /* AIF input */ | ||
| 784 | SND_SOC_DAPM_AIF_IN("AIFIN Left", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
| 785 | SND_SOC_DAPM_AIF_IN("AIFIN Right", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
| 786 | |||
| 787 | /* DACs */ | ||
| 788 | SND_SOC_DAPM_DAC("DAC Left", "Playback", DA9055_DAC_L_CTRL, 7, 0), | ||
| 789 | SND_SOC_DAPM_DAC("DAC Right", "Playback", DA9055_DAC_R_CTRL, 7, 0), | ||
| 790 | |||
| 791 | /* Output Mixers */ | ||
| 792 | SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0, | ||
| 793 | &da9055_dapm_mixoutl_controls[0], | ||
| 794 | ARRAY_SIZE(da9055_dapm_mixoutl_controls)), | ||
| 795 | SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0, | ||
| 796 | &da9055_dapm_mixoutr_controls[0], | ||
| 797 | ARRAY_SIZE(da9055_dapm_mixoutr_controls)), | ||
| 798 | |||
| 799 | /* Output PGAs */ | ||
| 800 | SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0), | ||
| 801 | SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0), | ||
| 802 | SND_SOC_DAPM_PGA("Lineout", DA9055_LINE_CTRL, 7, 0, NULL, 0), | ||
| 803 | SND_SOC_DAPM_PGA("Headphone Left", DA9055_HP_L_CTRL, 7, 0, NULL, 0), | ||
| 804 | SND_SOC_DAPM_PGA("Headphone Right", DA9055_HP_R_CTRL, 7, 0, NULL, 0), | ||
| 805 | |||
| 806 | /* Output Lines */ | ||
| 807 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
| 808 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
| 809 | SND_SOC_DAPM_OUTPUT("LINE"), | ||
| 810 | }; | ||
| 811 | |||
| 812 | /* DAPM audio route definition */ | ||
| 813 | static const struct snd_soc_dapm_route da9055_audio_map[] = { | ||
| 814 | /* Dest Connecting Widget source */ | ||
| 815 | |||
| 816 | /* Input path */ | ||
| 817 | {"Mic Left Source", "MIC1_P_N", "MIC1"}, | ||
| 818 | {"Mic Left Source", "MIC1_P", "MIC1"}, | ||
| 819 | {"Mic Left Source", "MIC1_N", "MIC1"}, | ||
| 820 | {"Mic Left Source", "MIC2_L", "MIC2"}, | ||
| 821 | |||
| 822 | {"Mic Right Source", "MIC2_R_L", "MIC2"}, | ||
| 823 | {"Mic Right Source", "MIC2_R", "MIC2"}, | ||
| 824 | {"Mic Right Source", "MIC2_L", "MIC2"}, | ||
| 825 | |||
| 826 | {"Mic Left", NULL, "Mic Left Source"}, | ||
| 827 | {"Mic Right", NULL, "Mic Right Source"}, | ||
| 828 | |||
| 829 | {"Aux Left", NULL, "AUXL"}, | ||
| 830 | {"Aux Right", NULL, "AUXR"}, | ||
| 831 | |||
| 832 | {"In Mixer Left", "Mic Left Switch", "Mic Left"}, | ||
| 833 | {"In Mixer Left", "Mic Right Switch", "Mic Right"}, | ||
| 834 | {"In Mixer Left", "Aux Left Switch", "Aux Left"}, | ||
| 835 | |||
| 836 | {"In Mixer Right", "Mic Right Switch", "Mic Right"}, | ||
| 837 | {"In Mixer Right", "Mic Left Switch", "Mic Left"}, | ||
| 838 | {"In Mixer Right", "Aux Right Switch", "Aux Right"}, | ||
| 839 | {"In Mixer Right", "Mixin Left Switch", "MIXIN Left"}, | ||
| 840 | |||
| 841 | {"MIXIN Left", NULL, "In Mixer Left"}, | ||
| 842 | {"ADC Left", NULL, "MIXIN Left"}, | ||
| 843 | |||
| 844 | {"MIXIN Right", NULL, "In Mixer Right"}, | ||
| 845 | {"ADC Right", NULL, "MIXIN Right"}, | ||
| 846 | |||
| 847 | {"ADC Left", NULL, "AIF"}, | ||
| 848 | {"ADC Right", NULL, "AIF"}, | ||
| 849 | |||
| 850 | /* Output path */ | ||
| 851 | {"AIFIN Left", NULL, "AIF"}, | ||
| 852 | {"AIFIN Right", NULL, "AIF"}, | ||
| 853 | |||
| 854 | {"DAC Left Source", "ADC output left", "ADC Left"}, | ||
| 855 | {"DAC Left Source", "ADC output right", "ADC Right"}, | ||
| 856 | {"DAC Left Source", "AIF input left", "AIFIN Left"}, | ||
| 857 | {"DAC Left Source", "AIF input right", "AIFIN Right"}, | ||
| 858 | |||
| 859 | {"DAC Right Source", "ADC output left", "ADC Left"}, | ||
| 860 | {"DAC Right Source", "ADC output right", "ADC Right"}, | ||
| 861 | {"DAC Right Source", "AIF input left", "AIFIN Left"}, | ||
| 862 | {"DAC Right Source", "AIF input right", "AIFIN Right"}, | ||
| 863 | |||
| 864 | {"DAC Left", NULL, "DAC Left Source"}, | ||
| 865 | {"DAC Right", NULL, "DAC Right Source"}, | ||
| 866 | |||
| 867 | {"Out Mixer Left", "Aux Left Switch", "Aux Left"}, | ||
| 868 | {"Out Mixer Left", "Mixin Left Switch", "MIXIN Left"}, | ||
| 869 | {"Out Mixer Left", "Mixin Right Switch", "MIXIN Right"}, | ||
| 870 | {"Out Mixer Left", "Aux Left Invert Switch", "Aux Left"}, | ||
| 871 | {"Out Mixer Left", "Mixin Left Invert Switch", "MIXIN Left"}, | ||
| 872 | {"Out Mixer Left", "Mixin Right Invert Switch", "MIXIN Right"}, | ||
| 873 | {"Out Mixer Left", "DAC Left Switch", "DAC Left"}, | ||
| 874 | |||
| 875 | {"Out Mixer Right", "Aux Right Switch", "Aux Right"}, | ||
| 876 | {"Out Mixer Right", "Mixin Right Switch", "MIXIN Right"}, | ||
| 877 | {"Out Mixer Right", "Mixin Left Switch", "MIXIN Left"}, | ||
| 878 | {"Out Mixer Right", "Aux Right Invert Switch", "Aux Right"}, | ||
| 879 | {"Out Mixer Right", "Mixin Right Invert Switch", "MIXIN Right"}, | ||
| 880 | {"Out Mixer Right", "Mixin Left Invert Switch", "MIXIN Left"}, | ||
| 881 | {"Out Mixer Right", "DAC Right Switch", "DAC Right"}, | ||
| 882 | |||
| 883 | {"MIXOUT Left", NULL, "Out Mixer Left"}, | ||
| 884 | {"Headphone Left", NULL, "MIXOUT Left"}, | ||
| 885 | {"Headphone Left", NULL, "Charge Pump"}, | ||
| 886 | {"HPL", NULL, "Headphone Left"}, | ||
| 887 | |||
| 888 | {"MIXOUT Right", NULL, "Out Mixer Right"}, | ||
| 889 | {"Headphone Right", NULL, "MIXOUT Right"}, | ||
| 890 | {"Headphone Right", NULL, "Charge Pump"}, | ||
| 891 | {"HPR", NULL, "Headphone Right"}, | ||
| 892 | |||
| 893 | {"MIXOUT Right", NULL, "Out Mixer Right"}, | ||
| 894 | {"Lineout", NULL, "MIXOUT Right"}, | ||
| 895 | {"LINE", NULL, "Lineout"}, | ||
| 896 | }; | ||
| 897 | |||
| 898 | /* Codec private data */ | ||
| 899 | struct da9055_priv { | ||
| 900 | struct regmap *regmap; | ||
| 901 | unsigned int mclk_rate; | ||
| 902 | int master; | ||
| 903 | struct da9055_platform_data *pdata; | ||
| 904 | }; | ||
| 905 | |||
| 906 | static struct reg_default da9055_reg_defaults[] = { | ||
| 907 | { 0x21, 0x10 }, | ||
| 908 | { 0x22, 0x0A }, | ||
| 909 | { 0x23, 0x00 }, | ||
| 910 | { 0x24, 0x00 }, | ||
| 911 | { 0x25, 0x00 }, | ||
| 912 | { 0x26, 0x00 }, | ||
| 913 | { 0x27, 0x0C }, | ||
| 914 | { 0x28, 0x01 }, | ||
| 915 | { 0x29, 0x08 }, | ||
| 916 | { 0x2A, 0x32 }, | ||
| 917 | { 0x2B, 0x00 }, | ||
| 918 | { 0x30, 0x35 }, | ||
| 919 | { 0x31, 0x35 }, | ||
| 920 | { 0x32, 0x00 }, | ||
| 921 | { 0x33, 0x00 }, | ||
| 922 | { 0x34, 0x03 }, | ||
| 923 | { 0x35, 0x03 }, | ||
| 924 | { 0x36, 0x6F }, | ||
| 925 | { 0x37, 0x6F }, | ||
| 926 | { 0x38, 0x80 }, | ||
| 927 | { 0x39, 0x01 }, | ||
| 928 | { 0x3A, 0x01 }, | ||
| 929 | { 0x40, 0x00 }, | ||
| 930 | { 0x41, 0x88 }, | ||
| 931 | { 0x42, 0x88 }, | ||
| 932 | { 0x43, 0x08 }, | ||
| 933 | { 0x44, 0x80 }, | ||
| 934 | { 0x45, 0x6F }, | ||
| 935 | { 0x46, 0x6F }, | ||
| 936 | { 0x47, 0x61 }, | ||
| 937 | { 0x48, 0x35 }, | ||
| 938 | { 0x49, 0x35 }, | ||
| 939 | { 0x4A, 0x35 }, | ||
| 940 | { 0x4B, 0x00 }, | ||
| 941 | { 0x4C, 0x00 }, | ||
| 942 | { 0x60, 0x44 }, | ||
| 943 | { 0x61, 0x44 }, | ||
| 944 | { 0x62, 0x00 }, | ||
| 945 | { 0x63, 0x40 }, | ||
| 946 | { 0x64, 0x40 }, | ||
| 947 | { 0x65, 0x40 }, | ||
| 948 | { 0x66, 0x40 }, | ||
| 949 | { 0x67, 0x40 }, | ||
| 950 | { 0x68, 0x40 }, | ||
| 951 | { 0x69, 0x48 }, | ||
| 952 | { 0x6A, 0x40 }, | ||
| 953 | { 0x6B, 0x41 }, | ||
| 954 | { 0x6C, 0x40 }, | ||
| 955 | { 0x6D, 0x40 }, | ||
| 956 | { 0x6E, 0x10 }, | ||
| 957 | { 0x6F, 0x10 }, | ||
| 958 | { 0x90, 0x80 }, | ||
| 959 | { 0x92, 0x02 }, | ||
| 960 | { 0x93, 0x00 }, | ||
| 961 | { 0x99, 0x00 }, | ||
| 962 | { 0x9A, 0x00 }, | ||
| 963 | { 0x9B, 0x00 }, | ||
| 964 | { 0x9C, 0x3F }, | ||
| 965 | { 0x9D, 0x00 }, | ||
| 966 | { 0x9E, 0x3F }, | ||
| 967 | { 0x9F, 0xFF }, | ||
| 968 | { 0xA0, 0x71 }, | ||
| 969 | { 0xA1, 0x00 }, | ||
| 970 | { 0xA2, 0x00 }, | ||
| 971 | { 0xA6, 0x00 }, | ||
| 972 | { 0xA7, 0x00 }, | ||
| 973 | { 0xAB, 0x00 }, | ||
| 974 | { 0xAC, 0x00 }, | ||
| 975 | { 0xAD, 0x00 }, | ||
| 976 | { 0xAF, 0x08 }, | ||
| 977 | { 0xB0, 0x00 }, | ||
| 978 | { 0xB1, 0x00 }, | ||
| 979 | { 0xB2, 0x00 }, | ||
| 980 | }; | ||
| 981 | |||
| 982 | static bool da9055_volatile_register(struct device *dev, | ||
| 983 | unsigned int reg) | ||
| 984 | { | ||
| 985 | switch (reg) { | ||
| 986 | case DA9055_STATUS1: | ||
| 987 | case DA9055_PLL_STATUS: | ||
| 988 | case DA9055_AUX_L_GAIN_STATUS: | ||
| 989 | case DA9055_AUX_R_GAIN_STATUS: | ||
| 990 | case DA9055_MIC_L_GAIN_STATUS: | ||
| 991 | case DA9055_MIC_R_GAIN_STATUS: | ||
| 992 | case DA9055_MIXIN_L_GAIN_STATUS: | ||
| 993 | case DA9055_MIXIN_R_GAIN_STATUS: | ||
| 994 | case DA9055_ADC_L_GAIN_STATUS: | ||
| 995 | case DA9055_ADC_R_GAIN_STATUS: | ||
| 996 | case DA9055_DAC_L_GAIN_STATUS: | ||
| 997 | case DA9055_DAC_R_GAIN_STATUS: | ||
| 998 | case DA9055_HP_L_GAIN_STATUS: | ||
| 999 | case DA9055_HP_R_GAIN_STATUS: | ||
| 1000 | case DA9055_LINE_GAIN_STATUS: | ||
| 1001 | case DA9055_ALC_CIC_OP_LVL_DATA: | ||
| 1002 | return 1; | ||
| 1003 | default: | ||
| 1004 | return 0; | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | /* Set DAI word length */ | ||
| 1009 | static int da9055_hw_params(struct snd_pcm_substream *substream, | ||
| 1010 | struct snd_pcm_hw_params *params, | ||
| 1011 | struct snd_soc_dai *dai) | ||
| 1012 | { | ||
| 1013 | struct snd_soc_codec *codec = dai->codec; | ||
| 1014 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1015 | u8 aif_ctrl, fs; | ||
| 1016 | u32 sysclk; | ||
| 1017 | |||
| 1018 | switch (params_format(params)) { | ||
| 1019 | case SNDRV_PCM_FORMAT_S16_LE: | ||
| 1020 | aif_ctrl = DA9055_AIF_WORD_S16_LE; | ||
| 1021 | break; | ||
| 1022 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
| 1023 | aif_ctrl = DA9055_AIF_WORD_S20_3LE; | ||
| 1024 | break; | ||
| 1025 | case SNDRV_PCM_FORMAT_S24_LE: | ||
| 1026 | aif_ctrl = DA9055_AIF_WORD_S24_LE; | ||
| 1027 | break; | ||
| 1028 | case SNDRV_PCM_FORMAT_S32_LE: | ||
| 1029 | aif_ctrl = DA9055_AIF_WORD_S32_LE; | ||
| 1030 | break; | ||
| 1031 | default: | ||
| 1032 | return -EINVAL; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /* Set AIF format */ | ||
| 1036 | snd_soc_update_bits(codec, DA9055_AIF_CTRL, DA9055_AIF_WORD_LENGTH_MASK, | ||
| 1037 | aif_ctrl); | ||
| 1038 | |||
| 1039 | switch (params_rate(params)) { | ||
| 1040 | case 8000: | ||
| 1041 | fs = DA9055_SR_8000; | ||
| 1042 | sysclk = 3072000; | ||
| 1043 | break; | ||
| 1044 | case 11025: | ||
| 1045 | fs = DA9055_SR_11025; | ||
| 1046 | sysclk = 2822400; | ||
| 1047 | break; | ||
| 1048 | case 12000: | ||
| 1049 | fs = DA9055_SR_12000; | ||
| 1050 | sysclk = 3072000; | ||
| 1051 | break; | ||
| 1052 | case 16000: | ||
| 1053 | fs = DA9055_SR_16000; | ||
| 1054 | sysclk = 3072000; | ||
| 1055 | break; | ||
| 1056 | case 22050: | ||
| 1057 | fs = DA9055_SR_22050; | ||
| 1058 | sysclk = 2822400; | ||
| 1059 | break; | ||
| 1060 | case 32000: | ||
| 1061 | fs = DA9055_SR_32000; | ||
| 1062 | sysclk = 3072000; | ||
| 1063 | break; | ||
| 1064 | case 44100: | ||
| 1065 | fs = DA9055_SR_44100; | ||
| 1066 | sysclk = 2822400; | ||
| 1067 | break; | ||
| 1068 | case 48000: | ||
| 1069 | fs = DA9055_SR_48000; | ||
| 1070 | sysclk = 3072000; | ||
| 1071 | break; | ||
| 1072 | case 88200: | ||
| 1073 | fs = DA9055_SR_88200; | ||
| 1074 | sysclk = 2822400; | ||
| 1075 | break; | ||
| 1076 | case 96000: | ||
| 1077 | fs = DA9055_SR_96000; | ||
| 1078 | sysclk = 3072000; | ||
| 1079 | break; | ||
| 1080 | default: | ||
| 1081 | return -EINVAL; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | if (da9055->mclk_rate) { | ||
| 1085 | /* PLL Mode, Write actual FS */ | ||
| 1086 | snd_soc_write(codec, DA9055_SR, fs); | ||
| 1087 | } else { | ||
| 1088 | /* | ||
| 1089 | * Non-PLL Mode | ||
| 1090 | * When PLL is bypassed, chip assumes constant MCLK of | ||
| 1091 | * 12.288MHz and uses sample rate value to divide this MCLK | ||
| 1092 | * to derive its sys clk. As sys clk has to be 256 * Fs, we | ||
| 1093 | * need to write constant sample rate i.e. 48KHz. | ||
| 1094 | */ | ||
| 1095 | snd_soc_write(codec, DA9055_SR, DA9055_SR_48000); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (da9055->mclk_rate && (da9055->mclk_rate != sysclk)) { | ||
| 1099 | /* PLL Mode */ | ||
| 1100 | if (!da9055->master) { | ||
| 1101 | /* PLL slave mode, enable PLL and also SRM */ | ||
| 1102 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, | ||
| 1103 | DA9055_PLL_EN | DA9055_PLL_SRM_EN, | ||
| 1104 | DA9055_PLL_EN | DA9055_PLL_SRM_EN); | ||
| 1105 | } else { | ||
| 1106 | /* PLL master mode, only enable PLL */ | ||
| 1107 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, | ||
| 1108 | DA9055_PLL_EN, DA9055_PLL_EN); | ||
| 1109 | } | ||
| 1110 | } else { | ||
| 1111 | /* Non PLL Mode, disable PLL */ | ||
| 1112 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, DA9055_PLL_EN, 0); | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | return 0; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /* Set DAI mode and Format */ | ||
| 1119 | static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
| 1120 | { | ||
| 1121 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 1122 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1123 | u8 aif_clk_mode, aif_ctrl, mode; | ||
| 1124 | |||
| 1125 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
| 1126 | case SND_SOC_DAIFMT_CBM_CFM: | ||
| 1127 | /* DA9055 in I2S Master Mode */ | ||
| 1128 | mode = 1; | ||
| 1129 | aif_clk_mode = DA9055_AIF_CLK_EN_MASTER_MODE; | ||
| 1130 | break; | ||
| 1131 | case SND_SOC_DAIFMT_CBS_CFS: | ||
| 1132 | /* DA9055 in I2S Slave Mode */ | ||
| 1133 | mode = 0; | ||
| 1134 | aif_clk_mode = DA9055_AIF_CLK_EN_SLAVE_MODE; | ||
| 1135 | break; | ||
| 1136 | default: | ||
| 1137 | return -EINVAL; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | /* Don't allow change of mode if PLL is enabled */ | ||
| 1141 | if ((snd_soc_read(codec, DA9055_PLL_CTRL) & DA9055_PLL_EN) && | ||
| 1142 | (da9055->master != mode)) | ||
| 1143 | return -EINVAL; | ||
| 1144 | |||
| 1145 | da9055->master = mode; | ||
| 1146 | |||
| 1147 | /* Only I2S is supported */ | ||
| 1148 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 1149 | case SND_SOC_DAIFMT_I2S: | ||
| 1150 | aif_ctrl = DA9055_AIF_FORMAT_I2S_MODE; | ||
| 1151 | break; | ||
| 1152 | case SND_SOC_DAIFMT_LEFT_J: | ||
| 1153 | aif_ctrl = DA9055_AIF_FORMAT_LEFT_J; | ||
| 1154 | break; | ||
| 1155 | case SND_SOC_DAIFMT_RIGHT_J: | ||
| 1156 | aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J; | ||
| 1157 | break; | ||
| 1158 | default: | ||
| 1159 | return -EINVAL; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | /* By default only 32 BCLK per WCLK is supported */ | ||
| 1163 | aif_clk_mode |= DA9055_AIF_BCLKS_PER_WCLK_32; | ||
| 1164 | |||
| 1165 | snd_soc_update_bits(codec, DA9055_AIF_CLK_MODE, | ||
| 1166 | (DA9055_AIF_CLK_MODE_MASK | DA9055_AIF_BCLK_MASK), | ||
| 1167 | aif_clk_mode); | ||
| 1168 | snd_soc_update_bits(codec, DA9055_AIF_CTRL, DA9055_AIF_FORMAT_MASK, | ||
| 1169 | aif_ctrl); | ||
| 1170 | return 0; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static int da9055_mute(struct snd_soc_dai *dai, int mute) | ||
| 1174 | { | ||
| 1175 | struct snd_soc_codec *codec = dai->codec; | ||
| 1176 | |||
| 1177 | if (mute) { | ||
| 1178 | snd_soc_update_bits(codec, DA9055_DAC_L_CTRL, | ||
| 1179 | DA9055_DAC_L_MUTE_EN, DA9055_DAC_L_MUTE_EN); | ||
| 1180 | snd_soc_update_bits(codec, DA9055_DAC_R_CTRL, | ||
| 1181 | DA9055_DAC_R_MUTE_EN, DA9055_DAC_R_MUTE_EN); | ||
| 1182 | } else { | ||
| 1183 | snd_soc_update_bits(codec, DA9055_DAC_L_CTRL, | ||
| 1184 | DA9055_DAC_L_MUTE_EN, 0); | ||
| 1185 | snd_soc_update_bits(codec, DA9055_DAC_R_CTRL, | ||
| 1186 | DA9055_DAC_R_MUTE_EN, 0); | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | return 0; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | #define DA9055_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
| 1193 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 1194 | |||
| 1195 | static int da9055_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
| 1196 | int clk_id, unsigned int freq, int dir) | ||
| 1197 | { | ||
| 1198 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 1199 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1200 | |||
| 1201 | switch (clk_id) { | ||
| 1202 | case DA9055_CLKSRC_MCLK: | ||
| 1203 | switch (freq) { | ||
| 1204 | case 11289600: | ||
| 1205 | case 12000000: | ||
| 1206 | case 12288000: | ||
| 1207 | case 13000000: | ||
| 1208 | case 13500000: | ||
| 1209 | case 14400000: | ||
| 1210 | case 19200000: | ||
| 1211 | case 19680000: | ||
| 1212 | case 19800000: | ||
| 1213 | da9055->mclk_rate = freq; | ||
| 1214 | return 0; | ||
| 1215 | default: | ||
| 1216 | dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", | ||
| 1217 | freq); | ||
| 1218 | return -EINVAL; | ||
| 1219 | } | ||
| 1220 | break; | ||
| 1221 | default: | ||
| 1222 | dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); | ||
| 1223 | return -EINVAL; | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | /* | ||
| 1228 | * da9055_set_dai_pll : Configure the codec PLL | ||
| 1229 | * @param codec_dai : Pointer to codec DAI | ||
| 1230 | * @param pll_id : da9055 has only one pll, so pll_id is always zero | ||
| 1231 | * @param fref : Input MCLK frequency | ||
| 1232 | * @param fout : FsDM value | ||
| 1233 | * @return int : Zero for success, negative error code for error | ||
| 1234 | * | ||
| 1235 | * Note: Supported PLL input frequencies are 11.2896MHz, 12MHz, 12.288MHz, | ||
| 1236 | * 13MHz, 13.5MHz, 14.4MHz, 19.2MHz, 19.6MHz and 19.8MHz | ||
| 1237 | */ | ||
| 1238 | static int da9055_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
| 1239 | int source, unsigned int fref, unsigned int fout) | ||
| 1240 | { | ||
| 1241 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 1242 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1243 | |||
| 1244 | u8 pll_frac_top, pll_frac_bot, pll_integer, cnt; | ||
| 1245 | |||
| 1246 | /* Disable PLL before setting the divisors */ | ||
| 1247 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, DA9055_PLL_EN, 0); | ||
| 1248 | |||
| 1249 | /* In slave mode, there is only one set of divisors */ | ||
| 1250 | if (!da9055->master && (fout != 2822400)) | ||
| 1251 | goto pll_err; | ||
| 1252 | |||
| 1253 | /* Search pll div array for correct divisors */ | ||
| 1254 | for (cnt = 0; cnt < ARRAY_SIZE(da9055_pll_div); cnt++) { | ||
| 1255 | /* Check fref, mode and fout */ | ||
| 1256 | if ((fref == da9055_pll_div[cnt].fref) && | ||
| 1257 | (da9055->master == da9055_pll_div[cnt].mode) && | ||
| 1258 | (fout == da9055_pll_div[cnt].fout)) { | ||
| 1259 | /* All match, pick up divisors */ | ||
| 1260 | pll_frac_top = da9055_pll_div[cnt].frac_top; | ||
| 1261 | pll_frac_bot = da9055_pll_div[cnt].frac_bot; | ||
| 1262 | pll_integer = da9055_pll_div[cnt].integer; | ||
| 1263 | break; | ||
| 1264 | } | ||
| 1265 | } | ||
| 1266 | if (cnt >= ARRAY_SIZE(da9055_pll_div)) | ||
| 1267 | goto pll_err; | ||
| 1268 | |||
| 1269 | /* Write PLL dividers */ | ||
| 1270 | snd_soc_write(codec, DA9055_PLL_FRAC_TOP, pll_frac_top); | ||
| 1271 | snd_soc_write(codec, DA9055_PLL_FRAC_BOT, pll_frac_bot); | ||
| 1272 | snd_soc_write(codec, DA9055_PLL_INTEGER, pll_integer); | ||
| 1273 | |||
| 1274 | return 0; | ||
| 1275 | pll_err: | ||
| 1276 | dev_err(codec_dai->dev, "Error in setting up PLL\n"); | ||
| 1277 | return -EINVAL; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | /* DAI operations */ | ||
| 1281 | static const struct snd_soc_dai_ops da9055_dai_ops = { | ||
| 1282 | .hw_params = da9055_hw_params, | ||
| 1283 | .set_fmt = da9055_set_dai_fmt, | ||
| 1284 | .set_sysclk = da9055_set_dai_sysclk, | ||
| 1285 | .set_pll = da9055_set_dai_pll, | ||
| 1286 | .digital_mute = da9055_mute, | ||
| 1287 | }; | ||
| 1288 | |||
| 1289 | static struct snd_soc_dai_driver da9055_dai = { | ||
| 1290 | .name = "da9055-hifi", | ||
| 1291 | /* Playback Capabilities */ | ||
| 1292 | .playback = { | ||
| 1293 | .stream_name = "Playback", | ||
| 1294 | .channels_min = 1, | ||
| 1295 | .channels_max = 2, | ||
| 1296 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
| 1297 | .formats = DA9055_FORMATS, | ||
| 1298 | }, | ||
| 1299 | /* Capture Capabilities */ | ||
| 1300 | .capture = { | ||
| 1301 | .stream_name = "Capture", | ||
| 1302 | .channels_min = 1, | ||
| 1303 | .channels_max = 2, | ||
| 1304 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
| 1305 | .formats = DA9055_FORMATS, | ||
| 1306 | }, | ||
| 1307 | .ops = &da9055_dai_ops, | ||
| 1308 | .symmetric_rates = 1, | ||
| 1309 | }; | ||
| 1310 | |||
| 1311 | static int da9055_set_bias_level(struct snd_soc_codec *codec, | ||
| 1312 | enum snd_soc_bias_level level) | ||
| 1313 | { | ||
| 1314 | switch (level) { | ||
| 1315 | case SND_SOC_BIAS_ON: | ||
| 1316 | case SND_SOC_BIAS_PREPARE: | ||
| 1317 | break; | ||
| 1318 | case SND_SOC_BIAS_STANDBY: | ||
| 1319 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
| 1320 | /* Enable VMID reference & master bias */ | ||
| 1321 | snd_soc_update_bits(codec, DA9055_REFERENCES, | ||
| 1322 | DA9055_VMID_EN | DA9055_BIAS_EN, | ||
| 1323 | DA9055_VMID_EN | DA9055_BIAS_EN); | ||
| 1324 | } | ||
| 1325 | break; | ||
| 1326 | case SND_SOC_BIAS_OFF: | ||
| 1327 | /* Disable VMID reference & master bias */ | ||
| 1328 | snd_soc_update_bits(codec, DA9055_REFERENCES, | ||
| 1329 | DA9055_VMID_EN | DA9055_BIAS_EN, 0); | ||
| 1330 | break; | ||
| 1331 | } | ||
| 1332 | codec->dapm.bias_level = level; | ||
| 1333 | return 0; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | static int da9055_probe(struct snd_soc_codec *codec) | ||
| 1337 | { | ||
| 1338 | int ret; | ||
| 1339 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1340 | |||
| 1341 | codec->control_data = da9055->regmap; | ||
| 1342 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
| 1343 | if (ret < 0) { | ||
| 1344 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
| 1345 | return ret; | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | /* Enable all Gain Ramps */ | ||
| 1349 | snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, | ||
| 1350 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1351 | snd_soc_update_bits(codec, DA9055_AUX_R_CTRL, | ||
| 1352 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1353 | snd_soc_update_bits(codec, DA9055_MIXIN_L_CTRL, | ||
| 1354 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1355 | snd_soc_update_bits(codec, DA9055_MIXIN_R_CTRL, | ||
| 1356 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1357 | snd_soc_update_bits(codec, DA9055_ADC_L_CTRL, | ||
| 1358 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1359 | snd_soc_update_bits(codec, DA9055_ADC_R_CTRL, | ||
| 1360 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1361 | snd_soc_update_bits(codec, DA9055_DAC_L_CTRL, | ||
| 1362 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1363 | snd_soc_update_bits(codec, DA9055_DAC_R_CTRL, | ||
| 1364 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1365 | snd_soc_update_bits(codec, DA9055_HP_L_CTRL, | ||
| 1366 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1367 | snd_soc_update_bits(codec, DA9055_HP_R_CTRL, | ||
| 1368 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1369 | snd_soc_update_bits(codec, DA9055_LINE_CTRL, | ||
| 1370 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1371 | |||
| 1372 | /* | ||
| 1373 | * There are two separate control bits for input and output mixers as | ||
| 1374 | * well as headphone and line outs. | ||
| 1375 | * One to enable corresponding amplifier and other to enable its | ||
| 1376 | * output. As amplifier bits are related to power control, they are | ||
| 1377 | * being managed by DAPM while other (non power related) bits are | ||
| 1378 | * enabled here | ||
| 1379 | */ | ||
| 1380 | snd_soc_update_bits(codec, DA9055_MIXIN_L_CTRL, | ||
| 1381 | DA9055_MIXIN_L_MIX_EN, DA9055_MIXIN_L_MIX_EN); | ||
| 1382 | snd_soc_update_bits(codec, DA9055_MIXIN_R_CTRL, | ||
| 1383 | DA9055_MIXIN_R_MIX_EN, DA9055_MIXIN_R_MIX_EN); | ||
| 1384 | |||
| 1385 | snd_soc_update_bits(codec, DA9055_MIXOUT_L_CTRL, | ||
| 1386 | DA9055_MIXOUT_L_MIX_EN, DA9055_MIXOUT_L_MIX_EN); | ||
| 1387 | snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL, | ||
| 1388 | DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN); | ||
| 1389 | |||
| 1390 | snd_soc_update_bits(codec, DA9055_HP_L_CTRL, | ||
| 1391 | DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE); | ||
| 1392 | snd_soc_update_bits(codec, DA9055_HP_R_CTRL, | ||
| 1393 | DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE); | ||
| 1394 | |||
| 1395 | snd_soc_update_bits(codec, DA9055_LINE_CTRL, | ||
| 1396 | DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE); | ||
| 1397 | |||
| 1398 | /* Set this as per your system configuration */ | ||
| 1399 | snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ); | ||
| 1400 | |||
| 1401 | /* Set platform data values */ | ||
| 1402 | if (da9055->pdata) { | ||
| 1403 | /* set mic bias source */ | ||
| 1404 | if (da9055->pdata->micbias_source) { | ||
| 1405 | snd_soc_update_bits(codec, DA9055_MIXIN_R_SELECT, | ||
| 1406 | DA9055_MICBIAS2_EN, | ||
| 1407 | DA9055_MICBIAS2_EN); | ||
| 1408 | } else { | ||
| 1409 | snd_soc_update_bits(codec, DA9055_MIXIN_R_SELECT, | ||
| 1410 | DA9055_MICBIAS2_EN, 0); | ||
| 1411 | } | ||
| 1412 | /* set mic bias voltage */ | ||
| 1413 | switch (da9055->pdata->micbias) { | ||
| 1414 | case DA9055_MICBIAS_2_2V: | ||
| 1415 | case DA9055_MICBIAS_2_1V: | ||
| 1416 | case DA9055_MICBIAS_1_8V: | ||
| 1417 | case DA9055_MICBIAS_1_6V: | ||
| 1418 | snd_soc_update_bits(codec, DA9055_MIC_CONFIG, | ||
| 1419 | DA9055_MICBIAS_LEVEL_MASK, | ||
| 1420 | (da9055->pdata->micbias) << 4); | ||
| 1421 | break; | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | return 0; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | static struct snd_soc_codec_driver soc_codec_dev_da9055 = { | ||
| 1428 | .probe = da9055_probe, | ||
| 1429 | .set_bias_level = da9055_set_bias_level, | ||
| 1430 | |||
| 1431 | .controls = da9055_snd_controls, | ||
| 1432 | .num_controls = ARRAY_SIZE(da9055_snd_controls), | ||
| 1433 | |||
| 1434 | .dapm_widgets = da9055_dapm_widgets, | ||
| 1435 | .num_dapm_widgets = ARRAY_SIZE(da9055_dapm_widgets), | ||
| 1436 | .dapm_routes = da9055_audio_map, | ||
| 1437 | .num_dapm_routes = ARRAY_SIZE(da9055_audio_map), | ||
| 1438 | }; | ||
| 1439 | |||
| 1440 | static const struct regmap_config da9055_regmap_config = { | ||
| 1441 | .reg_bits = 8, | ||
| 1442 | .val_bits = 8, | ||
| 1443 | |||
| 1444 | .reg_defaults = da9055_reg_defaults, | ||
| 1445 | .num_reg_defaults = ARRAY_SIZE(da9055_reg_defaults), | ||
| 1446 | .volatile_reg = da9055_volatile_register, | ||
| 1447 | .cache_type = REGCACHE_RBTREE, | ||
| 1448 | }; | ||
| 1449 | |||
| 1450 | static int __devinit da9055_i2c_probe(struct i2c_client *i2c, | ||
| 1451 | const struct i2c_device_id *id) | ||
| 1452 | { | ||
| 1453 | struct da9055_priv *da9055; | ||
| 1454 | struct da9055_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
| 1455 | int ret; | ||
| 1456 | |||
| 1457 | da9055 = devm_kzalloc(&i2c->dev, sizeof(struct da9055_priv), | ||
| 1458 | GFP_KERNEL); | ||
| 1459 | if (!da9055) | ||
| 1460 | return -ENOMEM; | ||
| 1461 | |||
| 1462 | if (pdata) | ||
| 1463 | da9055->pdata = pdata; | ||
| 1464 | |||
| 1465 | i2c_set_clientdata(i2c, da9055); | ||
| 1466 | |||
| 1467 | da9055->regmap = devm_regmap_init_i2c(i2c, &da9055_regmap_config); | ||
| 1468 | if (IS_ERR(da9055->regmap)) { | ||
| 1469 | ret = PTR_ERR(da9055->regmap); | ||
| 1470 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | ||
| 1471 | return ret; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | ret = snd_soc_register_codec(&i2c->dev, | ||
| 1475 | &soc_codec_dev_da9055, &da9055_dai, 1); | ||
| 1476 | if (ret < 0) { | ||
| 1477 | dev_err(&i2c->dev, "Failed to register da9055 codec: %d\n", | ||
| 1478 | ret); | ||
| 1479 | } | ||
| 1480 | return ret; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | static int __devexit da9055_remove(struct i2c_client *client) | ||
| 1484 | { | ||
| 1485 | snd_soc_unregister_codec(&client->dev); | ||
| 1486 | return 0; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static const struct i2c_device_id da9055_i2c_id[] = { | ||
| 1490 | { "da9055", 0 }, | ||
| 1491 | { } | ||
| 1492 | }; | ||
| 1493 | MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); | ||
| 1494 | |||
| 1495 | /* I2C codec control layer */ | ||
| 1496 | static struct i2c_driver da9055_i2c_driver = { | ||
| 1497 | .driver = { | ||
| 1498 | .name = "da9055", | ||
| 1499 | .owner = THIS_MODULE, | ||
| 1500 | }, | ||
| 1501 | .probe = da9055_i2c_probe, | ||
| 1502 | .remove = __devexit_p(da9055_remove), | ||
| 1503 | .id_table = da9055_i2c_id, | ||
| 1504 | }; | ||
| 1505 | |||
| 1506 | module_i2c_driver(da9055_i2c_driver); | ||
| 1507 | |||
| 1508 | MODULE_DESCRIPTION("ASoC DA9055 Codec driver"); | ||
| 1509 | MODULE_AUTHOR("David Chen, Ashish Chavan"); | ||
| 1510 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index f8d6c31db870..99afc003a084 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
| @@ -168,7 +168,8 @@ static void wm0010_halt(struct snd_soc_codec *codec) | |||
| 168 | case WM0010_STAGE2: | 168 | case WM0010_STAGE2: |
| 169 | case WM0010_FIRMWARE: | 169 | case WM0010_FIRMWARE: |
| 170 | /* Remember to put chip back into reset */ | 170 | /* Remember to put chip back into reset */ |
| 171 | gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); | 171 | gpio_set_value_cansleep(wm0010->gpio_reset, |
| 172 | wm0010->gpio_reset_value); | ||
| 172 | /* Disable the regulators */ | 173 | /* Disable the regulators */ |
| 173 | regulator_disable(wm0010->dbvdd); | 174 | regulator_disable(wm0010->dbvdd); |
| 174 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | 175 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), |
| @@ -387,7 +388,7 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
| 387 | } | 388 | } |
| 388 | 389 | ||
| 389 | /* Release reset */ | 390 | /* Release reset */ |
| 390 | gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value); | 391 | gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value); |
| 391 | spin_lock_irqsave(&wm0010->irq_lock, flags); | 392 | spin_lock_irqsave(&wm0010->irq_lock, flags); |
| 392 | wm0010->state = WM0010_OUT_OF_RESET; | 393 | wm0010->state = WM0010_OUT_OF_RESET; |
| 393 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | 394 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); |
| @@ -809,7 +810,6 @@ static int wm0010_probe(struct snd_soc_codec *codec) | |||
| 809 | 810 | ||
| 810 | static int __devinit wm0010_spi_probe(struct spi_device *spi) | 811 | static int __devinit wm0010_spi_probe(struct spi_device *spi) |
| 811 | { | 812 | { |
| 812 | unsigned long flags; | ||
| 813 | unsigned long gpio_flags; | 813 | unsigned long gpio_flags; |
| 814 | int ret; | 814 | int ret; |
| 815 | int trigger; | 815 | int trigger; |
| @@ -876,6 +876,8 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi) | |||
| 876 | return -EINVAL; | 876 | return -EINVAL; |
| 877 | } | 877 | } |
| 878 | 878 | ||
| 879 | wm0010->state = WM0010_POWER_OFF; | ||
| 880 | |||
| 879 | irq = spi->irq; | 881 | irq = spi->irq; |
| 880 | if (wm0010->pdata.irq_flags) | 882 | if (wm0010->pdata.irq_flags) |
| 881 | trigger = wm0010->pdata.irq_flags; | 883 | trigger = wm0010->pdata.irq_flags; |
| @@ -897,10 +899,6 @@ static int __devinit wm0010_spi_probe(struct spi_device *spi) | |||
| 897 | else | 899 | else |
| 898 | wm0010->board_max_spi_speed = 0; | 900 | wm0010->board_max_spi_speed = 0; |
| 899 | 901 | ||
| 900 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 901 | wm0010->state = WM0010_POWER_OFF; | ||
| 902 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 903 | |||
| 904 | ret = snd_soc_register_codec(&spi->dev, | 902 | ret = snd_soc_register_codec(&spi->dev, |
| 905 | &soc_codec_dev_wm0010, wm0010_dai, | 903 | &soc_codec_dev_wm0010, wm0010_dai, |
| 906 | ARRAY_SIZE(wm0010_dai)); | 904 | ARRAY_SIZE(wm0010_dai)); |
| @@ -916,10 +914,8 @@ static int __devexit wm0010_spi_remove(struct spi_device *spi) | |||
| 916 | 914 | ||
| 917 | snd_soc_unregister_codec(&spi->dev); | 915 | snd_soc_unregister_codec(&spi->dev); |
| 918 | 916 | ||
| 919 | if (wm0010->gpio_reset) { | 917 | gpio_set_value_cansleep(wm0010->gpio_reset, |
| 920 | /* Remember to put chip back into reset */ | 918 | wm0010->gpio_reset_value); |
| 921 | gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); | ||
| 922 | } | ||
| 923 | 919 | ||
| 924 | if (wm0010->irq) | 920 | if (wm0010->irq) |
| 925 | free_irq(wm0010->irq, wm0010); | 921 | free_irq(wm0010->irq, wm0010); |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 89cd6fcad015..b723e910fcdc 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
| 32 | #include <linux/regmap.h> | 32 | #include <linux/regmap.h> |
| 33 | #include <linux/debugfs.h> | 33 | #include <linux/debugfs.h> |
| 34 | #include <linux/regulator/consumer.h> | ||
| 34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 35 | #include <sound/core.h> | 36 | #include <sound/core.h> |
| 36 | #include <sound/pcm.h> | 37 | #include <sound/pcm.h> |
| @@ -43,6 +44,14 @@ | |||
| 43 | 44 | ||
| 44 | #include "wm2000.h" | 45 | #include "wm2000.h" |
| 45 | 46 | ||
| 47 | #define WM2000_NUM_SUPPLIES 3 | ||
| 48 | |||
| 49 | static const char *wm2000_supplies[WM2000_NUM_SUPPLIES] = { | ||
| 50 | "SPKVDD", | ||
| 51 | "DBVDD", | ||
| 52 | "DCVDD", | ||
| 53 | }; | ||
| 54 | |||
| 46 | enum wm2000_anc_mode { | 55 | enum wm2000_anc_mode { |
| 47 | ANC_ACTIVE = 0, | 56 | ANC_ACTIVE = 0, |
| 48 | ANC_BYPASS = 1, | 57 | ANC_BYPASS = 1, |
| @@ -54,6 +63,8 @@ struct wm2000_priv { | |||
| 54 | struct i2c_client *i2c; | 63 | struct i2c_client *i2c; |
| 55 | struct regmap *regmap; | 64 | struct regmap *regmap; |
| 56 | 65 | ||
| 66 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; | ||
| 67 | |||
| 57 | enum wm2000_anc_mode anc_mode; | 68 | enum wm2000_anc_mode anc_mode; |
| 58 | 69 | ||
| 59 | unsigned int anc_active:1; | 70 | unsigned int anc_active:1; |
| @@ -126,6 +137,12 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 126 | 137 | ||
| 127 | dev_dbg(&i2c->dev, "Beginning power up\n"); | 138 | dev_dbg(&i2c->dev, "Beginning power up\n"); |
| 128 | 139 | ||
| 140 | ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 141 | if (ret != 0) { | ||
| 142 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 129 | if (!wm2000->mclk_div) { | 146 | if (!wm2000->mclk_div) { |
| 130 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); | 147 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); |
| 131 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, | 148 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, |
| @@ -143,12 +160,14 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 143 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, | 160 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, |
| 144 | WM2000_ANC_ENG_IDLE)) { | 161 | WM2000_ANC_ENG_IDLE)) { |
| 145 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); | 162 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); |
| 163 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 146 | return -ETIMEDOUT; | 164 | return -ETIMEDOUT; |
| 147 | } | 165 | } |
| 148 | 166 | ||
| 149 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | 167 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, |
| 150 | WM2000_STATUS_BOOT_COMPLETE)) { | 168 | WM2000_STATUS_BOOT_COMPLETE)) { |
| 151 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); | 169 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); |
| 170 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 152 | return -ETIMEDOUT; | 171 | return -ETIMEDOUT; |
| 153 | } | 172 | } |
| 154 | 173 | ||
| @@ -163,11 +182,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 163 | wm2000->anc_download_size); | 182 | wm2000->anc_download_size); |
| 164 | if (ret < 0) { | 183 | if (ret < 0) { |
| 165 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); | 184 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); |
| 185 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 166 | return ret; | 186 | return ret; |
| 167 | } | 187 | } |
| 168 | if (ret != wm2000->anc_download_size) { | 188 | if (ret != wm2000->anc_download_size) { |
| 169 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", | 189 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", |
| 170 | ret, wm2000->anc_download_size); | 190 | ret, wm2000->anc_download_size); |
| 191 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 171 | return -EIO; | 192 | return -EIO; |
| 172 | } | 193 | } |
| 173 | 194 | ||
| @@ -201,6 +222,7 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 201 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | 222 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, |
| 202 | WM2000_STATUS_MOUSE_ACTIVE)) { | 223 | WM2000_STATUS_MOUSE_ACTIVE)) { |
| 203 | dev_err(&i2c->dev, "Timed out waiting for device\n"); | 224 | dev_err(&i2c->dev, "Timed out waiting for device\n"); |
| 225 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 204 | return -ETIMEDOUT; | 226 | return -ETIMEDOUT; |
| 205 | } | 227 | } |
| 206 | 228 | ||
| @@ -238,6 +260,8 @@ static int wm2000_power_down(struct i2c_client *i2c, int analogue) | |||
| 238 | return -ETIMEDOUT; | 260 | return -ETIMEDOUT; |
| 239 | } | 261 | } |
| 240 | 262 | ||
| 263 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 264 | |||
| 241 | dev_dbg(&i2c->dev, "powered off\n"); | 265 | dev_dbg(&i2c->dev, "powered off\n"); |
| 242 | wm2000->anc_mode = ANC_OFF; | 266 | wm2000->anc_mode = ANC_OFF; |
| 243 | 267 | ||
| @@ -747,7 +771,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 747 | struct wm2000_platform_data *pdata; | 771 | struct wm2000_platform_data *pdata; |
| 748 | const char *filename; | 772 | const char *filename; |
| 749 | const struct firmware *fw = NULL; | 773 | const struct firmware *fw = NULL; |
| 750 | int ret; | 774 | int ret, i; |
| 751 | int reg; | 775 | int reg; |
| 752 | u16 id; | 776 | u16 id; |
| 753 | 777 | ||
| @@ -760,7 +784,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 760 | 784 | ||
| 761 | dev_set_drvdata(&i2c->dev, wm2000); | 785 | dev_set_drvdata(&i2c->dev, wm2000); |
| 762 | 786 | ||
| 763 | wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap); | 787 | wm2000->regmap = devm_regmap_init_i2c(i2c, &wm2000_regmap); |
| 764 | if (IS_ERR(wm2000->regmap)) { | 788 | if (IS_ERR(wm2000->regmap)) { |
| 765 | ret = PTR_ERR(wm2000->regmap); | 789 | ret = PTR_ERR(wm2000->regmap); |
| 766 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 790 | 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, | |||
| 768 | goto out; | 792 | goto out; |
| 769 | } | 793 | } |
| 770 | 794 | ||
| 795 | for (i = 0; i < WM2000_NUM_SUPPLIES; i++) | ||
| 796 | wm2000->supplies[i].supply = wm2000_supplies[i]; | ||
| 797 | |||
| 798 | ret = devm_regulator_bulk_get(&i2c->dev, WM2000_NUM_SUPPLIES, | ||
| 799 | wm2000->supplies); | ||
| 800 | if (ret != 0) { | ||
| 801 | dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret); | ||
| 802 | return ret; | ||
| 803 | } | ||
| 804 | |||
| 805 | ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 806 | if (ret != 0) { | ||
| 807 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
| 808 | return ret; | ||
| 809 | } | ||
| 810 | |||
| 771 | /* Verify that this is a WM2000 */ | 811 | /* Verify that this is a WM2000 */ |
| 772 | reg = wm2000_read(i2c, WM2000_REG_ID1); | 812 | reg = wm2000_read(i2c, WM2000_REG_ID1); |
| 773 | id = reg << 8; | 813 | id = reg << 8; |
| @@ -777,7 +817,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 777 | if (id != 0x2000) { | 817 | if (id != 0x2000) { |
| 778 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); | 818 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); |
| 779 | ret = -ENODEV; | 819 | ret = -ENODEV; |
| 780 | goto out_regmap_exit; | 820 | goto err_supplies; |
| 781 | } | 821 | } |
| 782 | 822 | ||
| 783 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | 823 | reg = wm2000_read(i2c, WM2000_REG_REVISON); |
| @@ -796,7 +836,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 796 | ret = request_firmware(&fw, filename, &i2c->dev); | 836 | ret = request_firmware(&fw, filename, &i2c->dev); |
| 797 | if (ret != 0) { | 837 | if (ret != 0) { |
| 798 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); | 838 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); |
| 799 | goto out_regmap_exit; | 839 | goto err_supplies; |
| 800 | } | 840 | } |
| 801 | 841 | ||
| 802 | /* Pre-cook the concatenation of the register address onto the image */ | 842 | /* 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, | |||
| 807 | if (wm2000->anc_download == NULL) { | 847 | if (wm2000->anc_download == NULL) { |
| 808 | dev_err(&i2c->dev, "Out of memory\n"); | 848 | dev_err(&i2c->dev, "Out of memory\n"); |
| 809 | ret = -ENOMEM; | 849 | ret = -ENOMEM; |
| 810 | goto out_regmap_exit; | 850 | goto err_supplies; |
| 811 | } | 851 | } |
| 812 | 852 | ||
| 813 | wm2000->anc_download[0] = 0x80; | 853 | wm2000->anc_download[0] = 0x80; |
| @@ -822,11 +862,10 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 822 | wm2000_reset(wm2000); | 862 | wm2000_reset(wm2000); |
| 823 | 863 | ||
| 824 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); | 864 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); |
| 825 | if (!ret) | ||
| 826 | goto out; | ||
| 827 | 865 | ||
| 828 | out_regmap_exit: | 866 | err_supplies: |
| 829 | regmap_exit(wm2000->regmap); | 867 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); |
| 868 | |||
| 830 | out: | 869 | out: |
| 831 | release_firmware(fw); | 870 | release_firmware(fw); |
| 832 | return ret; | 871 | return ret; |
| @@ -834,10 +873,7 @@ out: | |||
| 834 | 873 | ||
| 835 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) | 874 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) |
| 836 | { | 875 | { |
| 837 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
| 838 | |||
| 839 | snd_soc_unregister_codec(&i2c->dev); | 876 | snd_soc_unregister_codec(&i2c->dev); |
| 840 | regmap_exit(wm2000->regmap); | ||
| 841 | 877 | ||
| 842 | return 0; | 878 | return 0; |
| 843 | } | 879 | } |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 4a2db4e10885..1722b586bdba 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
| @@ -308,7 +308,7 @@ SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, | |||
| 308 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), | 308 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
| 309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), | 309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
| 310 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | 310 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
| 311 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), | 311 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), |
| 312 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), | 312 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), |
| 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), |
| 314 | 314 | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index bf47914234b3..9211e4192f71 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
| @@ -153,6 +153,15 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |||
| 153 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 153 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
| 154 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | 154 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), |
| 155 | 155 | ||
| 156 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | ||
| 157 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | ||
| 158 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), | ||
| 159 | ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE), | ||
| 160 | ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE), | ||
| 161 | ARIZONA_MIXER_CONTROLS("DSP3R", ARIZONA_DSP3RMIX_INPUT_1_SOURCE), | ||
| 162 | ARIZONA_MIXER_CONTROLS("DSP4L", ARIZONA_DSP4LMIX_INPUT_1_SOURCE), | ||
| 163 | ARIZONA_MIXER_CONTROLS("DSP5R", ARIZONA_DSP4RMIX_INPUT_1_SOURCE), | ||
| 164 | |||
| 156 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | 165 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), |
| 157 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | 166 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), |
| 158 | 167 | ||
| @@ -163,7 +172,8 @@ ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | |||
| 163 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | 172 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), |
| 164 | ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), | 173 | ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), |
| 165 | ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), | 174 | ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), |
| 166 | ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | 175 | ARIZONA_MIXER_CONTROLS("HPOUT3L", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), |
| 176 | ARIZONA_MIXER_CONTROLS("HPOUT3R", ARIZONA_OUT3RMIX_INPUT_1_SOURCE), | ||
| 167 | ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | 177 | ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), |
| 168 | ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | 178 | ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), |
| 169 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | 179 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), |
| @@ -175,7 +185,7 @@ SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | |||
| 175 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), | 185 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), |
| 176 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | 186 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, |
| 177 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), | 187 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), |
| 178 | SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | 188 | SOC_SINGLE("OUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, |
| 179 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), | 189 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), |
| 180 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | 190 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, |
| 181 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | 191 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), |
| @@ -188,8 +198,8 @@ SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |||
| 188 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | 198 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), |
| 189 | SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | 199 | SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, |
| 190 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), | 200 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), |
| 191 | SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | 201 | SOC_DOUBLE_R("OUT3 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, |
| 192 | ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | 202 | ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), |
| 193 | SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | 203 | SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, |
| 194 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | 204 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), |
| 195 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | 205 | 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, | |||
| 203 | SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, | 213 | SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, |
| 204 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, | 214 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, |
| 205 | 0xbf, 0, digital_tlv), | 215 | 0xbf, 0, digital_tlv), |
| 206 | SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | 216 | SOC_DOUBLE_R_TLV("OUT3 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, |
| 207 | ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | 217 | ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_VOL_SHIFT, |
| 218 | 0xbf, 0, digital_tlv), | ||
| 208 | SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | 219 | SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, |
| 209 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, | 220 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, |
| 210 | 0xbf, 0, digital_tlv), | 221 | 0xbf, 0, digital_tlv), |
| @@ -223,8 +234,9 @@ SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | |||
| 223 | ARIZONA_OUTPUT_PATH_CONFIG_2R, | 234 | ARIZONA_OUTPUT_PATH_CONFIG_2R, |
| 224 | ARIZONA_OUT2L_PGA_VOL_SHIFT, | 235 | ARIZONA_OUT2L_PGA_VOL_SHIFT, |
| 225 | 0x34, 0x40, 0, ana_tlv), | 236 | 0x34, 0x40, 0, ana_tlv), |
| 226 | SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | 237 | SOC_DOUBLE_R_RANGE_TLV("OUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, |
| 227 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | 238 | ARIZONA_OUTPUT_PATH_CONFIG_3R, |
| 239 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | ||
| 228 | 240 | ||
| 229 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | 241 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, |
| 230 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | 242 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), |
| @@ -272,7 +284,8 @@ ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | |||
| 272 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | 284 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); |
| 273 | ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); | 285 | ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); |
| 274 | ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); | 286 | ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); |
| 275 | ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | 287 | ARIZONA_MIXER_ENUMS(OUT3L, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); |
| 288 | ARIZONA_MIXER_ENUMS(OUT3R, ARIZONA_OUT3RMIX_INPUT_1_SOURCE); | ||
| 276 | ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | 289 | ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); |
| 277 | ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); | 290 | ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); |
| 278 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | 291 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); |
| @@ -300,6 +313,26 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
| 300 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 313 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
| 301 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 314 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
| 302 | 315 | ||
| 316 | static const char *wm5110_aec_loopback_texts[] = { | ||
| 317 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", | ||
| 318 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", | ||
| 319 | }; | ||
| 320 | |||
| 321 | static const unsigned int wm5110_aec_loopback_values[] = { | ||
| 322 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, | ||
| 323 | }; | ||
| 324 | |||
| 325 | static const struct soc_enum wm5110_aec_loopback = | ||
| 326 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | ||
| 327 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | ||
| 328 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
| 329 | ARRAY_SIZE(wm5110_aec_loopback_texts), | ||
| 330 | wm5110_aec_loopback_texts, | ||
| 331 | wm5110_aec_loopback_values); | ||
| 332 | |||
| 333 | static const struct snd_kcontrol_new wm5110_aec_loopback_mux = | ||
| 334 | SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5110_aec_loopback); | ||
| 335 | |||
| 303 | static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { | 336 | static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { |
| 304 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 337 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
| 305 | 0, NULL, 0), | 338 | 0, NULL, 0), |
| @@ -313,7 +346,7 @@ SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, | |||
| 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), | 346 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
| 314 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), | 347 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
| 315 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | 348 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
| 316 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), | 349 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), |
| 317 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), | 350 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), |
| 318 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | 351 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), |
| 319 | 352 | ||
| @@ -409,6 +442,9 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | |||
| 409 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | 442 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, |
| 410 | NULL, 0), | 443 | NULL, 0), |
| 411 | 444 | ||
| 445 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | ||
| 446 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5110_aec_loopback_mux), | ||
| 447 | |||
| 412 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | 448 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, |
| 413 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | 449 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), |
| 414 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | 450 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, |
| @@ -478,6 +514,9 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | |||
| 478 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | 514 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, |
| 479 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 515 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
| 480 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 516 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
| 517 | SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, | ||
| 518 | ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
| 519 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 481 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | 520 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, |
| 482 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 521 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
| 483 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 522 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
| @@ -522,7 +561,8 @@ ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | |||
| 522 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | 561 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), |
| 523 | ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | 562 | ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), |
| 524 | ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | 563 | ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), |
| 525 | ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | 564 | ARIZONA_MIXER_WIDGETS(OUT3L, "HPOUT3L"), |
| 565 | ARIZONA_MIXER_WIDGETS(OUT3R, "HPOUT3R"), | ||
| 526 | ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | 566 | ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), |
| 527 | ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), | 567 | ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), |
| 528 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | 568 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), |
| @@ -554,8 +594,8 @@ SND_SOC_DAPM_OUTPUT("HPOUT1L"), | |||
| 554 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 594 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
| 555 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | 595 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), |
| 556 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), | 596 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), |
| 557 | SND_SOC_DAPM_OUTPUT("EPOUTN"), | 597 | SND_SOC_DAPM_OUTPUT("HPOUT3L"), |
| 558 | SND_SOC_DAPM_OUTPUT("EPOUTP"), | 598 | SND_SOC_DAPM_OUTPUT("HPOUT3R"), |
| 559 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | 599 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), |
| 560 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | 600 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), |
| 561 | SND_SOC_DAPM_OUTPUT("SPKOUTRN"), | 601 | SND_SOC_DAPM_OUTPUT("SPKOUTRN"), |
| @@ -570,6 +610,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"), | |||
| 570 | { name, "Noise Generator", "Noise Generator" }, \ | 610 | { name, "Noise Generator", "Noise Generator" }, \ |
| 571 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 611 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
| 572 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 612 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
| 613 | { name, "AEC", "AEC Loopback" }, \ | ||
| 573 | { name, "IN1L", "IN1L PGA" }, \ | 614 | { name, "IN1L", "IN1L PGA" }, \ |
| 574 | { name, "IN1R", "IN1R PGA" }, \ | 615 | { name, "IN1R", "IN1R PGA" }, \ |
| 575 | { name, "IN2L", "IN2L PGA" }, \ | 616 | { name, "IN2L", "IN2L PGA" }, \ |
| @@ -620,6 +661,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 620 | { "OUT2L", NULL, "CPVDD" }, | 661 | { "OUT2L", NULL, "CPVDD" }, |
| 621 | { "OUT2R", NULL, "CPVDD" }, | 662 | { "OUT2R", NULL, "CPVDD" }, |
| 622 | { "OUT3L", NULL, "CPVDD" }, | 663 | { "OUT3L", NULL, "CPVDD" }, |
| 664 | { "OUT3R", NULL, "CPVDD" }, | ||
| 623 | 665 | ||
| 624 | { "OUT4L", NULL, "SPKVDDL" }, | 666 | { "OUT4L", NULL, "SPKVDDL" }, |
| 625 | { "OUT4R", NULL, "SPKVDDR" }, | 667 | { "OUT4R", NULL, "SPKVDDR" }, |
| @@ -701,7 +743,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 701 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | 743 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), |
| 702 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | 744 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), |
| 703 | ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | 745 | ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), |
| 704 | ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | 746 | ARIZONA_MIXER_ROUTES("OUT3L", "HPOUT3L"), |
| 747 | ARIZONA_MIXER_ROUTES("OUT3R", "HPOUT3R"), | ||
| 705 | 748 | ||
| 706 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | 749 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), |
| 707 | ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), | 750 | ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), |
| @@ -754,8 +797,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 754 | { "HPOUT2L", NULL, "OUT2L" }, | 797 | { "HPOUT2L", NULL, "OUT2L" }, |
| 755 | { "HPOUT2R", NULL, "OUT2R" }, | 798 | { "HPOUT2R", NULL, "OUT2R" }, |
| 756 | 799 | ||
| 757 | { "EPOUTN", NULL, "OUT3L" }, | 800 | { "HPOUT3L", NULL, "OUT3L" }, |
| 758 | { "EPOUTP", NULL, "OUT3L" }, | 801 | { "HPOUT3R", NULL, "OUT3L" }, |
| 759 | 802 | ||
| 760 | { "SPKOUTLN", NULL, "OUT4L" }, | 803 | { "SPKOUTLN", NULL, "OUT4L" }, |
| 761 | { "SPKOUTLP", NULL, "OUT4L" }, | 804 | { "SPKOUTLP", NULL, "OUT4L" }, |
| @@ -873,6 +916,8 @@ static unsigned int wm5110_digital_vu[] = { | |||
| 873 | ARIZONA_ADC_DIGITAL_VOLUME_2R, | 916 | ARIZONA_ADC_DIGITAL_VOLUME_2R, |
| 874 | ARIZONA_ADC_DIGITAL_VOLUME_3L, | 917 | ARIZONA_ADC_DIGITAL_VOLUME_3L, |
| 875 | ARIZONA_ADC_DIGITAL_VOLUME_3R, | 918 | ARIZONA_ADC_DIGITAL_VOLUME_3R, |
| 919 | ARIZONA_ADC_DIGITAL_VOLUME_4L, | ||
| 920 | ARIZONA_ADC_DIGITAL_VOLUME_4R, | ||
| 876 | 921 | ||
| 877 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | 922 | ARIZONA_DAC_DIGITAL_VOLUME_1L, |
| 878 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | 923 | ARIZONA_DAC_DIGITAL_VOLUME_1R, |
| @@ -884,6 +929,8 @@ static unsigned int wm5110_digital_vu[] = { | |||
| 884 | ARIZONA_DAC_DIGITAL_VOLUME_4R, | 929 | ARIZONA_DAC_DIGITAL_VOLUME_4R, |
| 885 | ARIZONA_DAC_DIGITAL_VOLUME_5L, | 930 | ARIZONA_DAC_DIGITAL_VOLUME_5L, |
| 886 | ARIZONA_DAC_DIGITAL_VOLUME_5R, | 931 | ARIZONA_DAC_DIGITAL_VOLUME_5R, |
| 932 | ARIZONA_DAC_DIGITAL_VOLUME_6L, | ||
| 933 | ARIZONA_DAC_DIGITAL_VOLUME_6R, | ||
| 887 | }; | 934 | }; |
| 888 | 935 | ||
| 889 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { | 936 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 7a773a835b8e..867ae97ddcec 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
| @@ -681,6 +681,11 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec) | |||
| 681 | 681 | ||
| 682 | snd_soc_update_bits(codec, WM8993_CLASS_W_0, | 682 | snd_soc_update_bits(codec, WM8993_CLASS_W_0, |
| 683 | WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); | 683 | WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); |
| 684 | |||
| 685 | snd_soc_write(codec, WM8993_LEFT_OUTPUT_VOLUME, | ||
| 686 | snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME)); | ||
| 687 | snd_soc_write(codec, WM8993_RIGHT_OUTPUT_VOLUME, | ||
| 688 | snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME)); | ||
| 684 | } | 689 | } |
| 685 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); | 690 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); |
| 686 | 691 | ||
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index efb9ede01208..267d5b4b63ce 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c | |||
| @@ -93,9 +93,7 @@ static struct snd_soc_card eukrea_tlv320 = { | |||
| 93 | .num_links = 1, | 93 | .num_links = 1, |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | static struct platform_device *eukrea_tlv320_snd_device; | 96 | static int __devinit eukrea_tlv320_probe(struct platform_device *pdev) |
| 97 | |||
| 98 | static int __init eukrea_tlv320_init(void) | ||
| 99 | { | 97 | { |
| 100 | int ret; | 98 | int ret; |
| 101 | int int_port = 0, ext_port; | 99 | int int_port = 0, ext_port; |
| @@ -136,29 +134,32 @@ static int __init eukrea_tlv320_init(void) | |||
| 136 | return 0; | 134 | return 0; |
| 137 | } | 135 | } |
| 138 | 136 | ||
| 139 | eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1); | 137 | eukrea_tlv320.dev = &pdev->dev; |
| 140 | if (!eukrea_tlv320_snd_device) | 138 | ret = snd_soc_register_card(&eukrea_tlv320); |
| 141 | return -ENOMEM; | 139 | if (ret) |
| 142 | 140 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | |
| 143 | platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320); | ||
| 144 | ret = platform_device_add(eukrea_tlv320_snd_device); | ||
| 145 | |||
| 146 | if (ret) { | ||
| 147 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); | ||
| 148 | platform_device_put(eukrea_tlv320_snd_device); | ||
| 149 | } | ||
| 150 | 141 | ||
| 151 | return ret; | 142 | return ret; |
| 152 | } | 143 | } |
| 153 | 144 | ||
| 154 | static void __exit eukrea_tlv320_exit(void) | 145 | static int __devexit eukrea_tlv320_remove(struct platform_device *pdev) |
| 155 | { | 146 | { |
| 156 | platform_device_unregister(eukrea_tlv320_snd_device); | 147 | snd_soc_unregister_card(&eukrea_tlv320); |
| 148 | |||
| 149 | return 0; | ||
| 157 | } | 150 | } |
| 158 | 151 | ||
| 159 | module_init(eukrea_tlv320_init); | 152 | static struct platform_driver eukrea_tlv320_driver = { |
| 160 | module_exit(eukrea_tlv320_exit); | 153 | .driver = { |
| 154 | .name = "eukrea_tlv320", | ||
| 155 | .owner = THIS_MODULE, | ||
| 156 | }, | ||
| 157 | .probe = eukrea_tlv320_probe, | ||
| 158 | .remove = __devexit_p(eukrea_tlv320_remove),}; | ||
| 159 | |||
| 160 | module_platform_driver(eukrea_tlv320_driver); | ||
| 161 | 161 | ||
| 162 | MODULE_AUTHOR("Eric Bénard <eric@eukrea.com>"); | 162 | MODULE_AUTHOR("Eric Bénard <eric@eukrea.com>"); |
| 163 | MODULE_DESCRIPTION("CPUIMX ALSA SoC driver"); | 163 | MODULE_DESCRIPTION("CPUIMX ALSA SoC driver"); |
| 164 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
| 165 | MODULE_ALIAS("platform:eukrea_tlv320"); | ||
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 873e6e76ee87..d0a4be38dc0f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
| @@ -1017,10 +1017,29 @@ EXPORT_SYMBOL_GPL(dapm_reg_event); | |||
| 1017 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, | 1017 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, |
| 1018 | struct snd_kcontrol *kcontrol, int event) | 1018 | struct snd_kcontrol *kcontrol, int event) |
| 1019 | { | 1019 | { |
| 1020 | if (SND_SOC_DAPM_EVENT_ON(event)) | 1020 | int ret; |
| 1021 | |||
| 1022 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
| 1023 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | ||
| 1024 | ret = regulator_allow_bypass(w->regulator, true); | ||
| 1025 | if (ret != 0) | ||
| 1026 | dev_warn(w->dapm->dev, | ||
| 1027 | "Failed to bypass %s: %d\n", | ||
| 1028 | w->name, ret); | ||
| 1029 | } | ||
| 1030 | |||
| 1021 | return regulator_enable(w->regulator); | 1031 | return regulator_enable(w->regulator); |
| 1022 | else | 1032 | } else { |
| 1033 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | ||
| 1034 | ret = regulator_allow_bypass(w->regulator, false); | ||
| 1035 | if (ret != 0) | ||
| 1036 | dev_warn(w->dapm->dev, | ||
| 1037 | "Failed to unbypass %s: %d\n", | ||
| 1038 | w->name, ret); | ||
| 1039 | } | ||
| 1040 | |||
| 1023 | return regulator_disable_deferred(w->regulator, w->shift); | 1041 | return regulator_disable_deferred(w->regulator, w->shift); |
| 1042 | } | ||
| 1024 | } | 1043 | } |
| 1025 | EXPORT_SYMBOL_GPL(dapm_regulator_event); | 1044 | EXPORT_SYMBOL_GPL(dapm_regulator_event); |
| 1026 | 1045 | ||
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 31c4d26d0359..356611d9654d 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
| 19 | #include <linux/of.h> | ||
| 19 | 20 | ||
| 20 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
| 21 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
| @@ -56,16 +57,47 @@ static struct snd_soc_card mop500_card = { | |||
| 56 | .num_links = ARRAY_SIZE(mop500_dai_links), | 57 | .num_links = ARRAY_SIZE(mop500_dai_links), |
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| 60 | static int __devinit mop500_of_probe(struct platform_device *pdev, | ||
| 61 | struct device_node *np) | ||
| 62 | { | ||
| 63 | struct device_node *codec_np, *msp_np[2]; | ||
| 64 | int i; | ||
| 65 | |||
| 66 | msp_np[0] = of_parse_phandle(np, "stericsson,cpu-dai", 0); | ||
| 67 | msp_np[1] = of_parse_phandle(np, "stericsson,cpu-dai", 1); | ||
| 68 | codec_np = of_parse_phandle(np, "stericsson,audio-codec", 0); | ||
| 69 | |||
| 70 | if (!(msp_np[0] && msp_np[1] && codec_np)) { | ||
| 71 | dev_err(&pdev->dev, "Phandle missing or invalid\n"); | ||
| 72 | return -EINVAL; | ||
| 73 | } | ||
| 74 | |||
| 75 | for (i = 0; i < 2; i++) { | ||
| 76 | mop500_dai_links[i].cpu_of_node = msp_np[i]; | ||
| 77 | mop500_dai_links[i].cpu_dai_name = NULL; | ||
| 78 | mop500_dai_links[i].codec_of_node = codec_np; | ||
| 79 | mop500_dai_links[i].codec_name = NULL; | ||
| 80 | } | ||
| 81 | |||
| 82 | snd_soc_of_parse_card_name(&mop500_card, "stericsson,card-name"); | ||
| 83 | |||
| 84 | return 0; | ||
| 85 | } | ||
| 59 | static int __devinit mop500_probe(struct platform_device *pdev) | 86 | static int __devinit mop500_probe(struct platform_device *pdev) |
| 60 | { | 87 | { |
| 88 | struct device_node *np = pdev->dev.of_node; | ||
| 61 | int ret; | 89 | int ret; |
| 62 | 90 | ||
| 63 | pr_debug("%s: Enter.\n", __func__); | ||
| 64 | |||
| 65 | dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); | 91 | dev_dbg(&pdev->dev, "%s: Enter.\n", __func__); |
| 66 | 92 | ||
| 67 | mop500_card.dev = &pdev->dev; | 93 | mop500_card.dev = &pdev->dev; |
| 68 | 94 | ||
| 95 | if (np) { | ||
| 96 | ret = mop500_of_probe(pdev, np); | ||
| 97 | if (ret) | ||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 69 | dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n", | 101 | dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n", |
| 70 | __func__, mop500_card.name); | 102 | __func__, mop500_card.name); |
| 71 | platform_set_drvdata(pdev, &mop500_card); | 103 | platform_set_drvdata(pdev, &mop500_card); |
| @@ -83,8 +115,7 @@ static int __devinit mop500_probe(struct platform_device *pdev) | |||
| 83 | ret = snd_soc_register_card(&mop500_card); | 115 | ret = snd_soc_register_card(&mop500_card); |
| 84 | if (ret) | 116 | if (ret) |
| 85 | dev_err(&pdev->dev, | 117 | dev_err(&pdev->dev, |
| 86 | "Error: snd_soc_register_card failed (%d)!\n", | 118 | "Error: snd_soc_register_card failed (%d)!\n", ret); |
| 87 | ret); | ||
| 88 | 119 | ||
| 89 | return ret; | 120 | return ret; |
| 90 | } | 121 | } |
| @@ -97,14 +128,20 @@ static int __devexit mop500_remove(struct platform_device *pdev) | |||
| 97 | 128 | ||
| 98 | snd_soc_unregister_card(mop500_card); | 129 | snd_soc_unregister_card(mop500_card); |
| 99 | mop500_ab8500_remove(mop500_card); | 130 | mop500_ab8500_remove(mop500_card); |
| 100 | 131 | ||
| 101 | return 0; | 132 | return 0; |
| 102 | } | 133 | } |
| 103 | 134 | ||
| 135 | static const struct of_device_id snd_soc_mop500_match[] = { | ||
| 136 | { .compatible = "stericsson,snd-soc-mop500", }, | ||
| 137 | {}, | ||
| 138 | }; | ||
| 139 | |||
| 104 | static struct platform_driver snd_soc_mop500_driver = { | 140 | static struct platform_driver snd_soc_mop500_driver = { |
| 105 | .driver = { | 141 | .driver = { |
| 106 | .owner = THIS_MODULE, | 142 | .owner = THIS_MODULE, |
| 107 | .name = "snd-soc-mop500", | 143 | .name = "snd-soc-mop500", |
| 144 | .of_match_table = snd_soc_mop500_match, | ||
| 108 | }, | 145 | }, |
| 109 | .probe = mop500_probe, | 146 | .probe = mop500_probe, |
| 110 | .remove = __devexit_p(mop500_remove), | 147 | .remove = __devexit_p(mop500_remove), |
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 772cb19d2fb3..be94bf9bf94f 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
| @@ -833,10 +833,16 @@ static int __devexit ux500_msp_drv_remove(struct platform_device *pdev) | |||
| 833 | return 0; | 833 | return 0; |
| 834 | } | 834 | } |
| 835 | 835 | ||
| 836 | static const struct of_device_id ux500_msp_i2s_match[] = { | ||
| 837 | { .compatible = "stericsson,ux500-msp-i2s", }, | ||
| 838 | {}, | ||
| 839 | }; | ||
| 840 | |||
| 836 | static struct platform_driver msp_i2s_driver = { | 841 | static struct platform_driver msp_i2s_driver = { |
| 837 | .driver = { | 842 | .driver = { |
| 838 | .name = "ux500-msp-i2s", | 843 | .name = "ux500-msp-i2s", |
| 839 | .owner = THIS_MODULE, | 844 | .owner = THIS_MODULE, |
| 845 | .of_match_table = ux500_msp_i2s_match, | ||
| 840 | }, | 846 | }, |
| 841 | .probe = ux500_msp_drv_probe, | 847 | .probe = ux500_msp_drv_probe, |
| 842 | .remove = ux500_msp_drv_remove, | 848 | .remove = ux500_msp_drv_remove, |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 1b7c2f58ce13..b7c996e77570 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
| @@ -15,8 +15,10 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 18 | #include <linux/pinctrl/consumer.h> | ||
| 18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/of.h> | ||
| 20 | 22 | ||
| 21 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
| 22 | #include <mach/msp.h> | 24 | #include <mach/msp.h> |
| @@ -25,6 +27,9 @@ | |||
| 25 | 27 | ||
| 26 | #include "ux500_msp_i2s.h" | 28 | #include "ux500_msp_i2s.h" |
| 27 | 29 | ||
| 30 | /* MSP1/3 Tx/Rx usage protection */ | ||
| 31 | static DEFINE_SPINLOCK(msp_rxtx_lock); | ||
| 32 | |||
| 28 | /* Protocol desciptors */ | 33 | /* Protocol desciptors */ |
| 29 | static const struct msp_protdesc prot_descs[] = { | 34 | static const struct msp_protdesc prot_descs[] = { |
| 30 | { /* I2S */ | 35 | { /* I2S */ |
| @@ -352,17 +357,23 @@ static int configure_multichannel(struct ux500_msp *msp, | |||
| 352 | 357 | ||
| 353 | static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) | 358 | static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) |
| 354 | { | 359 | { |
| 355 | int status = 0; | 360 | int status = 0, retval = 0; |
| 356 | u32 reg_val_DMACR, reg_val_GCR; | 361 | u32 reg_val_DMACR, reg_val_GCR; |
| 362 | unsigned long flags; | ||
| 357 | 363 | ||
| 358 | /* Check msp state whether in RUN or CONFIGURED Mode */ | 364 | /* Check msp state whether in RUN or CONFIGURED Mode */ |
| 359 | if ((msp->msp_state == MSP_STATE_IDLE) && (msp->plat_init)) { | 365 | if (msp->msp_state == MSP_STATE_IDLE) { |
| 360 | status = msp->plat_init(); | 366 | spin_lock_irqsave(&msp_rxtx_lock, flags); |
| 361 | if (status) { | 367 | if (msp->pinctrl_rxtx_ref == 0 && |
| 362 | dev_err(msp->dev, "%s: ERROR: Failed to init MSP (%d)!\n", | 368 | !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) { |
| 363 | __func__, status); | 369 | retval = pinctrl_select_state(msp->pinctrl_p, |
| 364 | return status; | 370 | msp->pinctrl_def); |
| 371 | if (retval) | ||
| 372 | pr_err("could not set MSP defstate\n"); | ||
| 365 | } | 373 | } |
| 374 | if (!retval) | ||
| 375 | msp->pinctrl_rxtx_ref++; | ||
| 376 | spin_unlock_irqrestore(&msp_rxtx_lock, flags); | ||
| 366 | } | 377 | } |
| 367 | 378 | ||
| 368 | /* Configure msp with protocol dependent settings */ | 379 | /* Configure msp with protocol dependent settings */ |
| @@ -620,7 +631,8 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction) | |||
| 620 | 631 | ||
| 621 | int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | 632 | int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) |
| 622 | { | 633 | { |
| 623 | int status = 0; | 634 | int status = 0, retval = 0; |
| 635 | unsigned long flags; | ||
| 624 | 636 | ||
| 625 | dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); | 637 | dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); |
| 626 | 638 | ||
| @@ -631,12 +643,19 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | |||
| 631 | writel((readl(msp->registers + MSP_GCR) & | 643 | writel((readl(msp->registers + MSP_GCR) & |
| 632 | (~(FRAME_GEN_ENABLE | SRG_ENABLE))), | 644 | (~(FRAME_GEN_ENABLE | SRG_ENABLE))), |
| 633 | msp->registers + MSP_GCR); | 645 | msp->registers + MSP_GCR); |
| 634 | if (msp->plat_exit) | 646 | |
| 635 | status = msp->plat_exit(); | 647 | spin_lock_irqsave(&msp_rxtx_lock, flags); |
| 636 | if (status) | 648 | WARN_ON(!msp->pinctrl_rxtx_ref); |
| 637 | dev_warn(msp->dev, | 649 | msp->pinctrl_rxtx_ref--; |
| 638 | "%s: WARN: ux500_msp_i2s_exit failed (%d)!\n", | 650 | if (msp->pinctrl_rxtx_ref == 0 && |
| 639 | __func__, status); | 651 | !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) { |
| 652 | retval = pinctrl_select_state(msp->pinctrl_p, | ||
| 653 | msp->pinctrl_sleep); | ||
| 654 | if (retval) | ||
| 655 | pr_err("could not set MSP sleepstate\n"); | ||
| 656 | } | ||
| 657 | spin_unlock_irqrestore(&msp_rxtx_lock, flags); | ||
| 658 | |||
| 640 | writel(0, msp->registers + MSP_GCR); | 659 | writel(0, msp->registers + MSP_GCR); |
| 641 | writel(0, msp->registers + MSP_TCF); | 660 | writel(0, msp->registers + MSP_TCF); |
| 642 | writel(0, msp->registers + MSP_RCF); | 661 | writel(0, msp->registers + MSP_RCF); |
| @@ -665,20 +684,33 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
| 665 | { | 684 | { |
| 666 | struct resource *res = NULL; | 685 | struct resource *res = NULL; |
| 667 | struct i2s_controller *i2s_cont; | 686 | struct i2s_controller *i2s_cont; |
| 687 | struct device_node *np = pdev->dev.of_node; | ||
| 668 | struct ux500_msp *msp; | 688 | struct ux500_msp *msp; |
| 669 | 689 | ||
| 670 | dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, | ||
| 671 | pdev->name, platform_data->id); | ||
| 672 | |||
| 673 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); | 690 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); |
| 674 | msp = *msp_p; | 691 | msp = *msp_p; |
| 675 | if (!msp) | 692 | if (!msp) |
| 676 | return -ENOMEM; | 693 | return -ENOMEM; |
| 677 | 694 | ||
| 695 | if (np) { | ||
| 696 | if (!platform_data) { | ||
| 697 | platform_data = devm_kzalloc(&pdev->dev, | ||
| 698 | sizeof(struct msp_i2s_platform_data), GFP_KERNEL); | ||
| 699 | if (!platform_data) | ||
| 700 | ret = -ENOMEM; | ||
| 701 | } | ||
| 702 | } else | ||
| 703 | if (!platform_data) | ||
| 704 | ret = -EINVAL; | ||
| 705 | |||
| 706 | if (ret) | ||
| 707 | goto err_res; | ||
| 708 | |||
| 709 | dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, | ||
| 710 | pdev->name, platform_data->id); | ||
| 711 | |||
| 678 | msp->id = platform_data->id; | 712 | msp->id = platform_data->id; |
| 679 | msp->dev = &pdev->dev; | 713 | msp->dev = &pdev->dev; |
| 680 | msp->plat_init = platform_data->msp_i2s_init; | ||
| 681 | msp->plat_exit = platform_data->msp_i2s_exit; | ||
| 682 | msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; | 714 | msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; |
| 683 | msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; | 715 | msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; |
| 684 | 716 | ||
| @@ -715,6 +747,25 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
| 715 | dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name); | 747 | dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name); |
| 716 | msp->i2s_cont = i2s_cont; | 748 | msp->i2s_cont = i2s_cont; |
| 717 | 749 | ||
| 750 | msp->pinctrl_p = pinctrl_get(msp->dev); | ||
| 751 | if (IS_ERR(msp->pinctrl_p)) | ||
| 752 | dev_err(&pdev->dev, "could not get MSP pinctrl\n"); | ||
| 753 | else { | ||
| 754 | msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p, | ||
| 755 | PINCTRL_STATE_DEFAULT); | ||
| 756 | if (IS_ERR(msp->pinctrl_def)) { | ||
| 757 | dev_err(&pdev->dev, | ||
| 758 | "could not get MSP defstate (%li)\n", | ||
| 759 | PTR_ERR(msp->pinctrl_def)); | ||
| 760 | } | ||
| 761 | msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p, | ||
| 762 | PINCTRL_STATE_SLEEP); | ||
| 763 | if (IS_ERR(msp->pinctrl_sleep)) | ||
| 764 | dev_err(&pdev->dev, | ||
| 765 | "could not get MSP idlestate (%li)\n", | ||
| 766 | PTR_ERR(msp->pinctrl_def)); | ||
| 767 | } | ||
| 768 | |||
| 718 | return 0; | 769 | return 0; |
| 719 | } | 770 | } |
| 720 | 771 | ||
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 2d9136da9865..1311c0df7628 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h | |||
| @@ -524,14 +524,18 @@ struct ux500_msp { | |||
| 524 | struct dma_chan *rx_pipeid; | 524 | struct dma_chan *rx_pipeid; |
| 525 | enum msp_state msp_state; | 525 | enum msp_state msp_state; |
| 526 | int (*transfer) (struct ux500_msp *msp, struct i2s_message *message); | 526 | int (*transfer) (struct ux500_msp *msp, struct i2s_message *message); |
| 527 | int (*plat_init) (void); | ||
| 528 | int (*plat_exit) (void); | ||
| 529 | struct timer_list notify_timer; | 527 | struct timer_list notify_timer; |
| 530 | int def_elem_len; | 528 | int def_elem_len; |
| 531 | unsigned int dir_busy; | 529 | unsigned int dir_busy; |
| 532 | int loopback_enable; | 530 | int loopback_enable; |
| 533 | u32 backup_regs[MAX_MSP_BACKUP_REGS]; | 531 | u32 backup_regs[MAX_MSP_BACKUP_REGS]; |
| 534 | unsigned int f_bitclk; | 532 | unsigned int f_bitclk; |
| 533 | /* Pin modes */ | ||
| 534 | struct pinctrl *pinctrl_p; | ||
| 535 | struct pinctrl_state *pinctrl_def; | ||
| 536 | struct pinctrl_state *pinctrl_sleep; | ||
| 537 | /* Reference Count */ | ||
| 538 | int pinctrl_rxtx_ref; | ||
| 535 | }; | 539 | }; |
| 536 | 540 | ||
| 537 | struct ux500_msp_dma_params { | 541 | struct ux500_msp_dma_params { |
