Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: twl4030-audio: Add DT support

Support for loading the twl4030 audio module via devicetree.
Sub devices for codec and vibra will be created as mfd devices once the
core MFD driver is loaded when the kernel is booted with a DT blob.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Peter Ujfalusi and committed by
Samuel Ortiz
019a7e6b 1cc44f43

+93 -7
+46
Documentation/devicetree/bindings/mfd/twl4030-audio.txt
··· 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 + };
+47 -7
drivers/mfd/twl4030-audio.c
··· 28 28 #include <linux/kernel.h> 29 29 #include <linux/fs.h> 30 30 #include <linux/platform_device.h> 31 + #include <linux/of.h> 32 + #include <linux/of_platform.h> 31 33 #include <linux/i2c/twl.h> 32 34 #include <linux/mfd/core.h> 33 35 #include <linux/mfd/twl4030-audio.h> ··· 158 156 } 159 157 EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk); 160 158 159 + static bool twl4030_audio_has_codec(struct twl4030_audio_data *pdata, 160 + struct device_node *node) 161 + { 162 + if (pdata && pdata->codec) 163 + return true; 164 + 165 + if (of_find_node_by_name(node, "codec")) 166 + return true; 167 + 168 + return false; 169 + } 170 + 171 + static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata, 172 + struct device_node *node) 173 + { 174 + int vibra; 175 + 176 + if (pdata && pdata->vibra) 177 + return true; 178 + 179 + if (!of_property_read_u32(node, "ti,enable-vibra", &vibra) && vibra) 180 + return true; 181 + 182 + return false; 183 + } 184 + 161 185 static int __devinit twl4030_audio_probe(struct platform_device *pdev) 162 186 { 163 187 struct twl4030_audio *audio; 164 188 struct twl4030_audio_data *pdata = pdev->dev.platform_data; 189 + struct device_node *node = pdev->dev.of_node; 165 190 struct mfd_cell *cell = NULL; 166 191 int ret, childs = 0; 167 192 u8 val; 168 193 169 - if (!pdata) { 194 + if (!pdata && !node) { 170 195 dev_err(&pdev->dev, "Platform data is missing\n"); 171 196 return -EINVAL; 172 197 } ··· 231 202 audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL; 232 203 audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN; 233 204 234 - if (pdata->codec) { 205 + if (twl4030_audio_has_codec(pdata, node)) { 235 206 cell = &audio->cells[childs]; 236 207 cell->name = "twl4030-codec"; 237 - cell->platform_data = pdata->codec; 238 - cell->pdata_size = sizeof(*pdata->codec); 208 + if (pdata) { 209 + cell->platform_data = pdata->codec; 210 + cell->pdata_size = sizeof(*pdata->codec); 211 + } 239 212 childs++; 240 213 } 241 - if (pdata->vibra) { 214 + if (twl4030_audio_has_vibra(pdata, node)) { 242 215 cell = &audio->cells[childs]; 243 216 cell->name = "twl4030-vibra"; 244 - cell->platform_data = pdata->vibra; 245 - cell->pdata_size = sizeof(*pdata->vibra); 217 + if (pdata) { 218 + cell->platform_data = pdata->vibra; 219 + cell->pdata_size = sizeof(*pdata->vibra); 220 + } 246 221 childs++; 247 222 } 248 223 ··· 278 245 return 0; 279 246 } 280 247 248 + static const struct of_device_id twl4030_audio_of_match[] = { 249 + {.compatible = "ti,twl4030-audio", }, 250 + { }, 251 + }; 252 + MODULE_DEVICE_TABLE(of, twl4030_audio_of_match); 253 + 281 254 static struct platform_driver twl4030_audio_driver = { 282 255 .driver = { 283 256 .owner = THIS_MODULE, 284 257 .name = "twl4030-audio", 258 + .of_match_table = twl4030_audio_of_match, 285 259 }, 286 260 .probe = twl4030_audio_probe, 287 261 .remove = __devexit_p(twl4030_audio_remove),