···1515#define WM8962_GPIO_SET 0x1000016161717struct wm8962_pdata {1818+ int gpio_base;1819 u32 gpio_init[WM8962_MAX_GPIO];19202021 /* Setup for microphone detection, raw value to be written to
+119
sound/soc/codecs/wm8962.c
···1717#include <linux/delay.h>1818#include <linux/pm.h>1919#include <linux/gcd.h>2020+#include <linux/gpio.h>2021#include <linux/i2c.h>2122#include <linux/input.h>2223#include <linux/platform_device.h>···7069 struct input_dev *beep;7170 struct work_struct beep_work;7271 int beep_rate;7272+#endif7373+7474+#ifdef CONFIG_GPIOLIB7575+ struct gpio_chip gpio_chip;7376#endif7477};7578···16511646}16521647#endif1653164816491649+#ifdef CONFIG_GPIOLIB16501650+static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip)16511651+{16521652+ return container_of(chip, struct wm8962_priv, gpio_chip);16531653+}16541654+16551655+static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)16561656+{16571657+ struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);16581658+ struct snd_soc_codec *codec = wm8962->codec;16591659+ int mask = 0;16601660+ int val;16611661+16621662+ /* The WM8962 GPIOs aren't linearly numbered. For simplicity16631663+ * we export linear numbers and error out if the unsupported16641664+ * ones are requsted.16651665+ */16661666+ switch (offset + 1) {16671667+ case 2:16681668+ mask = WM8962_CLKOUT2_SEL_MASK;16691669+ val = 1 << WM8962_CLKOUT2_SEL_SHIFT;16701670+ break;16711671+ case 3:16721672+ mask = WM8962_CLKOUT3_SEL_MASK;16731673+ val = 1 << WM8962_CLKOUT3_SEL_SHIFT;16741674+ break;16751675+ case 5:16761676+ case 6:16771677+ break;16781678+ default:16791679+ return -EINVAL;16801680+ }16811681+16821682+ /* Some of the GPIOs are behind MFP configuration */16831683+ if (mask)16841684+ snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1,16851685+ mask, val);16861686+16871687+ return 0;16881688+}16891689+16901690+static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)16911691+{16921692+ struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);16931693+ struct snd_soc_codec *codec = wm8962->codec;16941694+16951695+ snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,16961696+ WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT);16971697+}16981698+16991699+static int wm8962_gpio_direction_out(struct gpio_chip *chip,17001700+ unsigned offset, int value)17011701+{17021702+ struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);17031703+ struct snd_soc_codec *codec = wm8962->codec;17041704+ int val;17051705+17061706+ /* Force function 1 (logic output) */17071707+ val = (1 << WM8962_GP2_FN_SHIFT) | (value << WM8962_GP2_LVL_SHIFT);17081708+17091709+ return snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,17101710+ WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val);17111711+}17121712+17131713+static struct gpio_chip wm8962_template_chip = {17141714+ .label = "wm8962",17151715+ .owner = THIS_MODULE,17161716+ .request = wm8962_gpio_request,17171717+ .direction_output = wm8962_gpio_direction_out,17181718+ .set = wm8962_gpio_set,17191719+ .can_sleep = 1,17201720+};17211721+17221722+static void wm8962_init_gpio(struct snd_soc_codec *codec)17231723+{17241724+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);17251725+ struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);17261726+ int ret;17271727+17281728+ wm8962->gpio_chip = wm8962_template_chip;17291729+ wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO;17301730+ wm8962->gpio_chip.dev = codec->dev;17311731+17321732+ if (pdata && pdata->gpio_base)17331733+ wm8962->gpio_chip.base = pdata->gpio_base;17341734+ else17351735+ wm8962->gpio_chip.base = -1;17361736+17371737+ ret = gpiochip_add(&wm8962->gpio_chip);17381738+ if (ret != 0)17391739+ dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);17401740+}17411741+17421742+static void wm8962_free_gpio(struct snd_soc_codec *codec)17431743+{17441744+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);17451745+ int ret;17461746+17471747+ ret = gpiochip_remove(&wm8962->gpio_chip);17481748+ if (ret != 0)17491749+ dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);17501750+}17511751+#else17521752+static void wm8962_init_gpio(struct snd_soc_codec *codec)17531753+{17541754+}17551755+17561756+static void wm8962_free_gpio(struct snd_soc_codec *codec)17571757+{17581758+}17591759+#endif17601760+16541761static int wm8962_probe(struct snd_soc_codec *codec)16551762{16561763 int ret;···18951778 wm8962_add_widgets(codec);1896177918971780 wm8962_init_beep(codec);17811781+ wm8962_init_gpio(codec);1898178218991783 if (i2c->irq) {19001784 if (pdata && pdata->irq_active_low) {···19461828 if (i2c->irq)19471829 free_irq(i2c->irq, codec);1948183018311831+ wm8962_free_gpio(codec);19491832 wm8962_free_beep(codec);19501833 for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)19511834 regulator_unregister_notifier(wm8962->supplies[i].consumer,