MA-17787 ASoC: rpmsg_wm8960: Separate i2c driver to individual file

Move rpmsg wm8960 i2c driver to a new driver file,
otherwise it can not be built as module.

Signed-off-by: Jindong <jindong.yue@nxp.com>
Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com>
This commit is contained in:
Jindong 2020-08-27 14:24:57 +08:00
parent 4e1aa17692
commit a67139eb8d
5 changed files with 224 additions and 163 deletions

View File

@ -258,6 +258,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM9712 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW)
select SND_SOC_WM9713 if (SND_SOC_AC97_BUS || SND_SOC_AC97_BUS_NEW)
select SND_SOC_RPMSG_WM8960
select SND_SOC_RPMSG_WM8960_I2C
select SND_SOC_RPMSG_CS42XX8
select SND_SOC_RPMSG_AK4497
help
@ -1443,7 +1444,11 @@ config SND_SOC_ZX_AUD96P22
select REGMAP_I2C
config SND_SOC_RPMSG_WM8960
tristate
tristate "RPMSG WM8960 Platform Driver"
select SND_SOC_RPMSG_WM8960_I2C
config SND_SOC_RPMSG_WM8960_I2C
tristate "RPMSG WM8960 I2C Driver"
config SND_SOC_RPMSG_CS42XX8
tristate

View File

@ -276,6 +276,7 @@ snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-zx-aud96p22-objs := zx_aud96p22.o
snd-soc-rpmsg-wm8960-objs := rpmsg_wm8960.o
snd-soc-rpmsg-wm8960-i2c-objs := rpmsg_wm8960_i2c.o
snd-soc-rpmsg-cs42xx8-objs := rpmsg_cs42xx8.o
snd-soc-rpmsg-ak4497-objs := rpmsg_ak4497.o
@ -564,6 +565,7 @@ obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o
obj-$(CONFIG_SND_SOC_RPMSG_WM8960) += snd-soc-rpmsg-wm8960.o
obj-$(CONFIG_SND_SOC_RPMSG_WM8960_I2C) += snd-soc-rpmsg-wm8960-i2c.o
obj-$(CONFIG_SND_SOC_RPMSG_CS42XX8) += snd-soc-rpmsg-cs42xx8.o
obj-$(CONFIG_SND_SOC_RPMSG_AK4497) += snd-soc-rpmsg-ak4497.o

View File

@ -27,26 +27,7 @@
#include <sound/wm8960.h>
#include "../fsl/fsl_rpmsg_i2s.h"
#include "wm8960.h"
/* R25 - Power 1 */
#define WM8960_VMID_MASK 0x180
#define WM8960_VREF 0x40
/* R26 - Power 2 */
#define WM8960_PWR2_LOUT1 0x40
#define WM8960_PWR2_ROUT1 0x20
#define WM8960_PWR2_OUT3 0x02
/* R28 - Anti-pop 1 */
#define WM8960_POBCTRL 0x80
#define WM8960_BUFDCOPEN 0x10
#define WM8960_BUFIOEN 0x08
#define WM8960_SOFT_ST 0x04
#define WM8960_HPSTBY 0x01
/* R29 - Anti-pop 2 */
#define WM8960_DISOP 0x40
#define WM8960_DRES_MASK 0x30
#include "rpmsg_wm8960.h"
static bool is_pll_freq_available(unsigned int source, unsigned int target);
static int wm8960_set_pll(struct snd_soc_component *component,
@ -110,26 +91,6 @@ static const struct reg_default wm8960_reg_defaults[] = {
{ 0x37, 0x00e9 },
};
struct rpmsg_wm8960_priv {
struct clk *mclk;
struct regmap *regmap;
int (*set_bias_level)(struct snd_soc_component *,
enum snd_soc_bias_level level);
struct snd_soc_dapm_widget *lout1;
struct snd_soc_dapm_widget *rout1;
struct snd_soc_dapm_widget *out3;
bool deemph;
int lrclk;
int bclk;
int sysclk;
int clk_id;
int freq_in;
bool is_stream_in_use[2];
struct wm8960_data pdata;
struct fsl_rpmsg_i2s *rpmsg_i2s;
int audioindex;
};
static bool wm8960_volatile(struct device *dev, unsigned int reg)
{
struct rpmsg_wm8960_priv *wm8960 = dev_get_drvdata(dev);
@ -145,7 +106,6 @@ static bool wm8960_volatile(struct device *dev, unsigned int reg)
}
}
#define wm8960_reset(c) regmap_write(c, WM8960_RESET, 0)
/* enumerated controls */
static const char * const wm8960_polarity[] = {"No Inversion", "Left Inverted",
@ -1315,7 +1275,7 @@ static const struct snd_soc_dai_ops rpmsg_wm8960_dai_ops = {
.set_sysclk = wm8960_set_dai_sysclk,
};
static struct snd_soc_dai_driver rpmsg_wm8960_codec_dai = {
struct snd_soc_dai_driver rpmsg_wm8960_codec_dai = {
.name = "rpmsg-wm8960-hifi",
.playback = {
.stream_name = "Playback",
@ -1334,6 +1294,7 @@ static struct snd_soc_dai_driver rpmsg_wm8960_codec_dai = {
.ops = &rpmsg_wm8960_dai_ops,
.symmetric_rates = 1,
};
EXPORT_SYMBOL(rpmsg_wm8960_codec_dai);
static int rpmsg_wm8960_probe(struct snd_soc_component *component)
{
@ -1401,13 +1362,14 @@ static int rpmsg_wm8960_write(void *context, unsigned int reg, unsigned int val)
return 0;
}
static const struct snd_soc_component_driver rpmsg_wm8960_component = {
const struct snd_soc_component_driver rpmsg_wm8960_component = {
.probe = rpmsg_wm8960_probe,
.set_bias_level = wm8960_set_bias_level,
.suspend_bias_off = 1,
};
EXPORT_SYMBOL(rpmsg_wm8960_component);
static struct regmap_config rpmsg_wm8960_regmap = {
struct regmap_config rpmsg_wm8960_regmap = {
.reg_bits = 7,
.val_bits = 9,
.max_register = WM8960_PLL4,
@ -1420,6 +1382,7 @@ static struct regmap_config rpmsg_wm8960_regmap = {
.reg_read = rpmsg_wm8960_read,
.reg_write = rpmsg_wm8960_write,
};
EXPORT_SYMBOL(rpmsg_wm8960_regmap);
#ifdef CONFIG_PM
static int wm8960_runtime_resume(struct device *dev)
@ -1545,123 +1508,5 @@ static struct platform_driver rpmsg_wm8960_codec_driver = {
module_platform_driver(rpmsg_wm8960_codec_driver);
static void rpmsg_wm8960_set_pdata_from_of(struct i2c_client *i2c,
struct wm8960_data *pdata)
{
const struct device_node *np = i2c->dev.of_node;
if (of_property_read_bool(np, "wlf,capless"))
pdata->capless = true;
if (of_property_read_bool(np, "wlf,shared-lrclk"))
pdata->shared_lrclk = true;
}
static int rpmsg_wm8960_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct rpmsg_wm8960_priv *wm8960;
int ret;
int repeat_reset = 10;
wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct rpmsg_wm8960_priv),
GFP_KERNEL);
if (wm8960 == NULL)
return -ENOMEM;
wm8960->mclk = devm_clk_get(&i2c->dev, "mclk");
if (IS_ERR(wm8960->mclk)) {
if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
}
rpmsg_wm8960_regmap.reg_read = NULL;
rpmsg_wm8960_regmap.reg_write = NULL;
wm8960->regmap = devm_regmap_init_i2c(i2c, &rpmsg_wm8960_regmap);
if (IS_ERR(wm8960->regmap))
return PTR_ERR(wm8960->regmap);
if (pdata)
memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));
else if (i2c->dev.of_node)
rpmsg_wm8960_set_pdata_from_of(i2c, &wm8960->pdata);
i2c_set_clientdata(i2c, wm8960);
do {
ret = wm8960_reset(wm8960->regmap);
repeat_reset--;
} while (repeat_reset > 0 && ret != 0);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
return ret;
}
if (wm8960->pdata.shared_lrclk) {
ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2,
0x4, 0x4);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable LRCM: %d\n",
ret);
return ret;
}
}
/* Latch the update bits */
regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RINVOL, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LADC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RADC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LDAC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RDAC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LOUT1, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT1, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100);
/*
* codec ADCLRC pin configured as GPIO, DACLRC pin is used as a frame
* clock for ADCs and DACs
*/
regmap_update_bits(wm8960->regmap, WM8960_IFACE2, 1<<6, 1<<6);
ret = devm_snd_soc_register_component(&i2c->dev,
&rpmsg_wm8960_component, &rpmsg_wm8960_codec_dai, 1);
return ret;
}
static int rpmsg_wm8960_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id rpmsg_wm8960_i2c_id[] = {
{ "wm8960", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
static const struct of_device_id rpmsg_wm8960_of_match[] = {
{ .compatible = "wlf,wm8960,lpa", },
{ }
};
MODULE_DEVICE_TABLE(of, rpmsg_wm8960_of_match);
static struct i2c_driver rpmsg_wm8960_i2c_driver = {
.driver = {
.name = RPMSG_CODEC_DRV_NAME_WM8960,
.of_match_table = rpmsg_wm8960_of_match,
},
.probe = rpmsg_wm8960_i2c_probe,
.remove = rpmsg_wm8960_i2c_remove,
.id_table = rpmsg_wm8960_i2c_id,
};
module_i2c_driver(rpmsg_wm8960_i2c_driver);
MODULE_DESCRIPTION("rpmsg wm8960 Codec Driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Audio driver for RPMSG WM8960
*
* Copyright 2007-11 Wolfson Microelectronics, plc
* Copyright 2020 NXP
*/
#ifndef _RPMSG_WM8960_H
#define _RPMSG_WM8960_H
/* R25 - Power 1 */
#define WM8960_VMID_MASK 0x180
#define WM8960_VREF 0x40
/* R26 - Power 2 */
#define WM8960_PWR2_LOUT1 0x40
#define WM8960_PWR2_ROUT1 0x20
#define WM8960_PWR2_OUT3 0x02
/* R28 - Anti-pop 1 */
#define WM8960_POBCTRL 0x80
#define WM8960_BUFDCOPEN 0x10
#define WM8960_BUFIOEN 0x08
#define WM8960_SOFT_ST 0x04
#define WM8960_HPSTBY 0x01
/* R29 - Anti-pop 2 */
#define WM8960_DISOP 0x40
#define WM8960_DRES_MASK 0x30
#define wm8960_reset(c) regmap_write(c, WM8960_RESET, 0)
struct rpmsg_wm8960_priv {
struct clk *mclk;
struct regmap *regmap;
int (*set_bias_level)(struct snd_soc_component *,
enum snd_soc_bias_level level);
struct snd_soc_dapm_widget *lout1;
struct snd_soc_dapm_widget *rout1;
struct snd_soc_dapm_widget *out3;
bool deemph;
int lrclk;
int bclk;
int sysclk;
int clk_id;
int freq_in;
bool is_stream_in_use[2];
struct wm8960_data pdata;
struct fsl_rpmsg_i2s *rpmsg_i2s;
int audioindex;
};
#endif

View File

@ -0,0 +1,155 @@
/*
* Copyright 2020 NXP
*
* Copyright 2007-11 Wolfson Microelectronics, plc
*
* Author: Liam Girdwood
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/pm_runtime.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <sound/wm8960.h>
#include "../fsl/fsl_rpmsg_i2s.h"
#include "wm8960.h"
#include "rpmsg_wm8960.h"
extern struct regmap_config rpmsg_wm8960_regmap;
extern const struct snd_soc_component_driver rpmsg_wm8960_component;
extern struct snd_soc_dai_driver rpmsg_wm8960_codec_dai;
static void rpmsg_wm8960_set_pdata_from_of(struct i2c_client *i2c,
struct wm8960_data *pdata)
{
const struct device_node *np = i2c->dev.of_node;
if (of_property_read_bool(np, "wlf,capless"))
pdata->capless = true;
if (of_property_read_bool(np, "wlf,shared-lrclk"))
pdata->shared_lrclk = true;
}
static int rpmsg_wm8960_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct rpmsg_wm8960_priv *wm8960;
int ret;
int repeat_reset = 10;
wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct rpmsg_wm8960_priv),
GFP_KERNEL);
if (wm8960 == NULL)
return -ENOMEM;
wm8960->mclk = devm_clk_get(&i2c->dev, "mclk");
if (IS_ERR(wm8960->mclk)) {
if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
}
rpmsg_wm8960_regmap.reg_read = NULL;
rpmsg_wm8960_regmap.reg_write = NULL;
wm8960->regmap = devm_regmap_init_i2c(i2c, &rpmsg_wm8960_regmap);
if (IS_ERR(wm8960->regmap))
return PTR_ERR(wm8960->regmap);
if (pdata)
memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));
else if (i2c->dev.of_node)
rpmsg_wm8960_set_pdata_from_of(i2c, &wm8960->pdata);
i2c_set_clientdata(i2c, wm8960);
do {
ret = wm8960_reset(wm8960->regmap);
repeat_reset--;
} while (repeat_reset > 0 && ret != 0);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
return ret;
}
if (wm8960->pdata.shared_lrclk) {
ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2,
0x4, 0x4);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable LRCM: %d\n",
ret);
return ret;
}
}
/* Latch the update bits */
regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RINVOL, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LADC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RADC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LDAC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_RDAC, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LOUT1, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT1, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100);
regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100);
/*
* codec ADCLRC pin configured as GPIO, DACLRC pin is used as a frame
* clock for ADCs and DACs
*/
regmap_update_bits(wm8960->regmap, WM8960_IFACE2, 1<<6, 1<<6);
ret = devm_snd_soc_register_component(&i2c->dev,
&rpmsg_wm8960_component, &rpmsg_wm8960_codec_dai, 1);
return ret;
}
static int rpmsg_wm8960_i2c_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id rpmsg_wm8960_i2c_id[] = {
{ "wm8960", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rpmsg_wm8960_i2c_id);
static const struct of_device_id rpmsg_wm8960_of_match[] = {
{ .compatible = "wlf,wm8960,lpa", },
{ }
};
MODULE_DEVICE_TABLE(of, rpmsg_wm8960_of_match);
static struct i2c_driver rpmsg_wm8960_i2c_driver = {
.driver = {
.name = RPMSG_CODEC_DRV_NAME_WM8960,
.of_match_table = rpmsg_wm8960_of_match,
},
.probe = rpmsg_wm8960_i2c_probe,
.remove = rpmsg_wm8960_i2c_remove,
.id_table = rpmsg_wm8960_i2c_id,
};
module_i2c_driver(rpmsg_wm8960_i2c_driver);
MODULE_DESCRIPTION("rpmsg wm8960 I2C Codec Driver");
MODULE_LICENSE("GPL v2");