// SPDX-License-Identifier: GPL-2.0-only
//
// rt715-sdca.c -- rt715 ALSA SoC audio driver
//
// Copyright(c) 2020 Realtek Semiconductor Corp.
//
//
//
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pm_runtime.h>
#include <linux/pm.h>
#include <linux/soundwire/sdw.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <linux/soundwire/sdw_registers.h>
#include "rt715-sdca.h"
static int rt715_index_write(struct rt715_sdca_priv *rt715, unsigned int nid,
unsigned int reg, unsigned int value)
{
struct regmap *regmap = rt715->mbq_regmap;
unsigned int addr;
int ret;
addr = (nid << 20) | reg;
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt715->slave->dev,
"Failed to set private value: %08x <= %04x %d\n", ret, addr,
value);
return ret;
}
static int rt715_index_read(struct rt715_sdca_priv *rt715,
unsigned int nid, unsigned int reg, unsigned int *value)
{
struct regmap *regmap = rt715->mbq_regmap;
unsigned int addr;
int ret;
addr = (nid << 20) | reg;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt715->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
return ret;
}
static int rt715_index_update_bits(struct rt715_sdca_priv *rt715,
unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val)
{
unsigned int tmp;
int ret;
ret = rt715_index_read(rt715, nid, reg, &tmp);
if (ret < 0)
return ret;
set_mask_bits(&tmp, mask, val);
return rt715_index_write(rt715, nid, reg, tmp);
}
/* SDCA Volume/Boost control */
static int rt715_set_amp_gain_put_sdca(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component);
unsigned int val_l, val_r, gain_l_val, gain_r_val;
int ret;
/* control value to 2s complement */
/* L channel */
gain_l_val = ucontrol->value.integer.value[0];
if (gain_l_val > mc->max)
gain_l_val = mc->max;
val_l = gain_l_val;
if (mc->shift == 8) {
gain_l_val = (gain_l_val * 10) << mc->shift;
} else {
gain_l_val =
((abs(gain_l_val - mc->shift) * RT715_SDCA_DB_STEP) << 8) / 1000;
if (val_l <= mc->shift) {
gain_l_val = ~gain_l_val;
gain_l_val += 1;
}
gain_l_val &= 0xffff;
}
/* R channel */
gain_r_val = ucontrol->value.integer.value[1];
if (gain_r_val > mc->max)
gain_r_val = mc->max;
val_r = gain_r_val;
if (mc->shift == 8) {
gain_r_val = (gain_r_val * 10) << mc->shift;
} else {
gain_r_val =
((abs(gain_r_val - mc->shift) * RT715_SDCA_DB_STEP) << 8) / 1000;
if (val_r <= mc->shift) {
gain_r_val = ~gain_r_val;
gain_r_val += 1;
}
gain_r_val &= 0xffff;
}
/* Lch*/
ret = regmap_write(rt715->mbq_regmap, mc->reg, gain_l_val);
if (ret != 0) {
dev_err(component->dev, "Failed to write 0x%x=0x%x\n", mc->reg,
gain_l_val);
return ret;
}
/* Rch */
ret =