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

ASoC: Add platform data for WM1250 EV1 GPIOs

The WM1250 EV1 has some GPIOs which can be used to control the behaviour
at runtime. Request them all if supplied and add a set_bias_level()
function to start and stop the clocks.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

+145 -3
+27
include/sound/wm1250-ev1.h
··· 1 + /* 2 + * linux/sound/wm1250-ev1.h - Platform data for WM1250-EV1 3 + * 4 + * Copyright 2011 Wolfson Microelectronics. PLC. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #ifndef __LINUX_SND_WM1250_EV1_H 12 + #define __LINUX_SND_WM1250_EV1_H 13 + 14 + #define WM1250_EV1_NUM_GPIOS 5 15 + 16 + #define WM1250_EV1_GPIO_CLK_ENA 0 17 + #define WM1250_EV1_GPIO_CLK_SEL0 1 18 + #define WM1250_EV1_GPIO_CLK_SEL1 2 19 + #define WM1250_EV1_GPIO_OSR 3 20 + #define WM1250_EV1_GPIO_MASTER 4 21 + 22 + 23 + struct wm1250_ev1_pdata { 24 + int gpios[WM1250_EV1_NUM_GPIOS]; 25 + }; 26 + 27 + #endif
+118 -3
sound/soc/codecs/wm1250-ev1.c
··· 12 12 13 13 #include <linux/init.h> 14 14 #include <linux/module.h> 15 + #include <linux/slab.h> 15 16 #include <linux/i2c.h> 17 + #include <linux/gpio.h> 16 18 17 19 #include <sound/soc.h> 18 20 #include <sound/soc-dapm.h> 21 + #include <sound/wm1250-ev1.h> 22 + 23 + static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = { 24 + "WM1250 CLK_ENA", 25 + "WM1250 CLK_SEL0", 26 + "WM1250 CLK_SEL1", 27 + "WM1250 OSR", 28 + "WM1250 MASTER", 29 + }; 30 + 31 + struct wm1250_priv { 32 + struct gpio gpios[WM1250_EV1_NUM_GPIOS]; 33 + }; 34 + 35 + static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec, 36 + enum snd_soc_bias_level level) 37 + { 38 + struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev); 39 + int ena; 40 + 41 + if (wm1250) 42 + ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio; 43 + else 44 + ena = -1; 45 + 46 + switch (level) { 47 + case SND_SOC_BIAS_ON: 48 + break; 49 + 50 + case SND_SOC_BIAS_PREPARE: 51 + break; 52 + 53 + case SND_SOC_BIAS_STANDBY: 54 + if (ena >= 0) 55 + gpio_set_value_cansleep(ena, 1); 56 + break; 57 + 58 + case SND_SOC_BIAS_OFF: 59 + if (ena >= 0) 60 + gpio_set_value_cansleep(ena, 0); 61 + break; 62 + } 63 + 64 + codec->dapm.bias_level = level; 65 + 66 + return 0; 67 + } 19 68 20 69 static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = { 21 70 SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0), ··· 102 53 .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), 103 54 .dapm_routes = wm1250_ev1_dapm_routes, 104 55 .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), 56 + 57 + .set_bias_level = wm1250_ev1_set_bias_level, 105 58 }; 59 + 60 + static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c) 61 + { 62 + struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev); 63 + struct wm1250_priv *wm1250; 64 + int i, ret; 65 + 66 + if (!pdata) 67 + return 0; 68 + 69 + wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL); 70 + if (!wm1250) { 71 + dev_err(&i2c->dev, "Unable to allocate private data\n"); 72 + ret = -ENOMEM; 73 + goto err; 74 + } 75 + 76 + for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) { 77 + wm1250->gpios[i].gpio = pdata->gpios[i]; 78 + wm1250->gpios[i].label = wm1250_gpio_names[i]; 79 + wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW; 80 + } 81 + wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH; 82 + wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH; 83 + 84 + ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios)); 85 + if (ret != 0) { 86 + dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret); 87 + goto err_alloc; 88 + } 89 + 90 + dev_set_drvdata(&i2c->dev, wm1250); 91 + 92 + return ret; 93 + 94 + err_alloc: 95 + kfree(wm1250); 96 + err: 97 + return ret; 98 + } 99 + 100 + static void wm1250_ev1_free(struct i2c_client *i2c) 101 + { 102 + struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev); 103 + 104 + if (wm1250) { 105 + gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios)); 106 + kfree(wm1250); 107 + } 108 + } 106 109 107 110 static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, 108 111 const struct i2c_device_id *i2c_id) 109 112 { 110 - int id, board, rev; 113 + int id, board, rev, ret; 114 + 115 + dev_set_drvdata(&i2c->dev, NULL); 111 116 112 117 board = i2c_smbus_read_byte_data(i2c, 0); 113 118 if (board < 0) { ··· 179 76 180 77 dev_info(&i2c->dev, "revision %d\n", rev + 1); 181 78 182 - return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, 183 - &wm1250_ev1_dai, 1); 79 + ret = wm1250_ev1_pdata(i2c); 80 + if (ret != 0) 81 + return ret; 82 + 83 + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, 84 + &wm1250_ev1_dai, 1); 85 + if (ret != 0) { 86 + dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); 87 + wm1250_ev1_free(i2c); 88 + return ret; 89 + } 90 + 91 + return 0; 184 92 } 185 93 186 94 static int __devexit wm1250_ev1_remove(struct i2c_client *i2c) 187 95 { 188 96 snd_soc_unregister_codec(&i2c->dev); 97 + wm1250_ev1_free(i2c); 189 98 190 99 return 0; 191 100 }