// SPDX-License-Identifier: GPL-2.0-only
/*
* cs42l84.c -- CS42L84 ALSA SoC audio driver
*
* Copyright (C) The Asahi Linux Contributors
*
* Based on sound/soc/codecs/cs42l42{.c,.h}
* Copyright 2016 Cirrus Logic, Inc.
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/jack.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 "cs42l84.h"
#include "cirrus_legacy.h"
struct cs42l84_private {
struct regmap *regmap;
struct device *dev;
struct gpio_desc *reset_gpio;
struct snd_soc_jack *jack;
struct mutex irq_lock;
u8 tip_state;
u8 ring_state;
int pll_config;
int bclk;
u8 pll_mclk_f;
u32 srate;
u8 stream_use;
int hs_type;
};
static bool cs42l84_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case CS42L84_DEVID ... CS42L84_DEVID+5:
case CS42L84_TSRS_PLUG_INT_STATUS:
case CS42L84_PLL_LOCK_STATUS:
case CS42L84_TSRS_PLUG_STATUS:
case CS42L84_HS_DET_STATUS2:
return true;
default:
return false;
}
}
static const struct regmap_config cs42l84_regmap = {
.reg_bits = 16,
.val_bits = 8,
.volatile_reg = cs42l84_volatile_register,
.max_register = 0x73fe,
.cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
};
static int cs42l84_put_dac_vol(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *val)
{
struct snd_soc_component *component = snd_kcontrol_chip(kctl);
struct soc_mixer_control *mc = (struct soc_mixer_control *) kctl->private_value;
int vola, volb;
int ret, ret2, updated = 0;
vola = val->value.integer.value[0] + mc->min;
volb = val->value.integer.value[1] + mc->min;
if (vola < mc->min || vola > mc->max || volb < mc->min || volb > mc->max)
return -EINVAL;
ret = snd_soc_component_update_bits(component, CS42L84_FRZ_CTL,
CS42L84_FRZ_CTL_ENGAGE,
CS42L84_FRZ_CTL_ENGAGE);
if (ret < 0)
goto bail;
updated |= ret;
ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHA_VOL_LSB,
0xff, vola & 0xff);
if (ret < 0)
goto bail;
updated |= ret;
ret = snd_soc_component_update_bits(component, CS42L84_DAC_CHA_VOL_MSB,
0xff, (vola >> 8) & 0x01);
if (ret < 0)
goto bail;
updated |= ret;
ret =