kernel_samsung_a53x/sound/soc/samsung/slif/slif_soc.c
2024-06-15 16:02:09 -03:00

1829 lines
49 KiB
C
Executable file

/* sound/soc/samsung/vts/slif.c
*
* ALSA SoC - Samsung VTS Serial Local Interface driver
*
* Copyright (c) 2019 Samsung Electronics Co. Ltd.
*
* 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.
*/
/* #define DEBUG */
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/pm_runtime.h>
#include <linux/firmware.h>
#include <linux/dma-mapping.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/sched/clock.h>
#include <linux/miscdevice.h>
#include <asm-generic/delay.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include <sound/samsung/mailbox.h>
#include <sound/samsung/vts.h>
#include <sound/samsung/abox.h>
#include <soc/samsung/exynos-pmu-if.h>
#include <soc/samsung/exynos-el3_mon.h>
#include "slif.h"
#include "slif_soc.h"
#include "slif_nm.h"
#include "slif_clk_table.h"
#include "slif_memlog.h"
#define vts_set_mask_value(id, mask, value) \
{id = (typeof(id))((id & ~mask) | (value & mask)); }
#define vts_set_value_by_name(id, name, value) \
vts_set_mask_value(id, name##_MASK, value << name##_L)
#define SLIF_USE_AUD0
/* #define SLIF_REG_LOW_CTRL */
void slif_debug_pad_en(int en)
{
/*Legacy Debugging Function*/
}
#ifdef SLIF_REG_LOW_CTRL
static void slif_check_reg(int cmd)
{
volatile unsigned long rco_reg;
volatile unsigned long gpv0_con;
volatile unsigned long sysreg_vts;
volatile unsigned long dmic_aud0;
volatile unsigned long dmic_aud1;
volatile unsigned long dmic_aud2;
volatile unsigned long serial_lif;
volatile unsigned long div_ratio;
volatile unsigned long cmu_aud;
#if 0
{
volatile unsigned long clk_con;
clk_con =
(volatile unsigned long)ioremap_wt(0x18C00000, 0x2000);
pr_info("clk_con(0x1038) 0x%08x\n",
readl((volatile void *)(clk_con + 0x1038)));
if (cmd == 1) {
unsigned int val = 0;
/* CLK_CON_MUX_MUX_CLK_AUD_UAIF6 : 0x18C0_0000 + 0x1038 */
val = readl((volatile void *)(clk_con + 0x1038));
val &= ~(0x7 << 0);
/* IOCLK_AUDIOCDCLK6 = 4 */
val |= (4 << 0);
writel(val, (volatile void *)(clk_con + 0x1038));
}
pr_info("clk_con(0x1038) 0x%08x\n",
readl((volatile void *)(clk_con + 0x1038)));
iounmap((volatile void __iomem *)clk_con);
}
#endif
{
volatile unsigned long sysreg_aud;
sysreg_aud =
(volatile unsigned long)ioremap_wt(0x18C10000, 0x1000);
if (cmd == 1) {
writel(0x7, (volatile void *)(sysreg_aud + 0x520));
}
pr_info("sysreg_aud(0x520) 0x%08x\n",
readl((volatile void *)(sysreg_aud + 0x520)));
pr_info("sysreg_aud(0x504) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(sysreg_aud + 0x504)),
readl((volatile void *)(sysreg_aud + 0x508)),
readl((volatile void *)(sysreg_aud + 0x50C)),
readl((volatile void *)(sysreg_aud + 0x520)));
pr_info("sysreg_aud(0x530) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(sysreg_aud + 0x530)),
readl((volatile void *)(sysreg_aud + 0x534)),
readl((volatile void *)(sysreg_aud + 0x538)),
readl((volatile void *)(sysreg_aud + 0x53C)));
iounmap((volatile void __iomem *)sysreg_aud);
}
printk("%s : %d\n", __func__, __LINE__);
/* check rco */
rco_reg =
(volatile unsigned long)ioremap_wt(0x15860000, 0x1000);
pr_info("rco_reg : 0x%8x\n",
readl((volatile void *)(rco_reg + 0xb00)));
iounmap((volatile void __iomem *)rco_reg);
/* check gpv0 */
gpv0_con =
(volatile unsigned long)ioremap_wt(0x15580000, 0x1000);
pr_info("gpv0_con(0x00) 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(gpv0_con + 0x0)),
readl((volatile void *)(gpv0_con + 0x4)),
readl((volatile void *)(gpv0_con + 0x8)));
pr_info("gpv0_con(0x10) 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(gpv0_con + 0x10)),
readl((volatile void *)(gpv0_con + 0x14)),
readl((volatile void *)(gpv0_con + 0x18)));
pr_info("gpv0_con(0x20) 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(gpv0_con + 0x20)),
readl((volatile void *)(gpv0_con + 0x24)),
readl((volatile void *)(gpv0_con + 0x28)));
iounmap((volatile void __iomem *)gpv0_con);
/* check sysreg_vts */
sysreg_vts =
(volatile unsigned long)ioremap_wt(0x15510000, 0x2000);
pr_info("sysreg_vts(0x940, 0x944, 0x1010) 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(sysreg_vts + 0x940)),
readl((volatile void *)(sysreg_vts + 0x944)),
readl((volatile void *)(sysreg_vts + 0x1010)));
pr_info("sysreg_vts(0x0108) 0x%08x\n",
readl((volatile void *)(sysreg_vts + 0x108)));
iounmap((volatile void __iomem *)sysreg_vts);
/* check dmic_aud0 *//* undescribed register */
dmic_aud0 =
/* (volatile unsigned long)ioremap_wt(0x15350000, 0x10); */
(volatile unsigned long)ioremap_wt(0x18F60000, 0x10);
pr_info("vts_dmic_aud0(0x0) 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
readl((volatile void *)(dmic_aud0 + 0x0)),
readl((volatile void *)(dmic_aud0 + 0x4)),
readl((volatile void *)(dmic_aud0 + 0x8)),
readl((volatile void *)(dmic_aud0 + 0xC)),
readl((volatile void *)(dmic_aud0 + 0x10)));
iounmap((volatile void __iomem *)dmic_aud0);
/* check dmic_aud1 */
dmic_aud1 =
/* (volatile unsigned long)ioremap_wt(0x15360000, 0x10); */
(volatile unsigned long)ioremap_wt(0x18F70000, 0x10);
pr_info("vts_dmic_aud1(0x1) 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
readl((volatile void *)(dmic_aud1 + 0x0)),
readl((volatile void *)(dmic_aud1 + 0x4)),
readl((volatile void *)(dmic_aud1 + 0x8)),
readl((volatile void *)(dmic_aud1 + 0xC)),
readl((volatile void *)(dmic_aud1 + 0x10)));
iounmap((volatile void __iomem *)dmic_aud1);
/* check dmic_aud2 */
dmic_aud2 =
/* (volatile unsigned long)ioremap_wt(0x15370000, 0x10); */
(volatile unsigned long)ioremap_wt(0x18F80000, 0x10);
pr_info("vts_dmic_aud2(0x2) 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
readl((volatile void *)(dmic_aud2 + 0x0)),
readl((volatile void *)(dmic_aud2 + 0x4)),
readl((volatile void *)(dmic_aud2 + 0x8)),
readl((volatile void *)(dmic_aud2 + 0xC)),
readl((volatile void *)(dmic_aud2 + 0x10)));
iounmap((volatile void __iomem *)dmic_aud2);
/* check serial lif */
serial_lif =
/* (volatile unsigned long)ioremap_wt(0x15340100, 0x1000); */
(volatile unsigned long)ioremap_wt(0x18F50100, 0x1000);
pr_info("slif(0x000) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(serial_lif + 0x0)),
readl((volatile void *)(serial_lif + 0x4)),
readl((volatile void *)(serial_lif + 0x8)),
readl((volatile void *)(serial_lif + 0xC)));
pr_info("slif(0x010) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(serial_lif + 0x10)),
readl((volatile void *)(serial_lif + 0x14)),
readl((volatile void *)(serial_lif + 0x18)),
readl((volatile void *)(serial_lif + 0x1C)));
pr_info("slif(0x020) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(serial_lif + 0x20)),
readl((volatile void *)(serial_lif + 0x24)),
readl((volatile void *)(serial_lif + 0x28)),
readl((volatile void *)(serial_lif + 0x2C)));
pr_info("slif(0x030) 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(serial_lif + 0x30)),
readl((volatile void *)(serial_lif + 0x34)),
readl((volatile void *)(serial_lif + 0x38)));
pr_info("slif(0x050) 0x%08x \n",
readl((volatile void *)(serial_lif + 0x50)));
pr_info("slif(0x300) 0x%08x\n",
readl((volatile void *)(serial_lif + 0x300)));
iounmap((volatile void __iomem *)serial_lif);
/* check dividr */
div_ratio =
(volatile unsigned long)ioremap_wt(0x15500000, 0x2000);
pr_info("vts_div_ratio(0x1804) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(div_ratio + 0x1804)),
readl((volatile void *)(div_ratio + 0x1808)),
readl((volatile void *)(div_ratio + 0x1818)),
readl((volatile void *)(div_ratio + 0x181c)));
pr_info("vts_div_ratio(0x181c) 0x%08x 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(div_ratio + 0x1804)),
readl((volatile void *)(div_ratio + 0x1808)),
readl((volatile void *)(div_ratio + 0x1818)),
readl((volatile void *)(div_ratio + 0x181c)));
iounmap((volatile void __iomem *)div_ratio);
/* check cmu_aud */
cmu_aud =
(volatile unsigned long)ioremap_wt(0x18c00000, 0x4000);
pr_info("cmu_aud(0x18c03008) 0x%08x 0x%08x 0x%08x\n",
readl((volatile void *)(cmu_aud + 0x3008)),
readl((volatile void *)(cmu_aud + 0x300c)),
readl((volatile void *)(cmu_aud + 0x3010)));
iounmap((volatile void __iomem *)cmu_aud);
}
#endif
static u32 slif_direct_readl(const volatile void __iomem *addr)
{
u32 ret = readl(addr);
return ret;
}
static void slif_direct_writel(u32 b, volatile void __iomem *addr)
{
writel(b, addr);
}
/* private functions */
static void slif_soc_reset_status(struct slif_data *data)
{
/* set_bit(0, &data->mode); */
data->enabled = 0;
data->running = 0;
/* data->state = 0; */
/* data->fmt = -1 */;
}
static void slif_soc_set_default_gain(struct slif_data *data)
{
int i;
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
data->gain_mode[i] = SLIF_DEFAULT_GAIN_MODE;
data->max_scale_gain[i] = SLIF_DEFAULT_MAX_SCALE_GAIN;
data->control_dmic_aud[i] = SLIF_DEFAULT_CONTROL_DMIC_AUD;
slif_soc_dmic_aud_gain_mode_write(data, i);
slif_soc_dmic_aud_max_scale_gain_write(data, i);
slif_soc_dmic_aud_control_gain_write(data, i);
}
}
static void slif_soc_set_dmic_aud(struct slif_data *data, int enable)
{
int i;
if (enable) {
#if (SLIF_SOC_VERSION(1, 0, 0) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
slif_direct_writel(0x80030000, data->dmic_aud[i] + 0x0);
}
#elif (SLIF_SOC_VERSION(1, 1, 1) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
slif_direct_writel(0xA0030000, data->dmic_aud[i] + 0x0);
}
#elif (SLIF_SOC_VERSION(1, 1, 2) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
slif_direct_writel(0xA0030000, data->dmic_aud[i] + 0x0);
}
#else
#error "SLIF_SOC_VERSION is not defined"
#endif
} else {
}
}
static void __maybe_unused slif_soc_set_sel_pad(struct slif_data *data, int enable)
{
struct device *dev = data->dev;
unsigned int ctrl;
if (enable) {
slif_direct_writel(0x7, data->sfr_sys_base +
SLIF_SEL_PAD_AUD_BASE);
ctrl = slif_direct_readl(data->sfr_sys_base +
SLIF_SEL_PAD_AUD_BASE);
slif_info(dev, "SEL_PAD_AUD(0x%08x)\n", ctrl);
slif_direct_writel(0x38, data->sfr_sys_base +
SLIF_SEL_DIV2_CLK_BASE);
ctrl = slif_direct_readl(data->sfr_sys_base +
SLIF_SEL_DIV2_CLK_BASE);
slif_info(dev, "SEL_DIV2_CLK(0x%08x)\n", ctrl);
} else {
slif_direct_writel(0, data->sfr_sys_base +
SLIF_SEL_PAD_AUD_BASE);
ctrl = slif_direct_readl(data->sfr_sys_base +
SLIF_SEL_PAD_AUD_BASE);
slif_info(dev, "SEL_PAD_AUD(0x%08x)\n", ctrl);
slif_direct_writel(0, data->sfr_sys_base +
SLIF_SEL_DIV2_CLK_BASE);
ctrl = slif_direct_readl(data->sfr_sys_base +
SLIF_SEL_DIV2_CLK_BASE);
slif_info(dev, "SEL_DIV2_CLK(0x%08x)\n", ctrl);
}
}
/* public functions */
int slif_soc_dmic_aud_gain_mode_write(struct slif_data *data,
unsigned int id)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
int ret = 0;
ret = regmap_write(regmap,
SLIF_SFR_GAIN_MODE_BASE,
data->gain_mode[id]);
if (ret < 0)
slif_err(dev, "Failed to write GAIN_MODE(%d): %d\n",
id, data->gain_mode[id]);
return ret;
}
int slif_soc_dmic_aud_gain_mode_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
int ret = 0;
ret = regmap_read(regmap,
SLIF_SFR_GAIN_MODE_BASE,
&data->gain_mode[id]);
if (ret < 0)
slif_err(dev, "Failed to get GAIN_MODE(%d): %d\n",
id, data->gain_mode[id]);
*val = data->gain_mode[id];
return ret;
}
int slif_soc_dmic_aud_gain_mode_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
int ret = 0;
data->gain_mode[id] = val;
ret = slif_soc_dmic_aud_gain_mode_write(data, id);
return ret;
}
int slif_soc_dmic_aud_max_scale_gain_write(struct slif_data *data,
unsigned int id)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
int ret = 0;
ret = regmap_write(regmap,
SLIF_SFR_MAX_SCALE_GAIN_BASE,
data->max_scale_gain[id]);
if (ret < 0)
slif_err(dev, "Failed to write MAX_SCALE_GAIN(%d): %d\n",
id, data->max_scale_gain[id]);
return ret;
}
int slif_soc_dmic_aud_max_scale_gain_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
int ret = 0;
ret = regmap_read(regmap,
SLIF_SFR_MAX_SCALE_GAIN_BASE,
&data->max_scale_gain[id]);
if (ret < 0)
slif_err(dev, "Failed to get MAX_SCALE_GAIN(%d): %d\n",
id, data->max_scale_gain[id]);
*val = data->max_scale_gain[id];
return ret;
}
int slif_soc_dmic_aud_max_scale_gain_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
int ret = 0;
data->max_scale_gain[id] = val;
ret = slif_soc_dmic_aud_max_scale_gain_write(data, id);
return ret;
}
int slif_soc_dmic_aud_control_gain_write(struct slif_data *data,
unsigned int id)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
int ret = 0;
ret = regmap_write(regmap,
SLIF_SFR_CONTROL_DMIC_AUD_BASE,
data->control_dmic_aud[id]);
if (ret < 0)
slif_err(dev, "Failed to write CONTROL_DMIC_AUD(%d): %d\n",
id, data->control_dmic_aud[id]);
return ret;
}
int slif_soc_dmic_aud_control_gain_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
unsigned int mask = 0;
int ret = 0;
ret = regmap_read(regmap,
SLIF_SFR_CONTROL_DMIC_AUD_BASE,
&data->control_dmic_aud[id]);
if (ret < 0)
slif_err(dev, "Failed to get CONTROL_DMIC_AUD(%d): %d\n",
id, data->control_dmic_aud[id]);
mask = SLIF_SFR_CONTROL_DMIC_AUD_GAIN_MASK;
*val = ((data->control_dmic_aud[id] & mask) >>
SLIF_SFR_CONTROL_DMIC_AUD_GAIN_L);
slif_dbg(dev, "mask 0x%x\n", mask);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
slif_dbg(dev, "val 0x%x \n", *val);
return ret;
}
int slif_soc_dmic_aud_control_gain_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
struct device *dev = data->dev;
unsigned int mask = 0;
unsigned int value = 0;
int ret = 0;
mask = SLIF_SFR_CONTROL_DMIC_AUD_GAIN_MASK;
value = (val << SLIF_SFR_CONTROL_DMIC_AUD_GAIN_L) & mask;
data->control_dmic_aud[id] &= ~mask;
data->control_dmic_aud[id] |= value;
slif_dbg(dev, "mask 0x%x val 0x%x value 0x%x\n",
mask, val, value);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
ret = slif_soc_dmic_aud_control_gain_write(data, id);
return ret;
}
int slif_soc_vol_set_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
unsigned int volumes;
int ret = 0;
ctrl = snd_soc_component_read(cmpnt, SLIF_VOL_SET(id));
volumes = (ctrl & SLIF_VOL_SET_MASK);
slif_dbg(dev, "(0x%08x, %u)\n", id, volumes);
*val = volumes;
return ret;
}
int slif_soc_vol_set_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
int ret = 0;
ret = snd_soc_component_update_bits(cmpnt,
SLIF_VOL_SET(id),
SLIF_VOL_SET_MASK,
val << SLIF_VOL_SET_L);
slif_dbg(dev, "(0x%08x, %u)\n", id, val);
return ret;
}
int slif_soc_vol_change_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
unsigned int volumes;
int ret = 0;
ctrl = snd_soc_component_read(cmpnt, SLIF_VOL_CHANGE(id));
volumes = (ctrl & SLIF_VOL_CHANGE_MASK);
slif_dbg(dev, "(0x%08x, %u)\n", id, volumes);
*val = volumes;
return ret;
}
int slif_soc_vol_change_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
int ret = 0;
ret = snd_soc_component_update_bits(cmpnt,
SLIF_VOL_CHANGE(id),
SLIF_VOL_CHANGE_MASK,
val << SLIF_VOL_CHANGE_L);
if (ret < 0)
slif_err(dev, "failed:%d\n", ret);
slif_dbg(dev, "(0x%08x, %u)\n", id, val);
return ret;
}
int slif_soc_channel_map_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
#if (SLIF_SOC_VERSION(1, 0, 0) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
return 0;
#elif (SLIF_SOC_VERSION(1, 1, 1) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
unsigned int channel_map;
unsigned int channel_map_mask;
int ret = 0;
if (id > 7) {
slif_err(dev, "id(%d) is not valid\n", id);
return -EINVAL;
}
ctrl = snd_soc_component_read(cmpnt, SLIF_CHANNEL_MAP_BASE);
channel_map_mask = SLIF_CHANNEL_MAP_MASK(id);
channel_map = ((ctrl & channel_map_mask) >>
(SLIF_CHANNEL_MAP_ITV * id));
slif_dbg(dev, "(0x%08x 0x%08x)\n", ctrl, channel_map_mask);
slif_dbg(dev, "(%d, 0x%08x)\n", id, channel_map);
*val = channel_map;
data->channel_map = ctrl;
return ret;
#elif (SLIF_SOC_VERSION(1, 1, 2) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
unsigned int channel_map;
unsigned int channel_map_mask;
int ret = 0;
if (id > 7) {
slif_err(dev, "id(%d) is not valid\n", id);
return -EINVAL;
}
ctrl = snd_soc_component_read(cmpnt, SLIF_CHANNEL_MAP_BASE);
channel_map_mask = SLIF_CHANNEL_MAP_MASK(id);
channel_map = ((ctrl & channel_map_mask) >>
(SLIF_CHANNEL_MAP_ITV * id));
slif_dbg(dev, "(0x%08x 0x%08x)\n", ctrl, channel_map_mask);
slif_dbg(dev, "(%d, 0x%08x)\n", id, channel_map);
*val = channel_map;
data->channel_map = ctrl;
return ret;
#endif
}
int slif_soc_channel_map_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
#if (SLIF_SOC_VERSION(1, 0, 0) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
return 0;
#elif (SLIF_SOC_VERSION(1, 1, 1) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
int ret = 0;
if (id > 7) {
slif_err(dev, "id(%d) is not valid\n", id);
return -EINVAL;
}
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CHANNEL_MAP_BASE,
SLIF_CHANNEL_MAP_MASK(id),
val << (SLIF_CHANNEL_MAP_ITV * id));
if (ret < 0)
slif_err(dev, "failed: %d\n", ret);
data->channel_map = snd_soc_component_read(cmpnt,
SLIF_CHANNEL_MAP_BASE);
slif_info(dev, "(0x%08x, 0x%x)\n", id, data->channel_map);
return ret;
#elif (SLIF_SOC_VERSION(1, 1, 2) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
int ret = 0;
if (id > 7) {
slif_err(dev, "id(%d) is not valid\n", id);
return -EINVAL;
}
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CHANNEL_MAP_BASE,
SLIF_CHANNEL_MAP_MASK(id),
val << (SLIF_CHANNEL_MAP_ITV * id));
if (ret < 0)
slif_err(dev, "failed:%d\n", ret);
data->channel_map = snd_soc_component_read(cmpnt,
SLIF_CHANNEL_MAP_BASE);
slif_info(dev, "(0x%08x, 0x%x)\n", id, data->channel_map);
return ret;
#endif
}
int slif_soc_dmic_aud_control_hpf_sel_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
unsigned int mask = 0;
int ret = 0;
ret = regmap_read(regmap,
SLIF_SFR_CONTROL_DMIC_AUD_BASE,
&data->control_dmic_aud[id]);
if (ret < 0)
slif_err(dev, "Failed to get HPF_SEL(%d): %d\n",
id, data->control_dmic_aud[id]);
mask = SLIF_SFR_CONTROL_DMIC_AUD_HPF_SEL_MASK;
*val = ((data->control_dmic_aud[id] & mask) >>
SLIF_SFR_CONTROL_DMIC_AUD_HPF_SEL_L);
slif_dbg(dev, "mask 0x%x\n", mask);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
slif_dbg(dev, "val 0x%x \n", *val);
return ret;
}
int slif_soc_dmic_aud_control_hpf_sel_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
struct device *dev = data->dev;
unsigned int mask = 0;
unsigned int value = 0;
int ret = 0;
mask = SLIF_SFR_CONTROL_DMIC_AUD_HPF_SEL_MASK;
value = (val << SLIF_SFR_CONTROL_DMIC_AUD_HPF_SEL_L) & mask;
data->control_dmic_aud[id] &= ~mask;
data->control_dmic_aud[id] |= value;
slif_dbg(dev, "mask 0x%x val 0x%x value 0x%x\n",
mask, val, value);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
ret = slif_soc_dmic_aud_control_gain_write(data, id);
return ret;
}
int slif_soc_dmic_aud_control_hpf_en_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
struct device *dev = data->dev;
struct regmap *regmap = data->regmap_dmic_aud[id];
unsigned int mask = 0;
int ret = 0;
ret = regmap_read(regmap,
SLIF_SFR_CONTROL_DMIC_AUD_BASE,
&data->control_dmic_aud[id]);
if (ret < 0)
slif_err(dev, "Failed to get HPF_EN(%d): %d\n",
id, data->control_dmic_aud[id]);
mask = SLIF_SFR_CONTROL_DMIC_AUD_HPF_EN_MASK;
*val = ((data->control_dmic_aud[id] & mask) >>
SLIF_SFR_CONTROL_DMIC_AUD_HPF_EN_L);
slif_dbg(dev, "mask 0x%x\n", mask);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
slif_dbg(dev, "val 0x%x \n", *val);
return ret;
}
int slif_soc_dmic_aud_control_hpf_en_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
struct device *dev = data->dev;
unsigned int mask = 0;
unsigned int value = 0;
int ret = 0;
mask = SLIF_SFR_CONTROL_DMIC_AUD_HPF_EN_MASK;
value = (val << SLIF_SFR_CONTROL_DMIC_AUD_HPF_EN_L) & mask;
data->control_dmic_aud[id] &= ~mask;
data->control_dmic_aud[id] |= value;
slif_dbg(dev, "mask 0x%x val 0x%x value 0x%x\n",
mask, val, value);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
ret = slif_soc_dmic_aud_control_gain_write(data, id);
return ret;
}
int slif_soc_dmic_en_get(struct slif_data *data,
unsigned int id, unsigned int *val)
{
int ret = 0;
*val = data->dmic_en[id];
return ret;
}
int slif_soc_dmic_en_put(struct slif_data *data,
unsigned int port, unsigned int val, bool update)
{
struct device *dev = data->dev;
if (update)
data->dmic_en[port] = val;
slif_info(dev, "port%d id%d PDM%d val%d\n",
port, VTS_PORT_ID_SLIF, DPDM, val);
if (!test_bit(SLIF_STATE_OPENED, &data->state)) {
slif_info(dev, "not powered\n");
return 0;
} else {
if (!data->dev_vts)
return -ENODEV;
return vts_port_cfg(data->dev_vts, port,
VTS_PORT_ID_SLIF, DPDM, !!val);
}
}
int slif_soc_dmic_aud_control_sys_sel_put(struct slif_data *data,
unsigned int id, unsigned int val)
{
struct device *dev = data->dev;
unsigned int mask = 0;
unsigned int value = 0;
int ret = 0;
mask = SLIF_SFR_CONTROL_DMIC_AUD_SYS_SEL_MASK;
value = (val << SLIF_SFR_CONTROL_DMIC_AUD_SYS_SEL_L) & mask;
data->control_dmic_aud[id] &= ~mask;
data->control_dmic_aud[id] |= value;
slif_dbg(dev, "mask 0x%x val 0x%x value 0x%x\n",
mask, val, value);
slif_dbg(dev, "dmic aud[%d] 0x%x \n",
id, data->control_dmic_aud[id]);
ret = slif_soc_dmic_aud_control_gain_write(data, id);
return ret;
}
static void slif_mark_dirty_register(struct slif_data *data)
{
int i;
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
regcache_mark_dirty(data->regmap_dmic_aud[i]);
}
regcache_mark_dirty(data->regmap_sfr);
}
static void slif_save_register(struct slif_data *data)
{
int i;
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
regcache_cache_only(data->regmap_dmic_aud[i], true);
regcache_mark_dirty(data->regmap_dmic_aud[i]);
}
regcache_cache_only(data->regmap_sfr, true);
regcache_mark_dirty(data->regmap_sfr);
}
static void slif_restore_register(struct slif_data *data)
{
int i;
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
regcache_cache_only(data->regmap_dmic_aud[i], false);
regcache_sync(data->regmap_dmic_aud[i]);
}
regcache_cache_only(data->regmap_sfr, false);
regcache_sync(data->regmap_sfr);
}
static int slif_soc_set_fmt_master(struct slif_data *data,
unsigned int fmt)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
int ret = 0;
slif_info(dev, "(0x%08x)\n", fmt);
if (fmt < 0)
return -EINVAL;
ctrl = snd_soc_component_read(cmpnt, SLIF_CONFIG_MASTER_BASE);
#if (SLIF_SOC_VERSION(1, 0, 0) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_NB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 1);
break;
case SND_SOC_DAIFMT_IB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_IB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 1);
break;
default:
ret = -EINVAL;
}
#elif (SLIF_SOC_VERSION(1, 1, 1) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_NB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 1);
break;
case SND_SOC_DAIFMT_IB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_IB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 1);
break;
default:
ret = -EINVAL;
}
#elif (SLIF_SOC_VERSION(1, 1, 2) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 0);
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_BCLK_POLAR, 0);
break;
case SND_SOC_DAIFMT_NB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 1);
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_BCLK_POLAR, 1);
break;
case SND_SOC_DAIFMT_IB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 0);
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_BCLK_POLAR, 0);
break;
case SND_SOC_DAIFMT_IB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_WS_POLAR, 1);
vts_set_value_by_name(ctrl, SLIF_CONFIG_MASTER_BCLK_POLAR, 1);
break;
default:
ret = -EINVAL;
}
#else
#error "SLIF_SOC_VERSION is not defined"
#endif
slif_info(dev, "ctrl(0x%08x)\n", ctrl);
snd_soc_component_write(cmpnt, SLIF_CONFIG_MASTER_BASE, ctrl);
return ret;
}
static int slif_soc_set_fmt_slave(struct slif_data *data,
unsigned int fmt)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
int ret = 0;
slif_info(dev, "(0x%08x)\n", fmt);
if (fmt < 0)
return -EINVAL;
ctrl = snd_soc_component_read(cmpnt, SLIF_CONFIG_SLAVE_BASE);
#if (SLIF_SOC_VERSION(1, 0, 0) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_NB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 1);
break;
case SND_SOC_DAIFMT_IB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_IB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 1);
break;
default:
ret = -EINVAL;
}
#elif (SLIF_SOC_VERSION(1, 1, 1) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_NB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 1);
break;
case SND_SOC_DAIFMT_IB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 0);
break;
case SND_SOC_DAIFMT_IB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 1);
break;
default:
ret = -EINVAL;
}
#elif (SLIF_SOC_VERSION(1, 1, 2) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 0);
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_BCLK_POLAR, 0);
break;
case SND_SOC_DAIFMT_NB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 1);
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_BCLK_POLAR, 1);
break;
case SND_SOC_DAIFMT_IB_NF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 0);
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_BCLK_POLAR, 0);
break;
case SND_SOC_DAIFMT_IB_IF:
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_WS_POLAR, 1);
vts_set_value_by_name(ctrl, SLIF_CONFIG_SLAVE_BCLK_POLAR, 1);
break;
default:
ret = -EINVAL;
}
#else
#error "SLIF_SOC_VERSION is not defined"
#endif
slif_info(dev, "ctrl(0x%08x)\n", ctrl);
snd_soc_component_write(cmpnt, SLIF_CONFIG_SLAVE_BASE, ctrl);
return ret;
}
int slif_soc_set_fmt(struct slif_data *data, unsigned int fmt)
{
struct device *dev = data->dev;
int ret = 0;
slif_info(dev, "(0x%08x)\n", fmt);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
case SND_SOC_DAIFMT_CBM_CFS:
set_bit(SLIF_MODE_MASTER, &data->mode);
break;
case SND_SOC_DAIFMT_CBS_CFM:
case SND_SOC_DAIFMT_CBS_CFS:
set_bit(SLIF_MODE_SLAVE, &data->mode);
break;
default:
ret = -EINVAL;
}
data->fmt = fmt;
return ret;
}
static int slif_soc_mux_clk_enable(struct slif_data *data)
{
struct device *dev = data->dev;
int ret = 0;
if (data->clk_mux_dmic_aud_user) {
ret = clk_enable(data->clk_mux_dmic_aud_user);
if (ret < 0) {
slif_err(dev, "Failed to enable clk_mux_dmic_aud_user: %d\n", ret);
return ret;
}
slif_info(dev, "clk_mux_dmic_aud_user:%d\n",
clk_get_rate(data->clk_mux_dmic_aud_user));
}
if (data->clk_mux_serial_lif) {
ret = clk_enable(data->clk_mux_serial_lif);
if (ret < 0) {
slif_err(dev, "Failed to enable clk_mux_serial_lif: %d\n", ret);
return ret;
}
slif_info(dev, "clk_mux_serial_lif:%d\n",
clk_get_rate(data->clk_mux_serial_lif));
}
if (data->clk_mux_dmic_aud0) {
ret = clk_enable(data->clk_mux_dmic_aud0);
if (ret < 0) {
slif_err(dev, "Failed to enable clk_mux_dmic_aud0: %d\n", ret);
return ret;
}
slif_info(dev, "clk_mux_dmic_aud0:%d\n",
clk_get_rate(data->clk_mux_dmic_aud0));
}
if (data->clk_mux_dmic_aud1) {
ret = clk_enable(data->clk_mux_dmic_aud1);
if (ret < 0) {
slif_err(dev, "Failed to enable clk_mux_dmic_aud1: %d\n", ret);
return ret;
}
slif_info(dev, "clk_mux_dmic_aud1:%d\n",
clk_get_rate(data->clk_mux_dmic_aud1));
}
return ret;
}
static int slif_soc_div_clk_enable(struct slif_data *data)
{
struct device *dev = data->dev;
int ret = 0;
if (data->clk_enable)
return 0;
data->clk_enable = true;
if (data->clk_dmic_aud_div2) {
ret = clk_enable(data->clk_dmic_aud_div2);
if (ret < 0) {
slif_err(dev, "Failed to enable clk_dmic_aud_div2: %d\n", ret);
goto rewind2;
}
slif_info(dev, "clk_dmic_aud_div2 aft:%d\n",
clk_get_rate(data->clk_dmic_aud_div2));
}
if (data->clk_serial_lif) {
ret = clk_enable(data->clk_serial_lif);
if (ret < 0) {
slif_err(dev, "Failed to enable clk_s_lif: %d\n", ret);
goto rewind1;
}
slif_info(dev, "clk_s_lif aft:%d\n",
clk_get_rate(data->clk_serial_lif));
}
return ret;
rewind1:
clk_disable(data->clk_dmic_aud_div2);
rewind2:
data->clk_enable = false;
return ret;
}
static void slif_soc_mux_clk_disable(struct slif_data *data)
{
if (data->clk_mux_dmic_aud_user)
clk_disable(data->clk_mux_dmic_aud_user);
clk_disable(data->clk_mux_serial_lif);
if (data->clk_mux_dmic_aud0)
clk_disable(data->clk_mux_dmic_aud0);
if (data->clk_mux_dmic_aud1)
clk_disable(data->clk_mux_dmic_aud1);
}
static void slif_soc_div_clk_disable(struct slif_data *data)
{
if (!data->clk_enable)
return;
data->clk_enable = false;
clk_disable(data->clk_serial_lif);
clk_disable(data->clk_dmic_aud_div2);
}
int slif_soc_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params,
struct slif_data *data)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl0, ctrl1;
int clk_val = 0;
int val = 0;
int ret = 0;
unsigned int i = 0;
slif_info(dev, "[%c]\n",
(substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
'C' : 'P');
data->channels = params_channels(hw_params);
data->rate = params_rate(hw_params);
data->width = params_width(hw_params);
data->clk_table_id = slif_clk_table_id_search(data->rate,
data->width);
slif_info(dev, "rate=%u, width=%d, channel=%u id=%d\n",
data->rate, data->width,
data->channels, data->clk_table_id);
if (data->clk_table_id < 0) {
slif_err(dev, "clk table is not matched(%d)\n", data->clk_table_id);
return -EINVAL;
}
if (data->channels > 8) {
slif_err(dev, "(%d) is not support channels\n", data->channels);
return -EINVAL;
}
ctrl0 = snd_soc_component_read(cmpnt, SLIF_CONFIG_MASTER_BASE);
ctrl1 = snd_soc_component_read(cmpnt, SLIF_CONFIG_SLAVE_BASE);
#if (SLIF_SOC_VERSION(1, 0, 0) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (params_format(hw_params)) {
case SNDRV_PCM_FORMAT_S16:
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OPMODE, 1);
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OPMODE, 1);
break;
case SNDRV_PCM_FORMAT_S24:
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OPMODE, 3);
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OPMODE, 3);
break;
default:
return -EINVAL;
}
#elif (SLIF_SOC_VERSION(1, 1, 1) == CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (params_format(hw_params)) {
case SNDRV_PCM_FORMAT_S16:
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OP_D, 1);
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OP_D, 1);
break;
case SNDRV_PCM_FORMAT_S24:
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OP_D, 0);
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OP_D, 0);
break;
default:
return -EINVAL;
}
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OP_C,
(data->channels - 1));
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OP_C,
(data->channels - 1));
#elif (SLIF_SOC_VERSION(1, 1, 2) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
switch (params_format(hw_params)) {
case SNDRV_PCM_FORMAT_S16:
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OP_D, 1);
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OP_D, 1);
break;
case SNDRV_PCM_FORMAT_S24:
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OP_D, 0);
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OP_D, 0);
break;
default:
return -EINVAL;
}
vts_set_value_by_name(ctrl0, SLIF_CONFIG_MASTER_OP_C,
(data->channels - 1));
vts_set_value_by_name(ctrl1, SLIF_CONFIG_SLAVE_OP_C,
(data->channels - 1));
#else
#error "SLIF_SOC_VERSION is not defined"
#endif
/* SYS_SEL */
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
val = slif_clk_table_get(data->clk_table_id,
CLK_TABLE_SYS_SEL);
if (val < 0) {
slif_err(dev, "clk id is not valid(%d)\n",
data->clk_table_id);
return -EINVAL;
}
ret = slif_soc_dmic_aud_control_sys_sel_put(data, i, val);
if (ret < 0)
slif_err(dev, "failed SYS_SEL[%d] ctrl %d\n",
i, ret);
}
clk_val = slif_clk_table_get(data->clk_table_id,
CLK_TABLE_DMIC_AUD);
if (clk_val < 0)
slif_err(dev, "Failed to find clk table : %s\n", "clk_dmic_aud");
slif_info(dev, "clk_dmic_aud bef:%d\n",
clk_get_rate(data->clk_dmic_aud));
slif_dbg(dev, "find clk table : %s: (%d)\n", "clk_dmic_aud", clk_val);
ret = clk_set_rate(data->clk_dmic_aud, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "dmic_aud");
return ret;
}
if (data->clk_mux_dmic_aud0) {
ret = clk_set_rate(data->clk_mux_dmic_aud0,
clk_get_rate(data->clk_dmic_aud));
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "dmic_mux_aud0");
return ret;
}
}
#if (SLIF_SOC_VERSION(1, 1, 1) >= CONFIG_SND_SOC_SAMSUNG_SLIF_VERSION)
clk_val = slif_clk_table_get(data->clk_table_id,
CLK_TABLE_DMIC_AUD_PAD);
if (clk_val < 0)
slif_err(dev, "Failed to find clk table : %s\n", "clk_dmic_pad");
slif_info(dev, "find clk table : %s: (%d)\n", "clk_dmic_pad", clk_val);
ret = clk_set_rate(data->clk_dmic_aud_pad, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "dmic_aud_pad");
return ret;
}
#endif
clk_val = slif_clk_table_get(data->clk_table_id,
CLK_TABLE_DMIC_AUD_DIV2);
if (clk_val < 0)
slif_err(dev, "Failed to find clk : %s\n", "clk_dmic_div2");
slif_dbg(dev, "find clk table : %s: (%d)\n", "clk_dmic_div2", clk_val);
slif_info(dev, "clk_dmic_aud_div2 bef:%d\n",
clk_get_rate(data->clk_dmic_aud_div2));
ret = clk_set_rate(data->clk_dmic_aud_div2, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "dmic_aud_div2");
return ret;
}
if (data->clk_mux_dmic_aud1) {
ret = clk_set_rate(data->clk_mux_dmic_aud1,
clk_get_rate(data->clk_dmic_aud_div2));
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "mux_dmic_aud1");
return ret;
}
}
clk_val = slif_clk_table_get(data->clk_table_id,
CLK_TABLE_SERIAL_LIF);
if (clk_val < 0)
slif_err(dev, "Failed to find clk table : %s\n",
"clk_serial_lif");
slif_info(dev, "find clk table : %s: (%d)\n",
"clk_serial_lif", clk_val);
/* change blck to supprot channel */
clk_val = (clk_val * data->channels) / SLIF_MAX_CHANNEL;
slif_info(dev, "clk_s_lif bef:%d:%d\n",
clk_val, clk_get_rate(data->clk_serial_lif));
ret = clk_set_rate(data->clk_serial_lif, clk_val);
if (ret < 0)
slif_err(dev, "Failed to set rate : %s\n", "clk_s_lif");
ret = slif_soc_div_clk_enable(data);
if (ret < 0)
slif_err(dev, "Failed to enable div clocks: %d\n", ret);
ret = snd_soc_component_write(cmpnt, SLIF_CONFIG_MASTER_BASE, ctrl0);
if (ret < 0)
slif_err(dev, "Failed to access CONFIG_MASTER sfr:%d\n",
ret);
ret = snd_soc_component_write(cmpnt, SLIF_CONFIG_SLAVE_BASE, ctrl1);
if (ret < 0)
slif_err(dev, "Failed to access CONFIG_SLAVE sfr:%d\n",
ret);
set_bit(SLIF_STATE_SET_PARAM, &data->state);
return 0;
}
int slif_soc_startup(struct snd_pcm_substream *substream,
struct slif_data *data)
{
struct device *dev = data->dev;
int clk_val = 0;
int ret = 0;
int i;
slif_info(dev, "[%c]\n",
(substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
'C' : 'P');
pm_runtime_get_sync(dev);
#if IS_ENABLED(CONFIG_SOC_S5E9925)
if (data->dev_vts) {
pm_runtime_get_sync(data->dev_vts);
} else {
slif_err(dev, "data->dev_vts is NULL\n");
return -EINVAL;
}
#endif
ret = slif_soc_mux_clk_enable(data);
if (ret < 0)
slif_err(dev, "Failed to enable mux clocks: %d\n", ret);
vts_set_clk_src(data->dev_vts, VTS_CLK_SRC_AUD0);
clk_val = 73728000;
if (data->clk_mux_dmic_aud_user) {
ret = clk_set_rate(data->clk_mux_dmic_aud_user, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "clk_mux_dmic_aud_user");
return ret;
}
}
if (data->clk_slif_src) {
ret = clk_set_rate(data->clk_slif_src, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "clk_slif_src");
return ret;
}
} else {
slif_info(dev, "%s is null\n", "clk_slif_src");
}
if (data->clk_mux_dmic_aud) {
ret = clk_set_rate(data->clk_mux_dmic_aud, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "clk_mux_dmic_aud");
return ret;
}
} else {
slif_info(dev, "%s is null\n", "clk_mux_dmic_aud");
}
if (data->clk_mux_serial_lif) {
ret = clk_set_rate(data->clk_mux_serial_lif, clk_val);
if (ret < 0) {
slif_err(dev, "Failed to set rate : %s\n", "clk_mux_serial_lif");
return ret;
}
} else {
slif_info(dev, "%s is null\n", "clk_mux_serial_lif");
}
slif_restore_register(data);
set_bit(SLIF_STATE_OPENED, &data->state);
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
slif_soc_dmic_en_put(data, i, data->dmic_en[i], true);
}
return 0;
pm_runtime_put_sync(dev);
#if IS_ENABLED(CONFIG_SOC_S5E9925)
if (data->dev_vts)
pm_runtime_put_sync(data->dev_vts);
#endif
return ret;
}
void slif_soc_shutdown(struct snd_pcm_substream *substream,
struct slif_data *data)
{
struct device *dev = data->dev;
int ret_chk = 0;
int i;
slif_dbg(dev, "[%c]\n",
(substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
'C' : 'P');
if (!data->dev_vts) {
slif_err(dev, "data->dev_vts is NULL\n");
return;
}
/* make default pin state as idle to prevent conflict with vts */
for (i = 0; i < SLIF_DMIC_AUD_NUM; i++) {
slif_soc_dmic_en_put(data, i, 0, false);
}
slif_save_register(data);
/* reset status */
slif_soc_reset_status(data);
slif_info(dev, " - set VTS clk\n");
vts_set_clk_src(data->dev_vts, VTS_CLK_SRC_RCO);
ret_chk = vts_chk_dmic_clk_mode(data->dev_vts);
if (ret_chk < 0) {
slif_info(dev, "ret_chk failed(%d)\n", ret_chk);
}
if (test_bit(SLIF_STATE_SET_PARAM, &data->state)) {
slif_soc_div_clk_disable(data);
clear_bit(SLIF_STATE_SET_PARAM, &data->state);
}
slif_soc_mux_clk_disable(data);
clear_bit(SLIF_STATE_OPENED, &data->state);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_sync(dev);
#if IS_ENABLED(CONFIG_SOC_S5E9925)
if (data->dev_vts)
pm_runtime_put_sync(data->dev_vts);
#endif
}
int slif_soc_hw_free(struct snd_pcm_substream *substream, struct slif_data *data)
{
struct device *dev = data->dev;
slif_dbg(dev, "[%c]\n",
(substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
'C' : 'P');
return 0;
}
int slif_soc_dma_en(int enable,
struct slif_data *data)
{
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
unsigned int ctrl;
int ret = 0;
int ret_chk = 0;
slif_info(dev, "enable(%d)\n", enable);
if (unlikely(data->slif_dump_enabled)) {
ret = slif_soc_set_fmt_slave(data, data->fmt);
ret |= slif_soc_set_fmt_master(data, data->fmt);
if (ret < 0) {
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
return ret;
}
} else {
if (test_bit(SLIF_MODE_SLAVE, &data->mode))
ret = slif_soc_set_fmt_slave(data, data->fmt);
if (test_bit(SLIF_MODE_MASTER, &data->mode))
ret = slif_soc_set_fmt_master(data, data->fmt);
if (ret < 0) {
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
return ret;
}
}
if (unlikely(data->slif_dump_enabled)) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CONFIG_DONE_BASE,
SLIF_CONFIG_DONE_MASTER_CONFIG_MASK |
SLIF_CONFIG_DONE_SLAVE_CONFIG_MASK |
SLIF_CONFIG_DONE_ALL_CONFIG_MASK,
(enable << SLIF_CONFIG_DONE_MASTER_CONFIG_L) |
(enable << SLIF_CONFIG_DONE_SLAVE_CONFIG_L) |
(enable << SLIF_CONFIG_DONE_ALL_CONFIG_L));
if (ret < 0)
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
} else {
if (test_bit(SLIF_MODE_SLAVE, &data->mode)) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CONFIG_DONE_BASE,
SLIF_CONFIG_DONE_SLAVE_CONFIG_MASK |
SLIF_CONFIG_DONE_ALL_CONFIG_MASK,
(enable << SLIF_CONFIG_DONE_SLAVE_CONFIG_L) |
(enable << SLIF_CONFIG_DONE_ALL_CONFIG_L));
if (ret < 0)
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
}
if (test_bit(SLIF_MODE_MASTER, &data->mode)) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CONFIG_DONE_BASE,
SLIF_CONFIG_DONE_MASTER_CONFIG_MASK |
SLIF_CONFIG_DONE_ALL_CONFIG_MASK,
(enable << SLIF_CONFIG_DONE_MASTER_CONFIG_L) |
(enable << SLIF_CONFIG_DONE_ALL_CONFIG_L));
if (ret < 0)
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
}
}
ctrl = snd_soc_component_read(cmpnt, SLIF_CONFIG_DONE_BASE);
slif_info(dev, "ctrl(0x%08x)\n", ctrl);
/* PAD configuration */
#if 0
slif_soc_set_sel_pad(data, enable);
#else
vts_clk_aud_set_rate(data->dev_vts, 5);
vts_set_sel_pad(data->dev_vts, enable);
if (IS_ENABLED(CONFIG_SOC_S5E9925))
abox_write_sysreg(0x7, 0x520);
#endif
/* slif_dmic_aud_en(data->dev_vts, enable); */
/* slif_dmic_if_en(data->dev_vts, enable); */
/* HACK : MOVE to resume */
if (enable)
vts_pad_retention(false);
/* DMIC_IF configuration */
slif_soc_set_dmic_aud(data, enable);
data->mute_enable = enable;
slif_info(dev, "en(%d) ms(%d)\n", enable, data->mute_ms);
if (enable && (data->mute_ms != 0)) {
/* queue delayed work at starting */
schedule_delayed_work(&data->mute_work, msecs_to_jiffies(data->mute_ms));
} else {
/* check dmic port and enable EN bit */
if (SLIF_DMIC_AUD_NUM == 1){
ret = snd_soc_component_update_bits(cmpnt,
SLIF_INPUT_EN_BASE,
SLIF_INPUT_EN_EN0_MASK,
(enable << SLIF_INPUT_EN_EN0_L));
} else if(SLIF_DMIC_AUD_NUM == 2){
ret = snd_soc_component_update_bits(cmpnt,
SLIF_INPUT_EN_BASE,
SLIF_INPUT_EN_EN0_MASK |
SLIF_INPUT_EN_EN1_MASK,
(enable << SLIF_INPUT_EN_EN0_L) |
(enable << SLIF_INPUT_EN_EN1_L));
} else if(SLIF_DMIC_AUD_NUM ==3) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_INPUT_EN_BASE,
SLIF_INPUT_EN_EN0_MASK |
SLIF_INPUT_EN_EN1_MASK |
SLIF_INPUT_EN_EN2_MASK,
(enable << SLIF_INPUT_EN_EN0_L) |
(enable << SLIF_INPUT_EN_EN1_L) |
(enable << SLIF_INPUT_EN_EN2_L));
} else
slif_info(dev, "Please check the number of DMIC ports\n");
if (ret < 0)
slif_err(dev, "Failed to access INPUT_EN sfr:%d\n",
ret);
}
if (unlikely(data->slif_dump_enabled)) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CTRL_BASE,
SLIF_CTRL_SLAVE_IF_EN_MASK |
SLIF_CTRL_MASTER_IF_EN_MASK |
SLIF_CTRL_LOOPBACK_EN_MASK |
SLIF_CTRL_SPU_EN_MASK,
(enable << SLIF_CTRL_SLAVE_IF_EN_L) |
(enable << SLIF_CTRL_MASTER_IF_EN_L) |
(enable << SLIF_CTRL_LOOPBACK_EN_L) |
(enable << SLIF_CTRL_SPU_EN_L));
if (ret < 0)
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
} else {
if (test_bit(SLIF_MODE_SLAVE, &data->mode)) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CTRL_BASE,
SLIF_CTRL_SLAVE_IF_EN_MASK |
SLIF_CTRL_SPU_EN_MASK,
(enable << SLIF_CTRL_SLAVE_IF_EN_L) |
(enable << SLIF_CTRL_SPU_EN_L));
if (ret < 0)
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
}
if (test_bit(SLIF_MODE_MASTER, &data->mode)) {
ret = snd_soc_component_update_bits(cmpnt,
SLIF_CTRL_BASE,
SLIF_CTRL_MASTER_IF_EN_MASK |
SLIF_CTRL_SPU_EN_MASK,
(enable << SLIF_CTRL_MASTER_IF_EN_L) |
(enable << SLIF_CTRL_SPU_EN_L));
if (ret < 0)
slif_err(dev, "Failed to access CTRL sfr:%d\n",
ret);
}
}
ctrl = snd_soc_component_read(cmpnt, SLIF_CTRL_BASE);
slif_info(dev, "ctrl(0x%08x)\n", ctrl);
#ifdef SLIF_REG_LOW_CTRL
slif_check_reg(0);
#endif
if (enable) {
slif_info(dev, " - set VTS clk\n");
ret_chk = vts_chk_dmic_clk_mode(data->dev_vts);
if (ret_chk < 0) {
slif_info(dev, "ret_chk failed(%d)\n", ret_chk);
}
}
return ret;
}
static struct clk *devm_clk_get_and_prepare(struct device *dev, const char *name)
{
struct clk *clk;
int result;
clk = devm_clk_get(dev, name);
if (IS_ERR(clk)) {
slif_err(dev, "Failed to get clock %s\n", name);
goto error;
}
result = clk_prepare(clk);
if (result < 0) {
slif_err(dev, "Failed to prepare clock %s\n", name);
goto error;
}
error:
return clk;
}
static void slif_soc_mute_func(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct slif_data *data = container_of(dwork, struct slif_data,
mute_work);
struct device *dev = data->dev;
struct snd_soc_component *cmpnt = data->cmpnt;
int ret = 0;
slif_info(dev, ":(en:%d)\n", data->mute_enable);
/* check dmic port and enable EN bit */
ret = snd_soc_component_update_bits(cmpnt,
SLIF_INPUT_EN_BASE,
SLIF_INPUT_EN_EN0_MASK |
SLIF_INPUT_EN_EN1_MASK |
SLIF_INPUT_EN_EN2_MASK,
(data->mute_enable << SLIF_INPUT_EN_EN0_L) |
(data->mute_enable << SLIF_INPUT_EN_EN1_L) |
(data->mute_enable << SLIF_INPUT_EN_EN2_L));
if (ret < 0)
slif_err(dev, "Failed to access INPUT_EN sfr:%d\n",
ret);
}
static DECLARE_DELAYED_WORK(slif_soc_mute, slif_soc_mute_func);
int slif_soc_probe(struct slif_data *data)
{
struct device *dev = data->dev;
data->clk_mux_dmic_aud_user = devm_clk_get_and_prepare(dev, "mux_dmic_aud_user");
if (IS_ERR(data->clk_mux_dmic_aud_user)) {
data->clk_mux_dmic_aud_user = NULL;
slif_info(dev, "Failed to get clk_mux_dmic_aud_user\n");
}
data->clk_mux_dmic_aud = devm_clk_get_and_prepare(dev, "mux_dmic_aud");
if (IS_ERR(data->clk_mux_dmic_aud)) {
data->clk_mux_dmic_aud = NULL;
slif_info(dev, "Failed to get clk_mux_dmic_aud\n");
}
data->clk_mux_serial_lif = devm_clk_get_and_prepare(dev, "mux_serial_lif");
if (IS_ERR(data->clk_mux_serial_lif)) {
data->clk_mux_serial_lif = NULL;
slif_info(dev, "Failed to get clk_mux_serial_lif\n");
}
data->clk_dmic_aud_div2 = devm_clk_get_and_prepare(dev, "dmic_aud_div2");
if (IS_ERR(data->clk_dmic_aud_div2)) {
data->clk_dmic_aud_div2 = NULL;
slif_info(dev, "Failed to get clk_dmic_aud_div2\n");
}
data->clk_dmic_aud = devm_clk_get_and_prepare(dev, "dmic_aud");
if (IS_ERR(data->clk_dmic_aud)) {
data->clk_dmic_aud = NULL;
slif_info(dev, "Failed to get clk_dmic_aud\n");
}
data->clk_mux_dmic_aud0 = devm_clk_get_and_prepare(dev, "mux_dmic_aud0");
if (IS_ERR(data->clk_mux_dmic_aud0)) {
data->clk_mux_dmic_aud0 = NULL;
slif_info(dev, "Failed to get clk_mux_dmic_aud0\n");
}
data->clk_mux_dmic_aud1 = devm_clk_get_and_prepare(dev, "mux_dmic_aud1");
if (IS_ERR(data->clk_mux_dmic_aud1)) {
data->clk_mux_dmic_aud1 = NULL;
slif_info(dev, "Failed to get clk_mux_dmic_aud1\n");
}
data->clk_serial_lif = devm_clk_get_and_prepare(dev, "serial_lif");
if (IS_ERR(data->clk_serial_lif)) {
data->clk_serial_lif = NULL;
slif_info(dev, "Failed to get clk_serial_lif\n");
}
data->clk_slif_src = devm_clk_get_and_prepare(dev, "clk_slif_src");
if (IS_ERR(data->clk_slif_src)) {
data->clk_slif_src = NULL;
slif_info(dev, "Failed to get clk_slif_src\n");
}
data->mute_enable = false;
data->clk_enable = false;
data->mute_ms = 0;
data->clk_input_path = SLIF_CLK_PLL_AUD0;
slif_mark_dirty_register(data);
slif_save_register(data);
slif_soc_set_default_gain(data);
pm_runtime_no_callbacks(dev);
pm_runtime_enable(dev);
INIT_DELAYED_WORK(&data->mute_work, slif_soc_mute_func);
return 0;
}