cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mt6660.c (15077B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3// Copyright (c) 2019 MediaTek Inc.
      4
      5#include <linux/module.h>
      6#include <linux/kernel.h>
      7#include <linux/err.h>
      8#include <linux/i2c.h>
      9#include <linux/pm_runtime.h>
     10#include <linux/delay.h>
     11#include <sound/soc.h>
     12#include <sound/tlv.h>
     13#include <sound/pcm_params.h>
     14
     15#include "mt6660.h"
     16
     17struct reg_size_table {
     18	u32 addr;
     19	u8 size;
     20};
     21
     22static const struct reg_size_table mt6660_reg_size_table[] = {
     23	{ MT6660_REG_HPF1_COEF, 4 },
     24	{ MT6660_REG_HPF2_COEF, 4 },
     25	{ MT6660_REG_TDM_CFG3, 2 },
     26	{ MT6660_REG_RESV17, 2 },
     27	{ MT6660_REG_RESV23, 2 },
     28	{ MT6660_REG_SIGMAX, 2 },
     29	{ MT6660_REG_DEVID, 2 },
     30	{ MT6660_REG_HCLIP_CTRL, 2 },
     31	{ MT6660_REG_DA_GAIN, 2 },
     32};
     33
     34static int mt6660_get_reg_size(uint32_t addr)
     35{
     36	int i;
     37
     38	for (i = 0; i < ARRAY_SIZE(mt6660_reg_size_table); i++) {
     39		if (mt6660_reg_size_table[i].addr == addr)
     40			return mt6660_reg_size_table[i].size;
     41	}
     42	return 1;
     43}
     44
     45static int mt6660_reg_write(void *context, unsigned int reg, unsigned int val)
     46{
     47	struct mt6660_chip *chip = context;
     48	int size = mt6660_get_reg_size(reg);
     49	u8 reg_data[4];
     50	int i;
     51
     52	for (i = 0; i < size; i++)
     53		reg_data[size - i - 1] = (val >> (8 * i)) & 0xff;
     54
     55	return i2c_smbus_write_i2c_block_data(chip->i2c, reg, size, reg_data);
     56}
     57
     58static int mt6660_reg_read(void *context, unsigned int reg, unsigned int *val)
     59{
     60	struct mt6660_chip *chip = context;
     61	int size = mt6660_get_reg_size(reg);
     62	int i, ret;
     63	u8 data[4];
     64	u32 reg_data = 0;
     65
     66	ret = i2c_smbus_read_i2c_block_data(chip->i2c, reg, size, data);
     67	if (ret < 0)
     68		return ret;
     69	for (i = 0; i < size; i++) {
     70		reg_data <<= 8;
     71		reg_data |= data[i];
     72	}
     73	*val = reg_data;
     74	return 0;
     75}
     76
     77static const struct regmap_config mt6660_regmap_config = {
     78	.reg_bits = 8,
     79	.val_bits = 32,
     80	.reg_write = mt6660_reg_write,
     81	.reg_read = mt6660_reg_read,
     82};
     83
     84static int mt6660_codec_dac_event(struct snd_soc_dapm_widget *w,
     85	struct snd_kcontrol *kcontrol, int event)
     86{
     87	if (event == SND_SOC_DAPM_POST_PMU)
     88		usleep_range(1000, 1100);
     89	return 0;
     90}
     91
     92static int mt6660_codec_classd_event(struct snd_soc_dapm_widget *w,
     93	struct snd_kcontrol *kcontrol, int event)
     94{
     95	struct snd_soc_component *component =
     96		snd_soc_dapm_to_component(w->dapm);
     97	int ret;
     98
     99	switch (event) {
    100	case SND_SOC_DAPM_PRE_PMU:
    101		dev_dbg(component->dev,
    102			"%s: before classd turn on\n", __func__);
    103		/* config to adaptive mode */
    104		ret = snd_soc_component_update_bits(component,
    105			MT6660_REG_BST_CTRL, 0x03, 0x03);
    106		if (ret < 0) {
    107			dev_err(component->dev, "config mode adaptive fail\n");
    108			return ret;
    109		}
    110		break;
    111	case SND_SOC_DAPM_POST_PMU:
    112		/* voltage sensing enable */
    113		ret = snd_soc_component_update_bits(component,
    114			MT6660_REG_RESV7, 0x04, 0x04);
    115		if (ret < 0) {
    116			dev_err(component->dev,
    117				"enable voltage sensing fail\n");
    118			return ret;
    119		}
    120		dev_dbg(component->dev, "Amp on\n");
    121		break;
    122	case SND_SOC_DAPM_PRE_PMD:
    123		dev_dbg(component->dev, "Amp off\n");
    124		/* voltage sensing disable */
    125		ret = snd_soc_component_update_bits(component,
    126			MT6660_REG_RESV7, 0x04, 0x00);
    127		if (ret < 0) {
    128			dev_err(component->dev,
    129				"disable voltage sensing fail\n");
    130			return ret;
    131		}
    132		/* pop-noise improvement 1 */
    133		ret = snd_soc_component_update_bits(component,
    134			MT6660_REG_RESV10, 0x10, 0x10);
    135		if (ret < 0) {
    136			dev_err(component->dev,
    137				"pop-noise improvement 1 fail\n");
    138			return ret;
    139		}
    140		break;
    141	case SND_SOC_DAPM_POST_PMD:
    142		dev_dbg(component->dev,
    143			"%s: after classd turn off\n", __func__);
    144		/* pop-noise improvement 2 */
    145		ret = snd_soc_component_update_bits(component,
    146			MT6660_REG_RESV10, 0x10, 0x00);
    147		if (ret < 0) {
    148			dev_err(component->dev,
    149				"pop-noise improvement 2 fail\n");
    150			return ret;
    151		}
    152		/* config to off mode */
    153		ret = snd_soc_component_update_bits(component,
    154			MT6660_REG_BST_CTRL, 0x03, 0x00);
    155		if (ret < 0) {
    156			dev_err(component->dev, "config mode off fail\n");
    157			return ret;
    158		}
    159		break;
    160	}
    161	return 0;
    162}
    163
    164static const struct snd_soc_dapm_widget mt6660_component_dapm_widgets[] = {
    165	SND_SOC_DAPM_DAC_E("DAC", NULL, MT6660_REG_PLL_CFG1,
    166		0, 1, mt6660_codec_dac_event, SND_SOC_DAPM_POST_PMU),
    167	SND_SOC_DAPM_ADC("VI ADC", NULL, SND_SOC_NOPM, 0, 0),
    168	SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
    169	SND_SOC_DAPM_OUT_DRV_E("ClassD", MT6660_REG_SYSTEM_CTRL, 2, 0,
    170			       NULL, 0, mt6660_codec_classd_event,
    171			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
    172			       SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
    173	SND_SOC_DAPM_OUTPUT("OUTP"),
    174	SND_SOC_DAPM_OUTPUT("OUTN"),
    175};
    176
    177static const struct snd_soc_dapm_route mt6660_component_dapm_routes[] = {
    178	{ "DAC", NULL, "aif_playback" },
    179	{ "PGA", NULL, "DAC" },
    180	{ "ClassD", NULL, "PGA" },
    181	{ "OUTP", NULL, "ClassD" },
    182	{ "OUTN", NULL, "ClassD" },
    183	{ "VI ADC", NULL, "ClassD" },
    184	{ "aif_capture", NULL, "VI ADC" },
    185};
    186
    187static int mt6660_component_get_volsw(struct snd_kcontrol *kcontrol,
    188				  struct snd_ctl_elem_value *ucontrol)
    189{
    190	struct snd_soc_component *component =
    191		snd_soc_kcontrol_component(kcontrol);
    192	struct mt6660_chip *chip = (struct mt6660_chip *)
    193		snd_soc_component_get_drvdata(component);
    194
    195	ucontrol->value.integer.value[0] = chip->chip_rev & 0x0f;
    196	return 0;
    197}
    198
    199static const DECLARE_TLV_DB_SCALE(vol_ctl_tlv, -1155, 5, 0);
    200
    201static const struct snd_kcontrol_new mt6660_component_snd_controls[] = {
    202	SOC_SINGLE_TLV("Digital Volume", MT6660_REG_VOL_CTRL, 0, 255,
    203			   1, vol_ctl_tlv),
    204	SOC_SINGLE("Hard Clip Switch", MT6660_REG_HCLIP_CTRL, 8, 1, 0),
    205	SOC_SINGLE("Clip Switch", MT6660_REG_SPS_CTRL, 0, 1, 0),
    206	SOC_SINGLE("Boost Mode", MT6660_REG_BST_CTRL, 0, 3, 0),
    207	SOC_SINGLE("DRE Switch", MT6660_REG_DRE_CTRL, 0, 1, 0),
    208	SOC_SINGLE("DC Protect Switch",	MT6660_REG_DC_PROTECT_CTRL, 3, 1, 0),
    209	SOC_SINGLE("Data Output Left Channel Selection",
    210		   MT6660_REG_DATAO_SEL, 3, 7, 0),
    211	SOC_SINGLE("Data Output Right Channel Selection",
    212		   MT6660_REG_DATAO_SEL, 0, 7, 0),
    213	SOC_SINGLE_EXT("T0 SEL", MT6660_REG_CALI_T0, 0, 7, 0,
    214		       snd_soc_get_volsw, NULL),
    215	SOC_SINGLE_EXT("Chip Rev", MT6660_REG_DEVID, 8, 15, 0,
    216		       mt6660_component_get_volsw, NULL),
    217};
    218
    219static int _mt6660_chip_power_on(struct mt6660_chip *chip, int on_off)
    220{
    221	return regmap_write_bits(chip->regmap, MT6660_REG_SYSTEM_CTRL,
    222				 0x01, on_off ? 0x00 : 0x01);
    223}
    224
    225struct reg_table {
    226	uint32_t addr;
    227	uint32_t mask;
    228	uint32_t val;
    229};
    230
    231static const struct reg_table mt6660_setting_table[] = {
    232	{ 0x20, 0x80, 0x00 },
    233	{ 0x30, 0x01, 0x00 },
    234	{ 0x50, 0x1c, 0x04 },
    235	{ 0xB1, 0x0c, 0x00 },
    236	{ 0xD3, 0x03, 0x03 },
    237	{ 0xE0, 0x01, 0x00 },
    238	{ 0x98, 0x44, 0x04 },
    239	{ 0xB9, 0xff, 0x82 },
    240	{ 0xB7, 0x7777, 0x7273 },
    241	{ 0xB6, 0x07, 0x03 },
    242	{ 0x6B, 0xe0, 0x20 },
    243	{ 0x07, 0xff, 0x70 },
    244	{ 0xBB, 0xff, 0x20 },
    245	{ 0x69, 0xff, 0x40 },
    246	{ 0xBD, 0xffff, 0x17f8 },
    247	{ 0x70, 0xff, 0x15 },
    248	{ 0x7C, 0xff, 0x00 },
    249	{ 0x46, 0xff, 0x1d },
    250	{ 0x1A, 0xffffffff, 0x7fdb7ffe },
    251	{ 0x1B, 0xffffffff, 0x7fdb7ffe },
    252	{ 0x51, 0xff, 0x58 },
    253	{ 0xA2, 0xff, 0xce },
    254	{ 0x33, 0xffff, 0x7fff },
    255	{ 0x4C, 0xffff, 0x0116 },
    256	{ 0x16, 0x1800, 0x0800 },
    257	{ 0x68, 0x1f, 0x07 },
    258};
    259
    260static int mt6660_component_setting(struct snd_soc_component *component)
    261{
    262	struct mt6660_chip *chip = snd_soc_component_get_drvdata(component);
    263	int ret = 0;
    264	size_t i = 0;
    265
    266	ret = _mt6660_chip_power_on(chip, 1);
    267	if (ret < 0) {
    268		dev_err(component->dev, "%s chip power on failed\n", __func__);
    269		return ret;
    270	}
    271
    272	for (i = 0; i < ARRAY_SIZE(mt6660_setting_table); i++) {
    273		ret = snd_soc_component_update_bits(component,
    274				mt6660_setting_table[i].addr,
    275				mt6660_setting_table[i].mask,
    276				mt6660_setting_table[i].val);
    277		if (ret < 0) {
    278			dev_err(component->dev, "%s update 0x%02x failed\n",
    279				__func__, mt6660_setting_table[i].addr);
    280			return ret;
    281		}
    282	}
    283
    284	ret = _mt6660_chip_power_on(chip, 0);
    285	if (ret < 0) {
    286		dev_err(component->dev, "%s chip power off failed\n", __func__);
    287		return ret;
    288	}
    289
    290	return 0;
    291}
    292
    293static int mt6660_component_probe(struct snd_soc_component *component)
    294{
    295	struct mt6660_chip *chip = snd_soc_component_get_drvdata(component);
    296	int ret;
    297
    298	dev_dbg(component->dev, "%s\n", __func__);
    299	snd_soc_component_init_regmap(component, chip->regmap);
    300
    301	ret = mt6660_component_setting(component);
    302	if (ret < 0)
    303		dev_err(chip->dev, "mt6660 component setting failed\n");
    304
    305	return ret;
    306}
    307
    308static void mt6660_component_remove(struct snd_soc_component *component)
    309{
    310	dev_dbg(component->dev, "%s\n", __func__);
    311	snd_soc_component_exit_regmap(component);
    312}
    313
    314static const struct snd_soc_component_driver mt6660_component_driver = {
    315	.probe = mt6660_component_probe,
    316	.remove = mt6660_component_remove,
    317
    318	.controls = mt6660_component_snd_controls,
    319	.num_controls = ARRAY_SIZE(mt6660_component_snd_controls),
    320	.dapm_widgets = mt6660_component_dapm_widgets,
    321	.num_dapm_widgets = ARRAY_SIZE(mt6660_component_dapm_widgets),
    322	.dapm_routes = mt6660_component_dapm_routes,
    323	.num_dapm_routes = ARRAY_SIZE(mt6660_component_dapm_routes),
    324
    325	.idle_bias_on = false, /* idle_bias_off = true */
    326	.endianness = 1,
    327};
    328
    329static int mt6660_component_aif_hw_params(struct snd_pcm_substream *substream,
    330	struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai)
    331{
    332	int word_len = params_physical_width(hw_params);
    333	int aud_bit = params_width(hw_params);
    334	u16 reg_data = 0;
    335	int ret;
    336
    337	dev_dbg(dai->dev, "%s: ++\n", __func__);
    338	dev_dbg(dai->dev, "format: 0x%08x\n", params_format(hw_params));
    339	dev_dbg(dai->dev, "rate: 0x%08x\n", params_rate(hw_params));
    340	dev_dbg(dai->dev, "word_len: %d, aud_bit: %d\n", word_len, aud_bit);
    341	if (word_len > 32 || word_len < 16) {
    342		dev_err(dai->dev, "not supported word length\n");
    343		return -ENOTSUPP;
    344	}
    345	switch (aud_bit) {
    346	case 16:
    347		reg_data = 3;
    348		break;
    349	case 18:
    350		reg_data = 2;
    351		break;
    352	case 20:
    353		reg_data = 1;
    354		break;
    355	case 24:
    356	case 32:
    357		reg_data = 0;
    358		break;
    359	default:
    360		return -ENOTSUPP;
    361	}
    362	ret = snd_soc_component_update_bits(dai->component,
    363		MT6660_REG_SERIAL_CFG1, 0xc0, (reg_data << 6));
    364	if (ret < 0) {
    365		dev_err(dai->dev, "config aud bit fail\n");
    366		return ret;
    367	}
    368	ret = snd_soc_component_update_bits(dai->component,
    369		MT6660_REG_TDM_CFG3, 0x3f0, word_len << 4);
    370	if (ret < 0) {
    371		dev_err(dai->dev, "config word len fail\n");
    372		return ret;
    373	}
    374	dev_dbg(dai->dev, "%s: --\n", __func__);
    375	return 0;
    376}
    377
    378static const struct snd_soc_dai_ops mt6660_component_aif_ops = {
    379	.hw_params = mt6660_component_aif_hw_params,
    380};
    381
    382#define STUB_RATES	SNDRV_PCM_RATE_8000_192000
    383#define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
    384			SNDRV_PCM_FMTBIT_U16_LE | \
    385			SNDRV_PCM_FMTBIT_S24_LE | \
    386			SNDRV_PCM_FMTBIT_U24_LE | \
    387			SNDRV_PCM_FMTBIT_S32_LE | \
    388			SNDRV_PCM_FMTBIT_U32_LE)
    389
    390static struct snd_soc_dai_driver mt6660_codec_dai = {
    391	.name = "mt6660-aif",
    392	.playback = {
    393		.stream_name	= "aif_playback",
    394		.channels_min	= 1,
    395		.channels_max	= 2,
    396		.rates		= STUB_RATES,
    397		.formats	= STUB_FORMATS,
    398	},
    399	.capture = {
    400		.stream_name	= "aif_capture",
    401		.channels_min	= 1,
    402		.channels_max	= 2,
    403		.rates = STUB_RATES,
    404		.formats = STUB_FORMATS,
    405	},
    406	/* dai properties */
    407	.symmetric_rate = 1,
    408	.symmetric_channels = 1,
    409	.symmetric_sample_bits = 1,
    410	/* dai operations */
    411	.ops = &mt6660_component_aif_ops,
    412};
    413
    414static int _mt6660_chip_id_check(struct mt6660_chip *chip)
    415{
    416	int ret;
    417	unsigned int val;
    418
    419	ret = regmap_read(chip->regmap, MT6660_REG_DEVID, &val);
    420	if (ret < 0)
    421		return ret;
    422	val &= 0x0ff0;
    423	if (val != 0x00e0 && val != 0x01e0) {
    424		dev_err(chip->dev, "%s id(%x) not match\n", __func__, val);
    425		return -ENODEV;
    426	}
    427	return 0;
    428}
    429
    430static int _mt6660_chip_sw_reset(struct mt6660_chip *chip)
    431{
    432	int ret;
    433
    434	/* turn on main pll first, then trigger reset */
    435	ret = regmap_write(chip->regmap, MT6660_REG_SYSTEM_CTRL, 0x00);
    436	if (ret < 0)
    437		return ret;
    438	ret = regmap_write(chip->regmap, MT6660_REG_SYSTEM_CTRL, 0x80);
    439	if (ret < 0)
    440		return ret;
    441	msleep(30);
    442	return 0;
    443}
    444
    445static int _mt6660_read_chip_revision(struct mt6660_chip *chip)
    446{
    447	int ret;
    448	unsigned int val;
    449
    450	ret = regmap_read(chip->regmap, MT6660_REG_DEVID, &val);
    451	if (ret < 0) {
    452		dev_err(chip->dev, "get chip revision fail\n");
    453		return ret;
    454	}
    455	chip->chip_rev = val&0xff;
    456	dev_info(chip->dev, "%s chip_rev = %x\n", __func__, chip->chip_rev);
    457	return 0;
    458}
    459
    460static int mt6660_i2c_probe(struct i2c_client *client)
    461{
    462	struct mt6660_chip *chip = NULL;
    463	int ret;
    464
    465	dev_dbg(&client->dev, "%s\n", __func__);
    466	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
    467	if (!chip)
    468		return -ENOMEM;
    469	chip->i2c = client;
    470	chip->dev = &client->dev;
    471	mutex_init(&chip->io_lock);
    472	i2c_set_clientdata(client, chip);
    473
    474	chip->regmap = devm_regmap_init(&client->dev,
    475		NULL, chip, &mt6660_regmap_config);
    476	if (IS_ERR(chip->regmap)) {
    477		ret = PTR_ERR(chip->regmap);
    478		dev_err(&client->dev, "failed to initialise regmap: %d\n", ret);
    479		return ret;
    480	}
    481
    482	/* chip reset first */
    483	ret = _mt6660_chip_sw_reset(chip);
    484	if (ret < 0) {
    485		dev_err(chip->dev, "chip reset fail\n");
    486		goto probe_fail;
    487	}
    488	/* chip power on */
    489	ret = _mt6660_chip_power_on(chip, 1);
    490	if (ret < 0) {
    491		dev_err(chip->dev, "chip power on 2 fail\n");
    492		goto probe_fail;
    493	}
    494	/* chip devid check */
    495	ret = _mt6660_chip_id_check(chip);
    496	if (ret < 0) {
    497		dev_err(chip->dev, "chip id check fail\n");
    498		goto probe_fail;
    499	}
    500	/* chip revision get */
    501	ret = _mt6660_read_chip_revision(chip);
    502	if (ret < 0) {
    503		dev_err(chip->dev, "read chip revision fail\n");
    504		goto probe_fail;
    505	}
    506	pm_runtime_set_active(chip->dev);
    507	pm_runtime_enable(chip->dev);
    508
    509	ret = devm_snd_soc_register_component(chip->dev,
    510					       &mt6660_component_driver,
    511					       &mt6660_codec_dai, 1);
    512	return ret;
    513probe_fail:
    514	_mt6660_chip_power_on(chip, 0);
    515	mutex_destroy(&chip->io_lock);
    516	return ret;
    517}
    518
    519static int mt6660_i2c_remove(struct i2c_client *client)
    520{
    521	struct mt6660_chip *chip = i2c_get_clientdata(client);
    522
    523	pm_runtime_disable(chip->dev);
    524	pm_runtime_set_suspended(chip->dev);
    525	mutex_destroy(&chip->io_lock);
    526	return 0;
    527}
    528
    529static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev)
    530{
    531	struct mt6660_chip *chip = dev_get_drvdata(dev);
    532
    533	dev_dbg(dev, "enter low power mode\n");
    534	return regmap_update_bits(chip->regmap,
    535		MT6660_REG_SYSTEM_CTRL, 0x01, 0x01);
    536}
    537
    538static int __maybe_unused mt6660_i2c_runtime_resume(struct device *dev)
    539{
    540	struct mt6660_chip *chip = dev_get_drvdata(dev);
    541
    542	dev_dbg(dev, "exit low power mode\n");
    543	return regmap_update_bits(chip->regmap,
    544		MT6660_REG_SYSTEM_CTRL, 0x01, 0x00);
    545}
    546
    547static const struct dev_pm_ops mt6660_dev_pm_ops = {
    548	SET_RUNTIME_PM_OPS(mt6660_i2c_runtime_suspend,
    549			   mt6660_i2c_runtime_resume, NULL)
    550};
    551
    552static const struct of_device_id __maybe_unused mt6660_of_id[] = {
    553	{ .compatible = "mediatek,mt6660",},
    554	{},
    555};
    556MODULE_DEVICE_TABLE(of, mt6660_of_id);
    557
    558static const struct i2c_device_id mt6660_i2c_id[] = {
    559	{"mt6660", 0 },
    560	{},
    561};
    562MODULE_DEVICE_TABLE(i2c, mt6660_i2c_id);
    563
    564static struct i2c_driver mt6660_i2c_driver = {
    565	.driver = {
    566		.name = "mt6660",
    567		.of_match_table = of_match_ptr(mt6660_of_id),
    568		.pm = &mt6660_dev_pm_ops,
    569	},
    570	.probe_new = mt6660_i2c_probe,
    571	.remove = mt6660_i2c_remove,
    572	.id_table = mt6660_i2c_id,
    573};
    574module_i2c_driver(mt6660_i2c_driver);
    575
    576MODULE_AUTHOR("Jeff Chang <jeff_chang@richtek.com>");
    577MODULE_DESCRIPTION("MT6660 SPKAMP Driver");
    578MODULE_LICENSE("GPL");
    579MODULE_VERSION("1.0.8_G");