dm: sound: Add conversion to driver model
Move the existing hardware drivers over to use driver model. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
6c986cfef4
commit
d6cadd5918
8 changed files with 320 additions and 17 deletions
|
@ -62,6 +62,7 @@
|
|||
i2c@12C70000 {
|
||||
soundcodec@1a {
|
||||
reg = <0x1a>;
|
||||
u-boot,i2c-offset-len = <2>;
|
||||
compatible = "wolfson,wm8994-codec";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
i2c@12C70000 {
|
||||
soundcodec@1a {
|
||||
reg = <0x1a>;
|
||||
u-boot,i2c-offset-len = <2>;
|
||||
compatible = "wolfson,wm8994-codec";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -6,9 +6,13 @@
|
|||
obj-$(CONFIG_SOUND) += sound.o
|
||||
obj-$(CONFIG_DM_SOUND) += codec-uclass.o
|
||||
obj-$(CONFIG_DM_SOUND) += i2s-uclass.o
|
||||
obj-$(CONFIG_I2S) += sound-i2s.o
|
||||
obj-$(CONFIG_DM_SOUND) += sound-uclass.o
|
||||
obj-$(CONFIG_I2S_SAMSUNG) += samsung-i2s.o
|
||||
obj-$(CONFIG_SOUND_SANDBOX) += sandbox.o
|
||||
ifdef CONFIG_DM_SOUND
|
||||
obj-$(CONFIG_I2S_SAMSUNG) += samsung_sound.o
|
||||
else
|
||||
obj-$(CONFIG_I2S) += sound-i2s.o
|
||||
endif
|
||||
obj-$(CONFIG_SOUND_WM8994) += wm8994.o
|
||||
obj-$(CONFIG_SOUND_MAX98095) += max98095.o
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <audio_codec.h>
|
||||
#include <dm.h>
|
||||
#include <div64.h>
|
||||
#include <fdtdec.h>
|
||||
#include <i2c.h>
|
||||
|
@ -28,6 +30,7 @@ struct max98095_priv {
|
|||
unsigned int rate;
|
||||
unsigned int fmt;
|
||||
int i2c_addr;
|
||||
struct udevice *dev;
|
||||
};
|
||||
|
||||
/* Index 0 is reserved. */
|
||||
|
@ -48,7 +51,12 @@ static int max98095_i2c_write(struct max98095_priv *priv, unsigned int reg,
|
|||
{
|
||||
debug("%s: Write Addr : 0x%02X, Data : 0x%02X\n",
|
||||
__func__, reg, data);
|
||||
#ifdef CONFIG_DM_SOUND
|
||||
debug("dev = %s\n", priv->dev->name);
|
||||
return dm_i2c_write(priv->dev, reg, &data, 1);
|
||||
#else
|
||||
return i2c_write(priv->i2c_addr, reg, 1, &data, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -65,7 +73,11 @@ static unsigned int max98095_i2c_read(struct max98095_priv *priv,
|
|||
{
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_DM_SOUND
|
||||
return dm_i2c_read(priv->dev, reg, data, 1);
|
||||
#else
|
||||
ret = i2c_read(priv->i2c_addr, reg, 1, data, 1);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
debug("%s: Error while reading register %#04x\n",
|
||||
__func__, reg);
|
||||
|
@ -484,7 +496,7 @@ static int max98095_do_init(struct max98095_priv *priv,
|
|||
|
||||
ret = max98095_setup_interface(priv, aif_id);
|
||||
if (ret < 0) {
|
||||
debug("%s: max98095 codec chip init failed\n", __func__);
|
||||
debug("%s: max98095 setup interface failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -507,6 +519,7 @@ static int max98095_do_init(struct max98095_priv *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_SOUND
|
||||
static int get_max98095_codec_values(struct sound_codec_info *pcodec_info,
|
||||
const void *blob)
|
||||
{
|
||||
|
@ -582,3 +595,47 @@ int max98095_init(const void *blob, enum en_max_audio_interface aif_id,
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int max98095_set_params(struct udevice *dev, int interface, int rate,
|
||||
int mclk_freq, int bits_per_sample,
|
||||
uint channels)
|
||||
{
|
||||
struct max98095_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return max98095_do_init(priv, interface, rate, mclk_freq,
|
||||
bits_per_sample);
|
||||
}
|
||||
|
||||
static int max98095_probe(struct udevice *dev)
|
||||
{
|
||||
struct max98095_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
priv->dev = dev;
|
||||
ret = max98095_device_init(priv);
|
||||
if (ret < 0) {
|
||||
debug("%s: max98095 codec chip init failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct audio_codec_ops max98095_ops = {
|
||||
.set_params = max98095_set_params,
|
||||
};
|
||||
|
||||
static const struct udevice_id max98095_ids[] = {
|
||||
{ .compatible = "maxim,max98095" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(max98095) = {
|
||||
.name = "max98095",
|
||||
.id = UCLASS_AUDIO_CODEC,
|
||||
.of_match = max98095_ids,
|
||||
.probe = max98095_probe,
|
||||
.ops = &max98095_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct max98095_priv),
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2s.h>
|
||||
#include <sound.h>
|
||||
#include <asm/arch/clk.h>
|
||||
|
@ -255,13 +256,13 @@ static int i2s_set_samplesize(struct i2s_reg *i2s_reg, unsigned int blc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, unsigned int *data,
|
||||
unsigned long data_size)
|
||||
int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, void *data,
|
||||
uint data_size)
|
||||
{
|
||||
struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address;
|
||||
u32 *ptr;
|
||||
int i;
|
||||
int start;
|
||||
struct i2s_reg *i2s_reg =
|
||||
(struct i2s_reg *)pi2s_tx->base_address;
|
||||
|
||||
if (data_size < FIFO_LENGTH) {
|
||||
debug("%s : Invalid data size\n", __func__);
|
||||
|
@ -269,17 +270,17 @@ int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, unsigned int *data,
|
|||
}
|
||||
|
||||
/* fill the tx buffer before stating the tx transmit */
|
||||
for (i = 0; i < FIFO_LENGTH; i++)
|
||||
writel(*data++, &i2s_reg->txd);
|
||||
for (i = 0, ptr = data; i < FIFO_LENGTH; i++)
|
||||
writel(*ptr++, &i2s_reg->txd);
|
||||
|
||||
data_size -= FIFO_LENGTH;
|
||||
data_size -= sizeof(*ptr) * FIFO_LENGTH;
|
||||
i2s_txctrl(i2s_reg, I2S_TX_ON);
|
||||
|
||||
while (data_size > 0) {
|
||||
start = get_timer(0);
|
||||
if (!(CON_TXFIFO_FULL & (readl(&i2s_reg->con)))) {
|
||||
writel(*data++, &i2s_reg->txd);
|
||||
data_size--;
|
||||
writel(*ptr++, &i2s_reg->txd);
|
||||
data_size -= sizeof(*ptr);
|
||||
} else {
|
||||
if (get_timer(start) > TIMEOUT_I2S_TX) {
|
||||
i2s_txctrl(i2s_reg, I2S_TX_OFF);
|
||||
|
@ -296,8 +297,8 @@ int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, unsigned int *data,
|
|||
int i2s_tx_init(struct i2s_uc_priv *pi2s_tx)
|
||||
{
|
||||
int ret;
|
||||
struct i2s_reg *i2s_reg =
|
||||
(struct i2s_reg *)pi2s_tx->base_address;
|
||||
struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address;
|
||||
|
||||
if (pi2s_tx->id == 0) {
|
||||
/* Initialize GPIO for I2S-0 */
|
||||
exynos_pinmux_config(PERIPH_ID_I2S0, 0);
|
||||
|
@ -348,8 +349,8 @@ int i2s_tx_init(struct i2s_uc_priv *pi2s_tx)
|
|||
}
|
||||
|
||||
/* Configure I2s format */
|
||||
ret = i2s_set_fmt(i2s_reg, (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBM_CFM));
|
||||
ret = i2s_set_fmt(i2s_reg, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBM_CFM);
|
||||
if (ret == 0) {
|
||||
i2s_set_lr_framesize(i2s_reg, pi2s_tx->rfs);
|
||||
ret = i2s_set_samplesize(i2s_reg, pi2s_tx->bitspersample);
|
||||
|
@ -368,3 +369,87 @@ int i2s_tx_init(struct i2s_uc_priv *pi2s_tx)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int samsung_i2s_tx_data(struct udevice *dev, void *data, uint data_size)
|
||||
{
|
||||
struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
|
||||
|
||||
return i2s_transfer_tx_data(priv, data, data_size);
|
||||
}
|
||||
|
||||
static int samsung_i2s_probe(struct udevice *dev)
|
||||
{
|
||||
struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
|
||||
|
||||
return i2s_tx_init(priv);
|
||||
}
|
||||
|
||||
static int samsung_i2s_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct i2s_uc_priv *priv = dev_get_uclass_priv(dev);
|
||||
ulong base;
|
||||
|
||||
/*
|
||||
* Get the pre-defined sound specific values from FDT.
|
||||
* All of these are expected to be correct otherwise
|
||||
* wrong register values in i2s setup parameters
|
||||
* may result in no sound play.
|
||||
*/
|
||||
base = dev_read_addr(dev);
|
||||
if (base == FDT_ADDR_T_NONE) {
|
||||
debug("%s: Missing i2s base\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
priv->base_address = base;
|
||||
|
||||
if (dev_read_u32u(dev, "samsung,i2s-epll-clock-frequency",
|
||||
&priv->audio_pll_clk))
|
||||
goto err;
|
||||
debug("audio_pll_clk = %d\n", priv->audio_pll_clk);
|
||||
if (dev_read_u32u(dev, "samsung,i2s-sampling-rate",
|
||||
&priv->samplingrate))
|
||||
goto err;
|
||||
debug("samplingrate = %d\n", priv->samplingrate);
|
||||
if (dev_read_u32u(dev, "samsung,i2s-bits-per-sample",
|
||||
&priv->bitspersample))
|
||||
goto err;
|
||||
debug("bitspersample = %d\n", priv->bitspersample);
|
||||
if (dev_read_u32u(dev, "samsung,i2s-channels", &priv->channels))
|
||||
goto err;
|
||||
debug("channels = %d\n", priv->channels);
|
||||
if (dev_read_u32u(dev, "samsung,i2s-lr-clk-framesize", &priv->rfs))
|
||||
goto err;
|
||||
debug("rfs = %d\n", priv->rfs);
|
||||
if (dev_read_u32u(dev, "samsung,i2s-bit-clk-framesize", &priv->bfs))
|
||||
goto err;
|
||||
debug("bfs = %d\n", priv->bfs);
|
||||
|
||||
if (dev_read_u32u(dev, "samsung,i2s-id", &priv->id))
|
||||
goto err;
|
||||
debug("id = %d\n", priv->id);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
debug("fail to get sound i2s node properties\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct i2s_ops samsung_i2s_ops = {
|
||||
.tx_data = samsung_i2s_tx_data,
|
||||
};
|
||||
|
||||
static const struct udevice_id samsung_i2s_ids[] = {
|
||||
{ .compatible = "samsung,s5pv210-i2s" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(samsung_i2s) = {
|
||||
.name = "samsung_i2s",
|
||||
.id = UCLASS_I2S,
|
||||
.of_match = samsung_i2s_ids,
|
||||
.probe = samsung_i2s_probe,
|
||||
.ofdata_to_platdata = samsung_i2s_ofdata_to_platdata,
|
||||
.ops = &samsung_i2s_ops,
|
||||
};
|
||||
|
|
101
drivers/sound/samsung_sound.c
Normal file
101
drivers/sound/samsung_sound.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2018 Google, LLC
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <audio_codec.h>
|
||||
#include <dm.h>
|
||||
#include <i2s.h>
|
||||
#include <sound.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
static int samsung_sound_setup(struct udevice *dev)
|
||||
{
|
||||
struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct i2s_uc_priv *i2c_priv = dev_get_uclass_priv(uc_priv->i2s);
|
||||
int ret;
|
||||
|
||||
if (uc_priv->setup_done)
|
||||
return -EALREADY;
|
||||
ret = audio_codec_set_params(uc_priv->codec, i2c_priv->id,
|
||||
i2c_priv->samplingrate,
|
||||
i2c_priv->samplingrate * i2c_priv->rfs,
|
||||
i2c_priv->bitspersample,
|
||||
i2c_priv->channels);
|
||||
if (ret)
|
||||
return ret;
|
||||
uc_priv->setup_done = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_sound_play(struct udevice *dev, void *data, uint data_size)
|
||||
{
|
||||
struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
|
||||
return i2s_tx_data(uc_priv->i2s, data, data_size);
|
||||
}
|
||||
|
||||
static int samsung_sound_probe(struct udevice *dev)
|
||||
{
|
||||
struct sound_uc_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct ofnode_phandle_args args;
|
||||
struct gpio_desc en_gpio;
|
||||
ofnode node;
|
||||
int ret;
|
||||
|
||||
ret = gpio_request_by_name(dev, "codec-enable-gpio", 0, &en_gpio,
|
||||
GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
|
||||
|
||||
/* Turn on the GPIO which connects to the codec's "enable" line. */
|
||||
if (!ret)
|
||||
gpio_set_pull(gpio_get_number(&en_gpio), S5P_GPIO_PULL_NONE);
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_AUDIO_CODEC, dev,
|
||||
"samsung,audio-codec",
|
||||
&uc_priv->codec);
|
||||
if (ret) {
|
||||
debug("Failed to probe audio codec\n");
|
||||
return ret;
|
||||
}
|
||||
node = ofnode_find_subnode(dev_ofnode(dev), "cpu");
|
||||
if (!ofnode_valid(node)) {
|
||||
debug("Failed to find /cpu subnode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = ofnode_parse_phandle_with_args(node, "sound-dai",
|
||||
"#sound-dai-cells", 0, 0, &args);
|
||||
if (ret) {
|
||||
debug("Cannot find phandle: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = uclass_get_device_by_ofnode(UCLASS_I2S, args.node, &uc_priv->i2s);
|
||||
if (ret) {
|
||||
debug("Cannot find i2s: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
debug("Probed sound '%s' with codec '%s' and i2s '%s'\n", dev->name,
|
||||
uc_priv->codec->name, uc_priv->i2s->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sound_ops samsung_sound_ops = {
|
||||
.setup = samsung_sound_setup,
|
||||
.play = samsung_sound_play,
|
||||
};
|
||||
|
||||
static const struct udevice_id samsung_sound_ids[] = {
|
||||
{ .compatible = "google,snow-audio-max98095" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(samsung_sound) = {
|
||||
.name = "samsung_sound",
|
||||
.id = UCLASS_SOUND,
|
||||
.of_match = samsung_sound_ids,
|
||||
.probe = samsung_sound_probe,
|
||||
.ops = &samsung_sound_ops,
|
||||
};
|
|
@ -118,7 +118,10 @@ static int sandbox_i2s_probe(struct udevice *dev)
|
|||
uc_priv->channels = 2;
|
||||
uc_priv->id = 1;
|
||||
|
||||
return sandbox_sdl_sound_init();
|
||||
/* Ignore any error here - we'll just have no sound */
|
||||
sandbox_sdl_sound_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_sound_setup(struct udevice *dev)
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* R. Chandrasekar <rcsekar@samsung.com>
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <audio_codec.h>
|
||||
#include <dm.h>
|
||||
#include <div64.h>
|
||||
#include <fdtdec.h>
|
||||
#include <i2c.h>
|
||||
|
@ -39,6 +41,7 @@ struct wm8994_priv {
|
|||
int aifclk[WM8994_MAX_AIF]; /* audio interface clock in Hz */
|
||||
struct wm8994_fll_config fll[2]; /* fll config to configure fll */
|
||||
int i2c_addr;
|
||||
struct udevice *dev;
|
||||
};
|
||||
|
||||
/* wm 8994 supported sampling rate values */
|
||||
|
@ -79,7 +82,12 @@ static int wm8994_i2c_write(struct wm8994_priv *priv, unsigned int reg,
|
|||
val[1] = (unsigned char)(data & 0xff);
|
||||
debug("Write Addr : 0x%04X, Data : 0x%04X\n", reg, data);
|
||||
|
||||
#ifdef CONFIG_DM_SOUND
|
||||
debug("dev = %s\n", priv->dev->name);
|
||||
return dm_i2c_write(priv->dev, reg, val, 2);
|
||||
#else
|
||||
return i2c_write(priv->i2c_addr, reg, 2, val, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -97,7 +105,11 @@ static unsigned int wm8994_i2c_read(struct wm8994_priv *priv, unsigned int reg,
|
|||
unsigned char val[2];
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_DM_SOUND
|
||||
ret = dm_i2c_read(priv->dev, reg, val, 1);
|
||||
#else
|
||||
ret = i2c_read(priv->i2c_addr, reg, 2, val, 2);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
debug("%s: Error while reading register %#04x\n",
|
||||
__func__, reg);
|
||||
|
@ -807,6 +819,7 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_SOUND
|
||||
/*
|
||||
* Gets fdt values for wm8994 config parameters
|
||||
*
|
||||
|
@ -859,6 +872,7 @@ static int get_codec_values(struct sound_codec_info *pcodec_info,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _wm8994_init(struct wm8994_priv *priv,
|
||||
enum en_audio_interface aif_id, int sampling_rate,
|
||||
|
@ -873,7 +887,7 @@ static int _wm8994_init(struct wm8994_priv *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = wm8994_set_sysclk(priv, aif_id, WM8994_SYSCLK_MCLK1, mclk_freq);
|
||||
ret = wm8994_set_sysclk(priv, aif_id, WM8994_SYSCLK_MCLK1, mclk_freq);
|
||||
if (ret < 0) {
|
||||
debug("%s: wm8994 codec set sys clock failed\n", __func__);
|
||||
return ret;
|
||||
|
@ -891,6 +905,7 @@ static int _wm8994_init(struct wm8994_priv *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_SOUND
|
||||
/* WM8994 Device Initialisation */
|
||||
int wm8994_init(const void *blob, enum en_audio_interface aif_id,
|
||||
int sampling_rate, int mclk_freq, int bits_per_sample,
|
||||
|
@ -918,3 +933,39 @@ int wm8994_init(const void *blob, enum en_audio_interface aif_id,
|
|||
return _wm8994_init(&wm8994_info, aif_id, sampling_rate, mclk_freq,
|
||||
bits_per_sample, channels);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int wm8994_set_params(struct udevice *dev, int interface, int rate,
|
||||
int mclk_freq, int bits_per_sample, uint channels)
|
||||
{
|
||||
struct wm8994_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return _wm8994_init(priv, interface, rate, mclk_freq, bits_per_sample,
|
||||
channels);
|
||||
}
|
||||
|
||||
static int wm8994_probe(struct udevice *dev)
|
||||
{
|
||||
struct wm8994_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->dev = dev;
|
||||
return wm8994_device_init(priv);
|
||||
}
|
||||
|
||||
static const struct audio_codec_ops wm8994_ops = {
|
||||
.set_params = wm8994_set_params,
|
||||
};
|
||||
|
||||
static const struct udevice_id wm8994_ids[] = {
|
||||
{ .compatible = "wolfson,wm8994" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(wm8994) = {
|
||||
.name = "wm8994",
|
||||
.id = UCLASS_AUDIO_CODEC,
|
||||
.of_match = wm8994_ids,
|
||||
.probe = wm8994_probe,
|
||||
.ops = &wm8994_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct wm8994_priv),
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue