diff options
| -rw-r--r-- | Documentation/devicetree/bindings/mfd/twl4030-audio.txt | 46 | ||||
| -rw-r--r-- | drivers/mfd/twl4030-audio.c | 54 |
2 files changed, 93 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/mfd/twl4030-audio.txt b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt new file mode 100644 index 000000000000..414d2ae0adf6 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | Texas Instruments TWL family (twl4030) audio module | ||
| 2 | |||
| 3 | The audio module inside the TWL family consist of an audio codec and a vibra | ||
| 4 | driver. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible : must be "ti,twl4030-audio" | ||
| 8 | |||
| 9 | Optional properties, nodes: | ||
| 10 | |||
| 11 | Audio functionality: | ||
| 12 | - codec { }: Need to be present if the audio functionality is used. Within this | ||
| 13 | section the following options can be used: | ||
| 14 | - ti,digimic_delay: Delay need after enabling the digimic to reduce artifacts | ||
| 15 | from the start of the recorded sample (in ms) | ||
| 16 | -ti,ramp_delay_value: HS ramp delay configuration to reduce pop noise | ||
| 17 | -ti,hs_extmute: Use external mute for HS pop reduction | ||
| 18 | -ti,hs_extmute_gpio: Use external GPIO to control the external mute | ||
| 19 | -ti,offset_cncl_path: Offset cancellation path selection, refer to TRM for the | ||
| 20 | valid values. | ||
| 21 | |||
| 22 | Vibra functionality | ||
| 23 | - ti,enable-vibra: Need to be set to <1> if the vibra functionality is used. if | ||
| 24 | missing or it is 0, the vibra functionality is disabled. | ||
| 25 | |||
| 26 | Example: | ||
| 27 | &i2c1 { | ||
| 28 | clock-frequency = <2600000>; | ||
| 29 | |||
| 30 | twl: twl@48 { | ||
| 31 | reg = <0x48>; | ||
| 32 | interrupts = <7>; /* SYS_NIRQ cascaded to intc */ | ||
| 33 | interrupt-parent = <&intc>; | ||
| 34 | |||
| 35 | twl_audio: audio { | ||
| 36 | compatible = "ti,twl4030-audio"; | ||
| 37 | |||
| 38 | ti,enable-vibra = <1>; | ||
| 39 | |||
| 40 | codec { | ||
| 41 | ti,ramp_delay_value = <3>; | ||
| 42 | }; | ||
| 43 | |||
| 44 | }; | ||
| 45 | }; | ||
| 46 | }; | ||
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index a48bf3af1240..58e6c228653b 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
| 30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| 31 | #include <linux/of.h> | ||
| 32 | #include <linux/of_platform.h> | ||
| 31 | #include <linux/i2c/twl.h> | 33 | #include <linux/i2c/twl.h> |
| 32 | #include <linux/mfd/core.h> | 34 | #include <linux/mfd/core.h> |
| 33 | #include <linux/mfd/twl4030-audio.h> | 35 | #include <linux/mfd/twl4030-audio.h> |
| @@ -156,15 +158,42 @@ unsigned int twl4030_audio_get_mclk(void) | |||
| 156 | } | 158 | } |
| 157 | EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk); | 159 | EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk); |
| 158 | 160 | ||
| 161 | static bool twl4030_audio_has_codec(struct twl4030_audio_data *pdata, | ||
| 162 | struct device_node *node) | ||
| 163 | { | ||
| 164 | if (pdata && pdata->codec) | ||
| 165 | return true; | ||
| 166 | |||
| 167 | if (of_find_node_by_name(node, "codec")) | ||
| 168 | return true; | ||
| 169 | |||
| 170 | return false; | ||
| 171 | } | ||
| 172 | |||
| 173 | static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata, | ||
| 174 | struct device_node *node) | ||
| 175 | { | ||
| 176 | int vibra; | ||
| 177 | |||
| 178 | if (pdata && pdata->vibra) | ||
| 179 | return true; | ||
| 180 | |||
| 181 | if (!of_property_read_u32(node, "ti,enable-vibra", &vibra) && vibra) | ||
| 182 | return true; | ||
| 183 | |||
| 184 | return false; | ||
| 185 | } | ||
| 186 | |||
| 159 | static int __devinit twl4030_audio_probe(struct platform_device *pdev) | 187 | static int __devinit twl4030_audio_probe(struct platform_device *pdev) |
| 160 | { | 188 | { |
| 161 | struct twl4030_audio *audio; | 189 | struct twl4030_audio *audio; |
| 162 | struct twl4030_audio_data *pdata = pdev->dev.platform_data; | 190 | struct twl4030_audio_data *pdata = pdev->dev.platform_data; |
| 191 | struct device_node *node = pdev->dev.of_node; | ||
| 163 | struct mfd_cell *cell = NULL; | 192 | struct mfd_cell *cell = NULL; |
| 164 | int ret, childs = 0; | 193 | int ret, childs = 0; |
| 165 | u8 val; | 194 | u8 val; |
| 166 | 195 | ||
| 167 | if (!pdata) { | 196 | if (!pdata && !node) { |
| 168 | dev_err(&pdev->dev, "Platform data is missing\n"); | 197 | dev_err(&pdev->dev, "Platform data is missing\n"); |
| 169 | return -EINVAL; | 198 | return -EINVAL; |
| 170 | } | 199 | } |
| @@ -202,18 +231,22 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev) | |||
| 202 | audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL; | 231 | audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL; |
| 203 | audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN; | 232 | audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN; |
| 204 | 233 | ||
| 205 | if (pdata->codec) { | 234 | if (twl4030_audio_has_codec(pdata, node)) { |
| 206 | cell = &audio->cells[childs]; | 235 | cell = &audio->cells[childs]; |
| 207 | cell->name = "twl4030-codec"; | 236 | cell->name = "twl4030-codec"; |
| 208 | cell->platform_data = pdata->codec; | 237 | if (pdata) { |
| 209 | cell->pdata_size = sizeof(*pdata->codec); | 238 | cell->platform_data = pdata->codec; |
| 239 | cell->pdata_size = sizeof(*pdata->codec); | ||
| 240 | } | ||
| 210 | childs++; | 241 | childs++; |
| 211 | } | 242 | } |
| 212 | if (pdata->vibra) { | 243 | if (twl4030_audio_has_vibra(pdata, node)) { |
| 213 | cell = &audio->cells[childs]; | 244 | cell = &audio->cells[childs]; |
| 214 | cell->name = "twl4030-vibra"; | 245 | cell->name = "twl4030-vibra"; |
| 215 | cell->platform_data = pdata->vibra; | 246 | if (pdata) { |
| 216 | cell->pdata_size = sizeof(*pdata->vibra); | 247 | cell->platform_data = pdata->vibra; |
| 248 | cell->pdata_size = sizeof(*pdata->vibra); | ||
| 249 | } | ||
| 217 | childs++; | 250 | childs++; |
| 218 | } | 251 | } |
| 219 | 252 | ||
| @@ -245,10 +278,17 @@ static int __devexit twl4030_audio_remove(struct platform_device *pdev) | |||
| 245 | return 0; | 278 | return 0; |
| 246 | } | 279 | } |
| 247 | 280 | ||
| 281 | static const struct of_device_id twl4030_audio_of_match[] = { | ||
| 282 | {.compatible = "ti,twl4030-audio", }, | ||
| 283 | { }, | ||
| 284 | }; | ||
| 285 | MODULE_DEVICE_TABLE(of, twl4030_audio_of_match); | ||
| 286 | |||
| 248 | static struct platform_driver twl4030_audio_driver = { | 287 | static struct platform_driver twl4030_audio_driver = { |
| 249 | .driver = { | 288 | .driver = { |
| 250 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
| 251 | .name = "twl4030-audio", | 290 | .name = "twl4030-audio", |
| 291 | .of_match_table = twl4030_audio_of_match, | ||
| 252 | }, | 292 | }, |
| 253 | .probe = twl4030_audio_probe, | 293 | .probe = twl4030_audio_probe, |
| 254 | .remove = __devexit_p(twl4030_audio_remove), | 294 | .remove = __devexit_p(twl4030_audio_remove), |
