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

pcm3168a.c (26264B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * PCM3168A codec driver
      4 *
      5 * Copyright (C) 2015 Imagination Technologies Ltd.
      6 *
      7 * Author: Damien Horsley <Damien.Horsley@imgtec.com>
      8 */
      9
     10#include <linux/clk.h>
     11#include <linux/delay.h>
     12#include <linux/gpio/consumer.h>
     13#include <linux/module.h>
     14#include <linux/of_gpio.h>
     15#include <linux/pm_runtime.h>
     16#include <linux/regulator/consumer.h>
     17
     18#include <sound/pcm_params.h>
     19#include <sound/soc.h>
     20#include <sound/tlv.h>
     21
     22#include "pcm3168a.h"
     23
     24#define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
     25			 SNDRV_PCM_FMTBIT_S24_3LE | \
     26			 SNDRV_PCM_FMTBIT_S24_LE)
     27
     28#define PCM3168A_FMT_I2S		0x0
     29#define PCM3168A_FMT_LEFT_J		0x1
     30#define PCM3168A_FMT_RIGHT_J		0x2
     31#define PCM3168A_FMT_RIGHT_J_16		0x3
     32#define PCM3168A_FMT_DSP_A		0x4
     33#define PCM3168A_FMT_DSP_B		0x5
     34#define PCM3168A_FMT_I2S_TDM		0x6
     35#define PCM3168A_FMT_LEFT_J_TDM		0x7
     36
     37static const char *const pcm3168a_supply_names[] = {
     38	"VDD1",
     39	"VDD2",
     40	"VCCAD1",
     41	"VCCAD2",
     42	"VCCDA1",
     43	"VCCDA2"
     44};
     45
     46#define PCM3168A_DAI_DAC		0
     47#define PCM3168A_DAI_ADC		1
     48
     49/* ADC/DAC side parameters */
     50struct pcm3168a_io_params {
     51	bool provider_mode;
     52	unsigned int format;
     53	int tdm_slots;
     54	u32 tdm_mask;
     55	int slot_width;
     56};
     57
     58struct pcm3168a_priv {
     59	struct regulator_bulk_data supplies[ARRAY_SIZE(pcm3168a_supply_names)];
     60	struct regmap *regmap;
     61	struct clk *scki;
     62	struct gpio_desc *gpio_rst;
     63	unsigned long sysclk;
     64
     65	struct pcm3168a_io_params io_params[2];
     66	struct snd_soc_dai_driver dai_drv[2];
     67};
     68
     69static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
     70
     71static SOC_ENUM_SINGLE_DECL(pcm3168a_d1_roll_off, PCM3168A_DAC_OP_FLT,
     72		PCM3168A_DAC_FLT_SHIFT, pcm3168a_roll_off);
     73static SOC_ENUM_SINGLE_DECL(pcm3168a_d2_roll_off, PCM3168A_DAC_OP_FLT,
     74		PCM3168A_DAC_FLT_SHIFT + 1, pcm3168a_roll_off);
     75static SOC_ENUM_SINGLE_DECL(pcm3168a_d3_roll_off, PCM3168A_DAC_OP_FLT,
     76		PCM3168A_DAC_FLT_SHIFT + 2, pcm3168a_roll_off);
     77static SOC_ENUM_SINGLE_DECL(pcm3168a_d4_roll_off, PCM3168A_DAC_OP_FLT,
     78		PCM3168A_DAC_FLT_SHIFT + 3, pcm3168a_roll_off);
     79
     80static const char *const pcm3168a_volume_type[] = {
     81		"Individual", "Master + Individual" };
     82
     83static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_volume_type, PCM3168A_DAC_ATT_DEMP_ZF,
     84		PCM3168A_DAC_ATMDDA_SHIFT, pcm3168a_volume_type);
     85
     86static const char *const pcm3168a_att_speed_mult[] = { "2048", "4096" };
     87
     88static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_att_mult, PCM3168A_DAC_ATT_DEMP_ZF,
     89		PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_att_speed_mult);
     90
     91static const char *const pcm3168a_demp[] = {
     92		"Disabled", "48khz", "44.1khz", "32khz" };
     93
     94static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_demp, PCM3168A_DAC_ATT_DEMP_ZF,
     95		PCM3168A_DAC_DEMP_SHIFT, pcm3168a_demp);
     96
     97static const char *const pcm3168a_zf_func[] = {
     98		"DAC 1/2/3/4 AND", "DAC 1/2/3/4 OR", "DAC 1/2/3 AND",
     99		"DAC 1/2/3 OR", "DAC 4 AND", "DAC 4 OR" };
    100
    101static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_func, PCM3168A_DAC_ATT_DEMP_ZF,
    102		PCM3168A_DAC_AZRO_SHIFT, pcm3168a_zf_func);
    103
    104static const char *const pcm3168a_pol[] = { "Active High", "Active Low" };
    105
    106static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_pol, PCM3168A_DAC_ATT_DEMP_ZF,
    107		PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_pol);
    108
    109static const char *const pcm3168a_con[] = { "Differential", "Single-Ended" };
    110
    111static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc1_con, PCM3168A_ADC_SEAD,
    112				0, 1, pcm3168a_con);
    113static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc2_con, PCM3168A_ADC_SEAD,
    114				2, 3, pcm3168a_con);
    115static SOC_ENUM_DOUBLE_DECL(pcm3168a_adc3_con, PCM3168A_ADC_SEAD,
    116				4, 5, pcm3168a_con);
    117
    118static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_volume_type, PCM3168A_ADC_ATT_OVF,
    119		PCM3168A_ADC_ATMDAD_SHIFT, pcm3168a_volume_type);
    120
    121static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_att_mult, PCM3168A_ADC_ATT_OVF,
    122		PCM3168A_ADC_ATSPAD_SHIFT, pcm3168a_att_speed_mult);
    123
    124static SOC_ENUM_SINGLE_DECL(pcm3168a_adc_ov_pol, PCM3168A_ADC_ATT_OVF,
    125		PCM3168A_ADC_OVFP_SHIFT, pcm3168a_pol);
    126
    127/* -100db to 0db, register values 0-54 cause mute */
    128static const DECLARE_TLV_DB_SCALE(pcm3168a_dac_tlv, -10050, 50, 1);
    129
    130/* -100db to 20db, register values 0-14 cause mute */
    131static const DECLARE_TLV_DB_SCALE(pcm3168a_adc_tlv, -10050, 50, 1);
    132
    133static const struct snd_kcontrol_new pcm3168a_snd_controls[] = {
    134	SOC_SINGLE("DAC Power-Save Switch", PCM3168A_DAC_PWR_MST_FMT,
    135			PCM3168A_DAC_PSMDA_SHIFT, 1, 1),
    136	SOC_ENUM("DAC1 Digital Filter roll-off", pcm3168a_d1_roll_off),
    137	SOC_ENUM("DAC2 Digital Filter roll-off", pcm3168a_d2_roll_off),
    138	SOC_ENUM("DAC3 Digital Filter roll-off", pcm3168a_d3_roll_off),
    139	SOC_ENUM("DAC4 Digital Filter roll-off", pcm3168a_d4_roll_off),
    140	SOC_DOUBLE("DAC1 Invert Switch", PCM3168A_DAC_INV, 0, 1, 1, 0),
    141	SOC_DOUBLE("DAC2 Invert Switch", PCM3168A_DAC_INV, 2, 3, 1, 0),
    142	SOC_DOUBLE("DAC3 Invert Switch", PCM3168A_DAC_INV, 4, 5, 1, 0),
    143	SOC_DOUBLE("DAC4 Invert Switch", PCM3168A_DAC_INV, 6, 7, 1, 0),
    144	SOC_ENUM("DAC Volume Control Type", pcm3168a_dac_volume_type),
    145	SOC_ENUM("DAC Volume Rate Multiplier", pcm3168a_dac_att_mult),
    146	SOC_ENUM("DAC De-Emphasis", pcm3168a_dac_demp),
    147	SOC_ENUM("DAC Zero Flag Function", pcm3168a_dac_zf_func),
    148	SOC_ENUM("DAC Zero Flag Polarity", pcm3168a_dac_zf_pol),
    149	SOC_SINGLE_RANGE_TLV("Master Playback Volume",
    150			PCM3168A_DAC_VOL_MASTER, 0, 54, 255, 0,
    151			pcm3168a_dac_tlv),
    152	SOC_DOUBLE_R_RANGE_TLV("DAC1 Playback Volume",
    153			PCM3168A_DAC_VOL_CHAN_START,
    154			PCM3168A_DAC_VOL_CHAN_START + 1,
    155			0, 54, 255, 0, pcm3168a_dac_tlv),
    156	SOC_DOUBLE_R_RANGE_TLV("DAC2 Playback Volume",
    157			PCM3168A_DAC_VOL_CHAN_START + 2,
    158			PCM3168A_DAC_VOL_CHAN_START + 3,
    159			0, 54, 255, 0, pcm3168a_dac_tlv),
    160	SOC_DOUBLE_R_RANGE_TLV("DAC3 Playback Volume",
    161			PCM3168A_DAC_VOL_CHAN_START + 4,
    162			PCM3168A_DAC_VOL_CHAN_START + 5,
    163			0, 54, 255, 0, pcm3168a_dac_tlv),
    164	SOC_DOUBLE_R_RANGE_TLV("DAC4 Playback Volume",
    165			PCM3168A_DAC_VOL_CHAN_START + 6,
    166			PCM3168A_DAC_VOL_CHAN_START + 7,
    167			0, 54, 255, 0, pcm3168a_dac_tlv),
    168	SOC_SINGLE("ADC1 High-Pass Filter Switch", PCM3168A_ADC_PWR_HPFB,
    169			PCM3168A_ADC_BYP_SHIFT, 1, 1),
    170	SOC_SINGLE("ADC2 High-Pass Filter Switch", PCM3168A_ADC_PWR_HPFB,
    171			PCM3168A_ADC_BYP_SHIFT + 1, 1, 1),
    172	SOC_SINGLE("ADC3 High-Pass Filter Switch", PCM3168A_ADC_PWR_HPFB,
    173			PCM3168A_ADC_BYP_SHIFT + 2, 1, 1),
    174	SOC_ENUM("ADC1 Connection Type", pcm3168a_adc1_con),
    175	SOC_ENUM("ADC2 Connection Type", pcm3168a_adc2_con),
    176	SOC_ENUM("ADC3 Connection Type", pcm3168a_adc3_con),
    177	SOC_DOUBLE("ADC1 Invert Switch", PCM3168A_ADC_INV, 0, 1, 1, 0),
    178	SOC_DOUBLE("ADC2 Invert Switch", PCM3168A_ADC_INV, 2, 3, 1, 0),
    179	SOC_DOUBLE("ADC3 Invert Switch", PCM3168A_ADC_INV, 4, 5, 1, 0),
    180	SOC_DOUBLE("ADC1 Mute Switch", PCM3168A_ADC_MUTE, 0, 1, 1, 0),
    181	SOC_DOUBLE("ADC2 Mute Switch", PCM3168A_ADC_MUTE, 2, 3, 1, 0),
    182	SOC_DOUBLE("ADC3 Mute Switch", PCM3168A_ADC_MUTE, 4, 5, 1, 0),
    183	SOC_ENUM("ADC Volume Control Type", pcm3168a_adc_volume_type),
    184	SOC_ENUM("ADC Volume Rate Multiplier", pcm3168a_adc_att_mult),
    185	SOC_ENUM("ADC Overflow Flag Polarity", pcm3168a_adc_ov_pol),
    186	SOC_SINGLE_RANGE_TLV("Master Capture Volume",
    187			PCM3168A_ADC_VOL_MASTER, 0, 14, 255, 0,
    188			pcm3168a_adc_tlv),
    189	SOC_DOUBLE_R_RANGE_TLV("ADC1 Capture Volume",
    190			PCM3168A_ADC_VOL_CHAN_START,
    191			PCM3168A_ADC_VOL_CHAN_START + 1,
    192			0, 14, 255, 0, pcm3168a_adc_tlv),
    193	SOC_DOUBLE_R_RANGE_TLV("ADC2 Capture Volume",
    194			PCM3168A_ADC_VOL_CHAN_START + 2,
    195			PCM3168A_ADC_VOL_CHAN_START + 3,
    196			0, 14, 255, 0, pcm3168a_adc_tlv),
    197	SOC_DOUBLE_R_RANGE_TLV("ADC3 Capture Volume",
    198			PCM3168A_ADC_VOL_CHAN_START + 4,
    199			PCM3168A_ADC_VOL_CHAN_START + 5,
    200			0, 14, 255, 0, pcm3168a_adc_tlv)
    201};
    202
    203static const struct snd_soc_dapm_widget pcm3168a_dapm_widgets[] = {
    204	SND_SOC_DAPM_DAC("DAC1", "Playback", PCM3168A_DAC_OP_FLT,
    205			PCM3168A_DAC_OPEDA_SHIFT, 1),
    206	SND_SOC_DAPM_DAC("DAC2", "Playback", PCM3168A_DAC_OP_FLT,
    207			PCM3168A_DAC_OPEDA_SHIFT + 1, 1),
    208	SND_SOC_DAPM_DAC("DAC3", "Playback", PCM3168A_DAC_OP_FLT,
    209			PCM3168A_DAC_OPEDA_SHIFT + 2, 1),
    210	SND_SOC_DAPM_DAC("DAC4", "Playback", PCM3168A_DAC_OP_FLT,
    211			PCM3168A_DAC_OPEDA_SHIFT + 3, 1),
    212
    213	SND_SOC_DAPM_OUTPUT("AOUT1L"),
    214	SND_SOC_DAPM_OUTPUT("AOUT1R"),
    215	SND_SOC_DAPM_OUTPUT("AOUT2L"),
    216	SND_SOC_DAPM_OUTPUT("AOUT2R"),
    217	SND_SOC_DAPM_OUTPUT("AOUT3L"),
    218	SND_SOC_DAPM_OUTPUT("AOUT3R"),
    219	SND_SOC_DAPM_OUTPUT("AOUT4L"),
    220	SND_SOC_DAPM_OUTPUT("AOUT4R"),
    221
    222	SND_SOC_DAPM_ADC("ADC1", "Capture", PCM3168A_ADC_PWR_HPFB,
    223			PCM3168A_ADC_PSVAD_SHIFT, 1),
    224	SND_SOC_DAPM_ADC("ADC2", "Capture", PCM3168A_ADC_PWR_HPFB,
    225			PCM3168A_ADC_PSVAD_SHIFT + 1, 1),
    226	SND_SOC_DAPM_ADC("ADC3", "Capture", PCM3168A_ADC_PWR_HPFB,
    227			PCM3168A_ADC_PSVAD_SHIFT + 2, 1),
    228
    229	SND_SOC_DAPM_INPUT("AIN1L"),
    230	SND_SOC_DAPM_INPUT("AIN1R"),
    231	SND_SOC_DAPM_INPUT("AIN2L"),
    232	SND_SOC_DAPM_INPUT("AIN2R"),
    233	SND_SOC_DAPM_INPUT("AIN3L"),
    234	SND_SOC_DAPM_INPUT("AIN3R")
    235};
    236
    237static const struct snd_soc_dapm_route pcm3168a_dapm_routes[] = {
    238	/* Playback */
    239	{ "AOUT1L", NULL, "DAC1" },
    240	{ "AOUT1R", NULL, "DAC1" },
    241
    242	{ "AOUT2L", NULL, "DAC2" },
    243	{ "AOUT2R", NULL, "DAC2" },
    244
    245	{ "AOUT3L", NULL, "DAC3" },
    246	{ "AOUT3R", NULL, "DAC3" },
    247
    248	{ "AOUT4L", NULL, "DAC4" },
    249	{ "AOUT4R", NULL, "DAC4" },
    250
    251	/* Capture */
    252	{ "ADC1", NULL, "AIN1L" },
    253	{ "ADC1", NULL, "AIN1R" },
    254
    255	{ "ADC2", NULL, "AIN2L" },
    256	{ "ADC2", NULL, "AIN2R" },
    257
    258	{ "ADC3", NULL, "AIN3L" },
    259	{ "ADC3", NULL, "AIN3R" }
    260};
    261
    262static unsigned int pcm3168a_scki_ratios[] = {
    263	768,
    264	512,
    265	384,
    266	256,
    267	192,
    268	128
    269};
    270
    271#define PCM3168A_NUM_SCKI_RATIOS_DAC	ARRAY_SIZE(pcm3168a_scki_ratios)
    272#define PCM3168A_NUM_SCKI_RATIOS_ADC	(ARRAY_SIZE(pcm3168a_scki_ratios) - 2)
    273
    274#define PCM3168A_MAX_SYSCLK		36864000
    275
    276static int pcm3168a_reset(struct pcm3168a_priv *pcm3168a)
    277{
    278	int ret;
    279
    280	ret = regmap_write(pcm3168a->regmap, PCM3168A_RST_SMODE, 0);
    281	if (ret)
    282		return ret;
    283
    284	/* Internal reset is de-asserted after 3846 SCKI cycles */
    285	msleep(DIV_ROUND_UP(3846 * 1000, pcm3168a->sysclk));
    286
    287	return regmap_write(pcm3168a->regmap, PCM3168A_RST_SMODE,
    288			PCM3168A_MRST_MASK | PCM3168A_SRST_MASK);
    289}
    290
    291static int pcm3168a_mute(struct snd_soc_dai *dai, int mute, int direction)
    292{
    293	struct snd_soc_component *component = dai->component;
    294	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
    295
    296	regmap_write(pcm3168a->regmap, PCM3168A_DAC_MUTE, mute ? 0xff : 0);
    297
    298	return 0;
    299}
    300
    301static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
    302				  int clk_id, unsigned int freq, int dir)
    303{
    304	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
    305	int ret;
    306
    307	/*
    308	 * Some sound card sets 0 Hz as reset,
    309	 * but it is impossible to set. Ignore it here
    310	 */
    311	if (freq == 0)
    312		return 0;
    313
    314	if (freq > PCM3168A_MAX_SYSCLK)
    315		return -EINVAL;
    316
    317	ret = clk_set_rate(pcm3168a->scki, freq);
    318	if (ret)
    319		return ret;
    320
    321	pcm3168a->sysclk = freq;
    322
    323	return 0;
    324}
    325
    326static void pcm3168a_update_fixup_pcm_stream(struct snd_soc_dai *dai)
    327{
    328	struct snd_soc_component *component = dai->component;
    329	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
    330	struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
    331	u64 formats = SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE;
    332	unsigned int channel_max = dai->id == PCM3168A_DAI_DAC ? 8 : 6;
    333
    334	if (io_params->format == SND_SOC_DAIFMT_RIGHT_J) {
    335		/* S16_LE is only supported in RIGHT_J mode */
    336		formats |= SNDRV_PCM_FMTBIT_S16_LE;
    337
    338		/*
    339		 * If multi DIN/DOUT is not selected, RIGHT_J can only support
    340		 * two channels (no TDM support)
    341		 */
    342		if (io_params->tdm_slots != 2)
    343			channel_max = 2;
    344	}
    345
    346	if (dai->id == PCM3168A_DAI_DAC) {
    347		dai->driver->playback.channels_max = channel_max;
    348		dai->driver->playback.formats = formats;
    349	} else {
    350		dai->driver->capture.channels_max = channel_max;
    351		dai->driver->capture.formats = formats;
    352	}
    353}
    354
    355static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
    356{
    357	struct snd_soc_component *component = dai->component;
    358	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
    359	struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
    360	bool provider_mode;
    361
    362	switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
    363	case SND_SOC_DAIFMT_LEFT_J:
    364	case SND_SOC_DAIFMT_I2S:
    365	case SND_SOC_DAIFMT_RIGHT_J:
    366	case SND_SOC_DAIFMT_DSP_A:
    367	case SND_SOC_DAIFMT_DSP_B:
    368		break;
    369	default:
    370		dev_err(component->dev, "unsupported dai format\n");
    371		return -EINVAL;
    372	}
    373
    374	switch (format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
    375	case SND_SOC_DAIFMT_CBC_CFC:
    376		provider_mode = false;
    377		break;
    378	case SND_SOC_DAIFMT_CBP_CFP:
    379		provider_mode = true;
    380		break;
    381	default:
    382		dev_err(component->dev, "unsupported provider mode\n");
    383		return -EINVAL;
    384	}
    385
    386	switch (format & SND_SOC_DAIFMT_INV_MASK) {
    387	case SND_SOC_DAIFMT_NB_NF:
    388		break;
    389	default:
    390		return -EINVAL;
    391	}
    392
    393	io_params->provider_mode = provider_mode;
    394	io_params->format = format & SND_SOC_DAIFMT_FORMAT_MASK;
    395
    396	pcm3168a_update_fixup_pcm_stream(dai);
    397
    398	return 0;
    399}
    400
    401static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
    402				 unsigned int rx_mask, int slots,
    403				 int slot_width)
    404{
    405	struct snd_soc_component *component = dai->component;
    406	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
    407	struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
    408
    409	if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) {
    410		dev_err(component->dev,
    411			"Bad tdm mask tx: 0x%08x rx: 0x%08x slots %d\n",
    412			tx_mask, rx_mask, slots);
    413		return -EINVAL;
    414	}
    415
    416	if (slot_width &&
    417	    (slot_width != 16 && slot_width != 24 && slot_width != 32 )) {
    418		dev_err(component->dev, "Unsupported slot_width %d\n",
    419			slot_width);
    420		return -EINVAL;
    421	}
    422
    423	io_params->tdm_slots = slots;
    424	io_params->slot_width = slot_width;
    425	/* Ignore the not relevant mask for the DAI/direction */
    426	if (dai->id == PCM3168A_DAI_DAC)
    427		io_params->tdm_mask = tx_mask;
    428	else
    429		io_params->tdm_mask = rx_mask;
    430
    431	pcm3168a_update_fixup_pcm_stream(dai);
    432
    433	return 0;
    434}
    435
    436static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
    437			     struct snd_pcm_hw_params *params,
    438			     struct snd_soc_dai *dai)
    439{
    440	struct snd_soc_component *component = dai->component;
    441	struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
    442	struct pcm3168a_io_params *io_params = &pcm3168a->io_params[dai->id];
    443	bool provider_mode, tdm_mode;
    444	unsigned int format;
    445	unsigned int reg, mask, ms, ms_shift, fmt, fmt_shift, ratio, tdm_slots;
    446	int i, num_scki_ratios, slot_width;
    447
    448	if (dai->id == PCM3168A_DAI_DAC) {
    449		num_scki_ratios = PCM3168A_NUM_SCKI_RATIOS_DAC;
    450		reg = PCM3168A_DAC_PWR_MST_FMT;
    451		mask = PCM3168A_DAC_MSDA_MASK | PCM3168A_DAC_FMT_MASK;
    452		ms_shift = PCM3168A_DAC_MSDA_SHIFT;
    453		fmt_shift = PCM3168A_DAC_FMT_SHIFT;
    454	} else {
    455		num_scki_ratios = PCM3168A_NUM_SCKI_RATIOS_ADC;
    456		reg = PCM3168A_ADC_MST_FMT;
    457		mask = PCM3168A_ADC_MSAD_MASK | PCM3168A_ADC_FMTAD_MASK;
    458		ms_shift = PCM3168A_ADC_MSAD_SHIFT;
    459		fmt_shift = PCM3168A_ADC_FMTAD_SHIFT;
    460	}
    461
    462	provider_mode = io_params->provider_mode;
    463
    464	if (provider_mode) {
    465		ratio = pcm3168a->sysclk / params_rate(params);
    466
    467		for (i = 0; i < num_scki_ratios; i++) {
    468			if (pcm3168a_scki_ratios[i] == ratio)
    469				break;
    470		}
    471
    472		if (i == num_scki_ratios) {
    473			dev_err(component->dev, "unsupported sysclk ratio\n");
    474			return -EINVAL;
    475		}
    476
    477		ms = (i + 1);
    478	} else {
    479		ms = 0;
    480	}
    481
    482	format = io_params->format;
    483
    484	if (io_params->slot_width)
    485		slot_width = io_params->slot_width;
    486	else
    487		slot_width = params_width(params);
    488
    489	switch (slot_width) {
    490	case 16:
    491		if (provider_mode || (format != SND_SOC_DAIFMT_RIGHT_J)) {
    492			dev_err(component->dev, "16-bit slots are supported only for consumer mode using right justified\n");
    493			return -EINVAL;
    494		}
    495		break;
    496	case 24:
    497		if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) ||
    498		    		     (format == SND_SOC_DAIFMT_DSP_B)) {
    499			dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n");
    500			return -EINVAL;
    501		}
    502		break;
    503	case 32:
    504		break;
    505	default:
    506		dev_err(component->dev, "unsupported frame size: %d\n", slot_width);
    507		return -EINVAL;
    508	}
    509
    510	if (io_params->tdm_slots)
    511		tdm_slots = io_params->tdm_slots;
    512	else
    513		tdm_slots = params_channels(params);
    514
    515	/*
    516	 * Switch the codec to TDM mode when more than 2 TDM slots are needed
    517	 * for the stream.
    518	 * If pcm3168a->tdm_slots is not set or set to more than 2 (8/6 usually)
    519	 * then DIN1/DOUT1 is used in TDM mode.
    520	 * If pcm3168a->tdm_slots is set to 2 then DIN1/2/3/4 and DOUT1/2/3 is
    521	 * used in normal mode, no need to switch to TDM modes.
    522	 */
    523	tdm_mode = (tdm_slots > 2);
    524
    525	if (tdm_mode) {
    526		switch (format) {
    527		case SND_SOC_DAIFMT_I2S:
    528		case SND_SOC_DAIFMT_DSP_A:
    529		case SND_SOC_DAIFMT_LEFT_J:
    530		case SND_SOC_DAIFMT_DSP_B:
    531			break;
    532		default:
    533			dev_err(component->dev,
    534				"TDM is supported under DSP/I2S/Left_J only\n");
    535			return -EINVAL;
    536		}
    537	}
    538
    539	switch (format) {
    540	case SND_SOC_DAIFMT_I2S:
    541		fmt = tdm_mode ? PCM3168A_FMT_I2S_TDM : PCM3168A_FMT_I2S;
    542		break;
    543	case SND_SOC_DAIFMT_LEFT_J:
    544		fmt = tdm_mode ? PCM3168A_FMT_LEFT_J_TDM : PCM3168A_FMT_LEFT_J;
    545		break;
    546	case SND_SOC_DAIFMT_RIGHT_J:
    547		fmt = (slot_width == 16) ? PCM3168A_FMT_RIGHT_J_16 :
    548					   PCM3168A_FMT_RIGHT_J;
    549		break;
    550	case SND_SOC_DAIFMT_DSP_A:
    551		fmt = tdm_mode ? PCM3168A_FMT_I2S_TDM : PCM3168A_FMT_DSP_A;
    552		break;
    553	case SND_SOC_DAIFMT_DSP_B:
    554		fmt = tdm_mode ? PCM3168A_FMT_LEFT_J_TDM : PCM3168A_FMT_DSP_B;
    555		break;
    556	default:
    557		return -EINVAL;
    558	}
    559
    560	regmap_update_bits(pcm3168a->regmap, reg, mask,
    561			(ms << ms_shift) | (fmt << fmt_shift));
    562
    563	return 0;
    564}
    565
    566static u64 pcm3168a_dai_formats[] = {
    567	/*
    568	 * Select below from Sound Card, not here
    569	 *	SND_SOC_DAIFMT_CBC_CFC
    570	 *	SND_SOC_DAIFMT_CBP_CFP
    571	 */
    572
    573	/*
    574	 * First Priority
    575	 */
    576	SND_SOC_POSSIBLE_DAIFMT_I2S	|
    577	SND_SOC_POSSIBLE_DAIFMT_LEFT_J,
    578	/*
    579	 * Second Priority
    580	 *
    581	 * These have picky limitation.
    582	 * see
    583	 *	pcm3168a_hw_params()
    584	 */
    585	SND_SOC_POSSIBLE_DAIFMT_RIGHT_J	|
    586	SND_SOC_POSSIBLE_DAIFMT_DSP_A	|
    587	SND_SOC_POSSIBLE_DAIFMT_DSP_B,
    588};
    589
    590static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
    591	.set_fmt	= pcm3168a_set_dai_fmt,
    592	.set_sysclk	= pcm3168a_set_dai_sysclk,
    593	.hw_params	= pcm3168a_hw_params,
    594	.mute_stream	= pcm3168a_mute,
    595	.set_tdm_slot	= pcm3168a_set_tdm_slot,
    596	.no_capture_mute = 1,
    597	.auto_selectable_formats	= pcm3168a_dai_formats,
    598	.num_auto_selectable_formats	= ARRAY_SIZE(pcm3168a_dai_formats),
    599};
    600
    601static struct snd_soc_dai_driver pcm3168a_dais[] = {
    602	{
    603		.name = "pcm3168a-dac",
    604		.id = PCM3168A_DAI_DAC,
    605		.playback = {
    606			.stream_name = "Playback",
    607			.channels_min = 1,
    608			.channels_max = 8,
    609			.rates = SNDRV_PCM_RATE_8000_192000,
    610			.formats = PCM3168A_FORMATS
    611		},
    612		.ops = &pcm3168a_dai_ops
    613	},
    614	{
    615		.name = "pcm3168a-adc",
    616		.id = PCM3168A_DAI_ADC,
    617		.capture = {
    618			.stream_name = "Capture",
    619			.channels_min = 1,
    620			.channels_max = 6,
    621			.rates = SNDRV_PCM_RATE_8000_96000,
    622			.formats = PCM3168A_FORMATS
    623		},
    624		.ops = &pcm3168a_dai_ops
    625	},
    626};
    627
    628static const struct reg_default pcm3168a_reg_default[] = {
    629	{ PCM3168A_RST_SMODE, PCM3168A_MRST_MASK | PCM3168A_SRST_MASK },
    630	{ PCM3168A_DAC_PWR_MST_FMT, 0x00 },
    631	{ PCM3168A_DAC_OP_FLT, 0x00 },
    632	{ PCM3168A_DAC_INV, 0x00 },
    633	{ PCM3168A_DAC_MUTE, 0x00 },
    634	{ PCM3168A_DAC_ZERO, 0x00 },
    635	{ PCM3168A_DAC_ATT_DEMP_ZF, 0x00 },
    636	{ PCM3168A_DAC_VOL_MASTER, 0xff },
    637	{ PCM3168A_DAC_VOL_CHAN_START, 0xff },
    638	{ PCM3168A_DAC_VOL_CHAN_START + 1, 0xff },
    639	{ PCM3168A_DAC_VOL_CHAN_START + 2, 0xff },
    640	{ PCM3168A_DAC_VOL_CHAN_START + 3, 0xff },
    641	{ PCM3168A_DAC_VOL_CHAN_START + 4, 0xff },
    642	{ PCM3168A_DAC_VOL_CHAN_START + 5, 0xff },
    643	{ PCM3168A_DAC_VOL_CHAN_START + 6, 0xff },
    644	{ PCM3168A_DAC_VOL_CHAN_START + 7, 0xff },
    645	{ PCM3168A_ADC_SMODE, 0x00 },
    646	{ PCM3168A_ADC_MST_FMT, 0x00 },
    647	{ PCM3168A_ADC_PWR_HPFB, 0x00 },
    648	{ PCM3168A_ADC_SEAD, 0x00 },
    649	{ PCM3168A_ADC_INV, 0x00 },
    650	{ PCM3168A_ADC_MUTE, 0x00 },
    651	{ PCM3168A_ADC_OV, 0x00 },
    652	{ PCM3168A_ADC_ATT_OVF, 0x00 },
    653	{ PCM3168A_ADC_VOL_MASTER, 0xd3 },
    654	{ PCM3168A_ADC_VOL_CHAN_START, 0xd3 },
    655	{ PCM3168A_ADC_VOL_CHAN_START + 1, 0xd3 },
    656	{ PCM3168A_ADC_VOL_CHAN_START + 2, 0xd3 },
    657	{ PCM3168A_ADC_VOL_CHAN_START + 3, 0xd3 },
    658	{ PCM3168A_ADC_VOL_CHAN_START + 4, 0xd3 },
    659	{ PCM3168A_ADC_VOL_CHAN_START + 5, 0xd3 }
    660};
    661
    662static bool pcm3168a_readable_register(struct device *dev, unsigned int reg)
    663{
    664	if (reg >= PCM3168A_RST_SMODE)
    665		return true;
    666	else
    667		return false;
    668}
    669
    670static bool pcm3168a_volatile_register(struct device *dev, unsigned int reg)
    671{
    672	switch (reg) {
    673	case PCM3168A_RST_SMODE:
    674	case PCM3168A_DAC_ZERO:
    675	case PCM3168A_ADC_OV:
    676		return true;
    677	default:
    678		return false;
    679	}
    680}
    681
    682static bool pcm3168a_writeable_register(struct device *dev, unsigned int reg)
    683{
    684	if (reg < PCM3168A_RST_SMODE)
    685		return false;
    686
    687	switch (reg) {
    688	case PCM3168A_DAC_ZERO:
    689	case PCM3168A_ADC_OV:
    690		return false;
    691	default:
    692		return true;
    693	}
    694}
    695
    696const struct regmap_config pcm3168a_regmap = {
    697	.reg_bits = 8,
    698	.val_bits = 8,
    699
    700	.max_register = PCM3168A_ADC_VOL_CHAN_START + 5,
    701	.reg_defaults = pcm3168a_reg_default,
    702	.num_reg_defaults = ARRAY_SIZE(pcm3168a_reg_default),
    703	.readable_reg = pcm3168a_readable_register,
    704	.volatile_reg = pcm3168a_volatile_register,
    705	.writeable_reg = pcm3168a_writeable_register,
    706	.cache_type = REGCACHE_FLAT
    707};
    708EXPORT_SYMBOL_GPL(pcm3168a_regmap);
    709
    710static const struct snd_soc_component_driver pcm3168a_driver = {
    711	.controls		= pcm3168a_snd_controls,
    712	.num_controls		= ARRAY_SIZE(pcm3168a_snd_controls),
    713	.dapm_widgets		= pcm3168a_dapm_widgets,
    714	.num_dapm_widgets	= ARRAY_SIZE(pcm3168a_dapm_widgets),
    715	.dapm_routes		= pcm3168a_dapm_routes,
    716	.num_dapm_routes	= ARRAY_SIZE(pcm3168a_dapm_routes),
    717	.use_pmdown_time	= 1,
    718	.endianness		= 1,
    719	.non_legacy_dai_naming	= 1,
    720};
    721
    722int pcm3168a_probe(struct device *dev, struct regmap *regmap)
    723{
    724	struct pcm3168a_priv *pcm3168a;
    725	int ret, i;
    726
    727	pcm3168a = devm_kzalloc(dev, sizeof(*pcm3168a), GFP_KERNEL);
    728	if (pcm3168a == NULL)
    729		return -ENOMEM;
    730
    731	dev_set_drvdata(dev, pcm3168a);
    732
    733	/*
    734	 * Request the reset (connected to RST pin) gpio line as non exclusive
    735	 * as the same reset line might be connected to multiple pcm3168a codec
    736	 *
    737	 * The RST is low active, we want the GPIO line to be high initially, so
    738	 * request the initial level to LOW which in practice means DEASSERTED:
    739	 * The deasserted level of GPIO_ACTIVE_LOW is HIGH.
    740	 */
    741	pcm3168a->gpio_rst = devm_gpiod_get_optional(dev, "reset",
    742						GPIOD_OUT_LOW |
    743						GPIOD_FLAGS_BIT_NONEXCLUSIVE);
    744	if (IS_ERR(pcm3168a->gpio_rst))
    745		return dev_err_probe(dev, PTR_ERR(pcm3168a->gpio_rst),
    746				     "failed to acquire RST gpio\n");
    747
    748	pcm3168a->scki = devm_clk_get(dev, "scki");
    749	if (IS_ERR(pcm3168a->scki))
    750		return dev_err_probe(dev, PTR_ERR(pcm3168a->scki),
    751				     "failed to acquire clock 'scki'\n");
    752
    753	ret = clk_prepare_enable(pcm3168a->scki);
    754	if (ret) {
    755		dev_err(dev, "Failed to enable mclk: %d\n", ret);
    756		return ret;
    757	}
    758
    759	pcm3168a->sysclk = clk_get_rate(pcm3168a->scki);
    760
    761	for (i = 0; i < ARRAY_SIZE(pcm3168a->supplies); i++)
    762		pcm3168a->supplies[i].supply = pcm3168a_supply_names[i];
    763
    764	ret = devm_regulator_bulk_get(dev,
    765			ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies);
    766	if (ret) {
    767		dev_err_probe(dev, ret, "failed to request supplies\n");
    768		goto err_clk;
    769	}
    770
    771	ret = regulator_bulk_enable(ARRAY_SIZE(pcm3168a->supplies),
    772				    pcm3168a->supplies);
    773	if (ret) {
    774		dev_err(dev, "failed to enable supplies: %d\n", ret);
    775		goto err_clk;
    776	}
    777
    778	pcm3168a->regmap = regmap;
    779	if (IS_ERR(pcm3168a->regmap)) {
    780		ret = PTR_ERR(pcm3168a->regmap);
    781		dev_err(dev, "failed to allocate regmap: %d\n", ret);
    782		goto err_regulator;
    783	}
    784
    785	if (pcm3168a->gpio_rst) {
    786		/*
    787		 * The device is taken out from reset via GPIO line, wait for
    788		 * 3846 SCKI clock cycles for the internal reset de-assertion
    789		 */
    790		msleep(DIV_ROUND_UP(3846 * 1000, pcm3168a->sysclk));
    791	} else {
    792		ret = pcm3168a_reset(pcm3168a);
    793		if (ret) {
    794			dev_err(dev, "Failed to reset device: %d\n", ret);
    795			goto err_regulator;
    796		}
    797	}
    798
    799	pm_runtime_set_active(dev);
    800	pm_runtime_enable(dev);
    801	pm_runtime_idle(dev);
    802
    803	memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv));
    804	ret = devm_snd_soc_register_component(dev, &pcm3168a_driver,
    805					      pcm3168a->dai_drv,
    806					      ARRAY_SIZE(pcm3168a->dai_drv));
    807	if (ret) {
    808		dev_err(dev, "failed to register component: %d\n", ret);
    809		goto err_regulator;
    810	}
    811
    812	return 0;
    813
    814err_regulator:
    815	regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
    816			pcm3168a->supplies);
    817err_clk:
    818	clk_disable_unprepare(pcm3168a->scki);
    819
    820	return ret;
    821}
    822EXPORT_SYMBOL_GPL(pcm3168a_probe);
    823
    824static void pcm3168a_disable(struct device *dev)
    825{
    826	struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
    827
    828	regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
    829			       pcm3168a->supplies);
    830	clk_disable_unprepare(pcm3168a->scki);
    831}
    832
    833void pcm3168a_remove(struct device *dev)
    834{
    835	struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
    836
    837	/*
    838	 * The RST is low active, we want the GPIO line to be low when the
    839	 * driver is removed, so set level to 1 which in practice means
    840	 * ASSERTED:
    841	 * The asserted level of GPIO_ACTIVE_LOW is LOW.
    842	 */
    843	gpiod_set_value_cansleep(pcm3168a->gpio_rst, 1);
    844	pm_runtime_disable(dev);
    845#ifndef CONFIG_PM
    846	pcm3168a_disable(dev);
    847#endif
    848}
    849EXPORT_SYMBOL_GPL(pcm3168a_remove);
    850
    851#ifdef CONFIG_PM
    852static int pcm3168a_rt_resume(struct device *dev)
    853{
    854	struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
    855	int ret;
    856
    857	ret = clk_prepare_enable(pcm3168a->scki);
    858	if (ret) {
    859		dev_err(dev, "Failed to enable mclk: %d\n", ret);
    860		return ret;
    861	}
    862
    863	ret = regulator_bulk_enable(ARRAY_SIZE(pcm3168a->supplies),
    864				    pcm3168a->supplies);
    865	if (ret) {
    866		dev_err(dev, "Failed to enable supplies: %d\n", ret);
    867		goto err_clk;
    868	}
    869
    870	ret = pcm3168a_reset(pcm3168a);
    871	if (ret) {
    872		dev_err(dev, "Failed to reset device: %d\n", ret);
    873		goto err_regulator;
    874	}
    875
    876	regcache_cache_only(pcm3168a->regmap, false);
    877
    878	regcache_mark_dirty(pcm3168a->regmap);
    879
    880	ret = regcache_sync(pcm3168a->regmap);
    881	if (ret) {
    882		dev_err(dev, "Failed to sync regmap: %d\n", ret);
    883		goto err_regulator;
    884	}
    885
    886	return 0;
    887
    888err_regulator:
    889	regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
    890			       pcm3168a->supplies);
    891err_clk:
    892	clk_disable_unprepare(pcm3168a->scki);
    893
    894	return ret;
    895}
    896
    897static int pcm3168a_rt_suspend(struct device *dev)
    898{
    899	struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
    900
    901	regcache_cache_only(pcm3168a->regmap, true);
    902
    903	pcm3168a_disable(dev);
    904
    905	return 0;
    906}
    907#endif
    908
    909const struct dev_pm_ops pcm3168a_pm_ops = {
    910	SET_RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL)
    911};
    912EXPORT_SYMBOL_GPL(pcm3168a_pm_ops);
    913
    914MODULE_DESCRIPTION("PCM3168A codec driver");
    915MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
    916MODULE_LICENSE("GPL v2");