162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// rk3328 ALSA SoC Audio driver
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/clk.h>
862306a36Sopenharmony_ci#include <linux/delay.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/of.h>
1362306a36Sopenharmony_ci#include <linux/platform_device.h>
1462306a36Sopenharmony_ci#include <linux/regmap.h>
1562306a36Sopenharmony_ci#include <linux/mfd/syscon.h>
1662306a36Sopenharmony_ci#include <sound/dmaengine_pcm.h>
1762306a36Sopenharmony_ci#include <sound/pcm_params.h>
1862306a36Sopenharmony_ci#include "rk3328_codec.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * volume setting
2262306a36Sopenharmony_ci * 0: -39dB
2362306a36Sopenharmony_ci * 26: 0dB
2462306a36Sopenharmony_ci * 31: 6dB
2562306a36Sopenharmony_ci * Step: 1.5dB
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ci#define OUT_VOLUME	(0x18)
2862306a36Sopenharmony_ci#define RK3328_GRF_SOC_CON2	(0x0408)
2962306a36Sopenharmony_ci#define RK3328_GRF_SOC_CON10	(0x0428)
3062306a36Sopenharmony_ci#define INITIAL_FREQ	(11289600)
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistruct rk3328_codec_priv {
3362306a36Sopenharmony_ci	struct regmap *regmap;
3462306a36Sopenharmony_ci	struct gpio_desc *mute;
3562306a36Sopenharmony_ci	struct clk *mclk;
3662306a36Sopenharmony_ci	struct clk *pclk;
3762306a36Sopenharmony_ci	unsigned int sclk;
3862306a36Sopenharmony_ci	int spk_depop_time; /* msec */
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic const struct reg_default rk3328_codec_reg_defaults[] = {
4262306a36Sopenharmony_ci	{ CODEC_RESET, 0x03 },
4362306a36Sopenharmony_ci	{ DAC_INIT_CTRL1, 0x00 },
4462306a36Sopenharmony_ci	{ DAC_INIT_CTRL2, 0x50 },
4562306a36Sopenharmony_ci	{ DAC_INIT_CTRL3, 0x0e },
4662306a36Sopenharmony_ci	{ DAC_PRECHARGE_CTRL, 0x01 },
4762306a36Sopenharmony_ci	{ DAC_PWR_CTRL, 0x00 },
4862306a36Sopenharmony_ci	{ DAC_CLK_CTRL, 0x00 },
4962306a36Sopenharmony_ci	{ HPMIX_CTRL, 0x00 },
5062306a36Sopenharmony_ci	{ HPOUT_CTRL, 0x00 },
5162306a36Sopenharmony_ci	{ HPOUTL_GAIN_CTRL, 0x00 },
5262306a36Sopenharmony_ci	{ HPOUTR_GAIN_CTRL, 0x00 },
5362306a36Sopenharmony_ci	{ HPOUT_POP_CTRL, 0x11 },
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
5962306a36Sopenharmony_ci	mdelay(10);
6062306a36Sopenharmony_ci	regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
6862306a36Sopenharmony_ci		snd_soc_component_get_drvdata(dai->component);
6962306a36Sopenharmony_ci	unsigned int val;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
7262306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBC_CFC:
7362306a36Sopenharmony_ci		val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
7462306a36Sopenharmony_ci		break;
7562306a36Sopenharmony_ci	case SND_SOC_DAIFMT_CBP_CFP:
7662306a36Sopenharmony_ci		val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
7762306a36Sopenharmony_ci		break;
7862306a36Sopenharmony_ci	default:
7962306a36Sopenharmony_ci		return -EINVAL;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
8362306a36Sopenharmony_ci			   PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
8662306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
8762306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_B:
8862306a36Sopenharmony_ci		val = DAC_MODE_PCM;
8962306a36Sopenharmony_ci		break;
9062306a36Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
9162306a36Sopenharmony_ci		val = DAC_MODE_I2S;
9262306a36Sopenharmony_ci		break;
9362306a36Sopenharmony_ci	case SND_SOC_DAIFMT_RIGHT_J:
9462306a36Sopenharmony_ci		val = DAC_MODE_RJM;
9562306a36Sopenharmony_ci		break;
9662306a36Sopenharmony_ci	case SND_SOC_DAIFMT_LEFT_J:
9762306a36Sopenharmony_ci		val = DAC_MODE_LJM;
9862306a36Sopenharmony_ci		break;
9962306a36Sopenharmony_ci	default:
10062306a36Sopenharmony_ci		return -EINVAL;
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
10462306a36Sopenharmony_ci			   DAC_MODE_MASK, val);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return 0;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
11262306a36Sopenharmony_ci		snd_soc_component_get_drvdata(dai->component);
11362306a36Sopenharmony_ci	unsigned int val;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	if (mute)
11662306a36Sopenharmony_ci		val = HPOUTL_MUTE | HPOUTR_MUTE;
11762306a36Sopenharmony_ci	else
11862306a36Sopenharmony_ci		val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
12162306a36Sopenharmony_ci			   HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return 0;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
12962306a36Sopenharmony_ci			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
13062306a36Sopenharmony_ci	mdelay(10);
13162306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
13262306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_MASK,
13362306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_ON);
13462306a36Sopenharmony_ci	mdelay(wait_ms);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	return 0;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
14262306a36Sopenharmony_ci			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
14362306a36Sopenharmony_ci	mdelay(10);
14462306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
14562306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_MASK,
14662306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_ON);
14762306a36Sopenharmony_ci	mdelay(wait_ms);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	return 0;
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic const struct rk3328_reg_msk_val playback_open_list[] = {
15362306a36Sopenharmony_ci	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
15462306a36Sopenharmony_ci	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
15562306a36Sopenharmony_ci	  DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
15662306a36Sopenharmony_ci	{ DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
15762306a36Sopenharmony_ci	  HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
15862306a36Sopenharmony_ci	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
15962306a36Sopenharmony_ci	  HPOUTR_POP_WORK | HPOUTL_POP_WORK },
16062306a36Sopenharmony_ci	{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
16162306a36Sopenharmony_ci	{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
16262306a36Sopenharmony_ci	  HPMIXL_INIT_EN | HPMIXR_INIT_EN },
16362306a36Sopenharmony_ci	{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
16462306a36Sopenharmony_ci	{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
16562306a36Sopenharmony_ci	  HPOUTL_INIT_EN | HPOUTR_INIT_EN },
16662306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
16762306a36Sopenharmony_ci	  DACL_REFV_ON | DACR_REFV_ON },
16862306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
16962306a36Sopenharmony_ci	  DACL_CLK_ON | DACR_CLK_ON },
17062306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
17162306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
17262306a36Sopenharmony_ci	  DACL_INIT_ON | DACR_INIT_ON },
17362306a36Sopenharmony_ci	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
17462306a36Sopenharmony_ci	  DACL_SELECT | DACR_SELECT },
17562306a36Sopenharmony_ci	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
17662306a36Sopenharmony_ci	  HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
17762306a36Sopenharmony_ci	{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
17862306a36Sopenharmony_ci	  HPOUTL_UNMUTE | HPOUTR_UNMUTE },
17962306a36Sopenharmony_ci};
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	int i;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
18662306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_MASK,
18762306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_I);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
19062306a36Sopenharmony_ci		regmap_update_bits(rk3328->regmap,
19162306a36Sopenharmony_ci				   playback_open_list[i].reg,
19262306a36Sopenharmony_ci				   playback_open_list[i].msk,
19362306a36Sopenharmony_ci				   playback_open_list[i].val);
19462306a36Sopenharmony_ci		mdelay(1);
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	msleep(rk3328->spk_depop_time);
19862306a36Sopenharmony_ci	gpiod_set_value(rk3328->mute, 0);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
20162306a36Sopenharmony_ci			   HPOUTL_GAIN_MASK, OUT_VOLUME);
20262306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
20362306a36Sopenharmony_ci			   HPOUTR_GAIN_MASK, OUT_VOLUME);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	return 0;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic const struct rk3328_reg_msk_val playback_close_list[] = {
20962306a36Sopenharmony_ci	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
21062306a36Sopenharmony_ci	  HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
21162306a36Sopenharmony_ci	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
21262306a36Sopenharmony_ci	  DACL_UNSELECT | DACR_UNSELECT },
21362306a36Sopenharmony_ci	{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
21462306a36Sopenharmony_ci	  HPOUTL_MUTE | HPOUTR_MUTE },
21562306a36Sopenharmony_ci	{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
21662306a36Sopenharmony_ci	  HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
21762306a36Sopenharmony_ci	{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
21862306a36Sopenharmony_ci	{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
21962306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
22062306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
22162306a36Sopenharmony_ci	  DACL_CLK_OFF | DACR_CLK_OFF },
22262306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
22362306a36Sopenharmony_ci	  DACL_REFV_OFF | DACR_REFV_OFF },
22462306a36Sopenharmony_ci	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
22562306a36Sopenharmony_ci	  HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
22662306a36Sopenharmony_ci	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
22762306a36Sopenharmony_ci	  DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
22862306a36Sopenharmony_ci	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
22962306a36Sopenharmony_ci	{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
23062306a36Sopenharmony_ci	  HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
23162306a36Sopenharmony_ci	{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
23262306a36Sopenharmony_ci	  DACL_INIT_OFF | DACR_INIT_OFF },
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	size_t i;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	gpiod_set_value(rk3328->mute, 1);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
24262306a36Sopenharmony_ci			   HPOUTL_GAIN_MASK, 0);
24362306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
24462306a36Sopenharmony_ci			   HPOUTR_GAIN_MASK, 0);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
24762306a36Sopenharmony_ci		regmap_update_bits(rk3328->regmap,
24862306a36Sopenharmony_ci				   playback_close_list[i].reg,
24962306a36Sopenharmony_ci				   playback_close_list[i].msk,
25062306a36Sopenharmony_ci				   playback_close_list[i].val);
25162306a36Sopenharmony_ci		mdelay(1);
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	/* Workaround for silence when changed Fs 48 -> 44.1kHz */
25562306a36Sopenharmony_ci	rk3328_codec_reset(rk3328);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
25862306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_MASK,
25962306a36Sopenharmony_ci			   DAC_CHARGE_CURRENT_ALL_ON);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	return 0;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic int rk3328_hw_params(struct snd_pcm_substream *substream,
26562306a36Sopenharmony_ci			    struct snd_pcm_hw_params *params,
26662306a36Sopenharmony_ci			    struct snd_soc_dai *dai)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
26962306a36Sopenharmony_ci		snd_soc_component_get_drvdata(dai->component);
27062306a36Sopenharmony_ci	unsigned int val = 0;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	switch (params_format(params)) {
27362306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S16_LE:
27462306a36Sopenharmony_ci		val = DAC_VDL_16BITS;
27562306a36Sopenharmony_ci		break;
27662306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S20_3LE:
27762306a36Sopenharmony_ci		val = DAC_VDL_20BITS;
27862306a36Sopenharmony_ci		break;
27962306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S24_LE:
28062306a36Sopenharmony_ci		val = DAC_VDL_24BITS;
28162306a36Sopenharmony_ci		break;
28262306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S32_LE:
28362306a36Sopenharmony_ci		val = DAC_VDL_32BITS;
28462306a36Sopenharmony_ci		break;
28562306a36Sopenharmony_ci	default:
28662306a36Sopenharmony_ci		return -EINVAL;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	val = DAC_WL_32BITS | DAC_RST_DIS;
29162306a36Sopenharmony_ci	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
29262306a36Sopenharmony_ci			   DAC_WL_MASK | DAC_RST_MASK, val);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	return 0;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic int rk3328_pcm_startup(struct snd_pcm_substream *substream,
29862306a36Sopenharmony_ci			      struct snd_soc_dai *dai)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
30162306a36Sopenharmony_ci		snd_soc_component_get_drvdata(dai->component);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	return rk3328_codec_open_playback(rk3328);
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
30762306a36Sopenharmony_ci				struct snd_soc_dai *dai)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
31062306a36Sopenharmony_ci		snd_soc_component_get_drvdata(dai->component);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	rk3328_codec_close_playback(rk3328);
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic const struct snd_soc_dai_ops rk3328_dai_ops = {
31662306a36Sopenharmony_ci	.hw_params = rk3328_hw_params,
31762306a36Sopenharmony_ci	.set_fmt = rk3328_set_dai_fmt,
31862306a36Sopenharmony_ci	.mute_stream = rk3328_mute_stream,
31962306a36Sopenharmony_ci	.startup = rk3328_pcm_startup,
32062306a36Sopenharmony_ci	.shutdown = rk3328_pcm_shutdown,
32162306a36Sopenharmony_ci	.no_capture_mute = 1,
32262306a36Sopenharmony_ci};
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic struct snd_soc_dai_driver rk3328_dai[] = {
32562306a36Sopenharmony_ci	{
32662306a36Sopenharmony_ci		.name = "rk3328-hifi",
32762306a36Sopenharmony_ci		.id = RK3328_HIFI,
32862306a36Sopenharmony_ci		.playback = {
32962306a36Sopenharmony_ci			.stream_name = "HIFI Playback",
33062306a36Sopenharmony_ci			.channels_min = 1,
33162306a36Sopenharmony_ci			.channels_max = 2,
33262306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_8000_96000,
33362306a36Sopenharmony_ci			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
33462306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S20_3LE |
33562306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S24_LE |
33662306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S32_LE),
33762306a36Sopenharmony_ci		},
33862306a36Sopenharmony_ci		.capture = {
33962306a36Sopenharmony_ci			.stream_name = "HIFI Capture",
34062306a36Sopenharmony_ci			.channels_min = 2,
34162306a36Sopenharmony_ci			.channels_max = 8,
34262306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_8000_96000,
34362306a36Sopenharmony_ci			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
34462306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S20_3LE |
34562306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S24_LE |
34662306a36Sopenharmony_ci				    SNDRV_PCM_FMTBIT_S32_LE),
34762306a36Sopenharmony_ci		},
34862306a36Sopenharmony_ci		.ops = &rk3328_dai_ops,
34962306a36Sopenharmony_ci	},
35062306a36Sopenharmony_ci};
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cistatic int rk3328_codec_probe(struct snd_soc_component *component)
35362306a36Sopenharmony_ci{
35462306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
35562306a36Sopenharmony_ci		snd_soc_component_get_drvdata(component);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	rk3328_codec_reset(rk3328);
35862306a36Sopenharmony_ci	rk3328_codec_power_on(rk3328, 0);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return 0;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic void rk3328_codec_remove(struct snd_soc_component *component)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328 =
36662306a36Sopenharmony_ci		snd_soc_component_get_drvdata(component);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	rk3328_codec_close_playback(rk3328);
36962306a36Sopenharmony_ci	rk3328_codec_power_off(rk3328, 0);
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_rk3328 = {
37362306a36Sopenharmony_ci	.probe = rk3328_codec_probe,
37462306a36Sopenharmony_ci	.remove = rk3328_codec_remove,
37562306a36Sopenharmony_ci};
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	switch (reg) {
38062306a36Sopenharmony_ci	case CODEC_RESET:
38162306a36Sopenharmony_ci	case DAC_INIT_CTRL1:
38262306a36Sopenharmony_ci	case DAC_INIT_CTRL2:
38362306a36Sopenharmony_ci	case DAC_INIT_CTRL3:
38462306a36Sopenharmony_ci	case DAC_PRECHARGE_CTRL:
38562306a36Sopenharmony_ci	case DAC_PWR_CTRL:
38662306a36Sopenharmony_ci	case DAC_CLK_CTRL:
38762306a36Sopenharmony_ci	case HPMIX_CTRL:
38862306a36Sopenharmony_ci	case DAC_SELECT:
38962306a36Sopenharmony_ci	case HPOUT_CTRL:
39062306a36Sopenharmony_ci	case HPOUTL_GAIN_CTRL:
39162306a36Sopenharmony_ci	case HPOUTR_GAIN_CTRL:
39262306a36Sopenharmony_ci	case HPOUT_POP_CTRL:
39362306a36Sopenharmony_ci		return true;
39462306a36Sopenharmony_ci	default:
39562306a36Sopenharmony_ci		return false;
39662306a36Sopenharmony_ci	}
39762306a36Sopenharmony_ci}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_cistatic bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
40062306a36Sopenharmony_ci{
40162306a36Sopenharmony_ci	switch (reg) {
40262306a36Sopenharmony_ci	case CODEC_RESET:
40362306a36Sopenharmony_ci		return true;
40462306a36Sopenharmony_ci	default:
40562306a36Sopenharmony_ci		return false;
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic const struct regmap_config rk3328_codec_regmap_config = {
41062306a36Sopenharmony_ci	.reg_bits = 32,
41162306a36Sopenharmony_ci	.reg_stride = 4,
41262306a36Sopenharmony_ci	.val_bits = 32,
41362306a36Sopenharmony_ci	.max_register = HPOUT_POP_CTRL,
41462306a36Sopenharmony_ci	.writeable_reg = rk3328_codec_write_read_reg,
41562306a36Sopenharmony_ci	.readable_reg = rk3328_codec_write_read_reg,
41662306a36Sopenharmony_ci	.volatile_reg = rk3328_codec_volatile_reg,
41762306a36Sopenharmony_ci	.reg_defaults = rk3328_codec_reg_defaults,
41862306a36Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),
41962306a36Sopenharmony_ci	.cache_type = REGCACHE_FLAT,
42062306a36Sopenharmony_ci};
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic int rk3328_platform_probe(struct platform_device *pdev)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	struct device_node *rk3328_np = pdev->dev.of_node;
42562306a36Sopenharmony_ci	struct rk3328_codec_priv *rk3328;
42662306a36Sopenharmony_ci	struct regmap *grf;
42762306a36Sopenharmony_ci	void __iomem *base;
42862306a36Sopenharmony_ci	int ret = 0;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
43162306a36Sopenharmony_ci	if (!rk3328)
43262306a36Sopenharmony_ci		return -ENOMEM;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	grf = syscon_regmap_lookup_by_phandle(rk3328_np,
43562306a36Sopenharmony_ci					      "rockchip,grf");
43662306a36Sopenharmony_ci	if (IS_ERR(grf)) {
43762306a36Sopenharmony_ci		dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
43862306a36Sopenharmony_ci		return PTR_ERR(grf);
43962306a36Sopenharmony_ci	}
44062306a36Sopenharmony_ci	/* enable i2s_acodec_en */
44162306a36Sopenharmony_ci	regmap_write(grf, RK3328_GRF_SOC_CON2,
44262306a36Sopenharmony_ci		     (BIT(14) << 16 | BIT(14)));
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
44562306a36Sopenharmony_ci				   &rk3328->spk_depop_time);
44662306a36Sopenharmony_ci	if (ret < 0) {
44762306a36Sopenharmony_ci		dev_info(&pdev->dev, "spk_depop_time use default value.\n");
44862306a36Sopenharmony_ci		rk3328->spk_depop_time = 200;
44962306a36Sopenharmony_ci	}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
45262306a36Sopenharmony_ci	if (IS_ERR(rk3328->mute))
45362306a36Sopenharmony_ci		return PTR_ERR(rk3328->mute);
45462306a36Sopenharmony_ci	/*
45562306a36Sopenharmony_ci	 * Rock64 is the only supported platform to have widely relied on
45662306a36Sopenharmony_ci	 * this; if we do happen to come across an old DTB, just leave the
45762306a36Sopenharmony_ci	 * external mute forced off.
45862306a36Sopenharmony_ci	 */
45962306a36Sopenharmony_ci	if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) {
46062306a36Sopenharmony_ci		dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n");
46162306a36Sopenharmony_ci		regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
46562306a36Sopenharmony_ci	if (IS_ERR(rk3328->mclk))
46662306a36Sopenharmony_ci		return PTR_ERR(rk3328->mclk);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	ret = clk_prepare_enable(rk3328->mclk);
46962306a36Sopenharmony_ci	if (ret)
47062306a36Sopenharmony_ci		return ret;
47162306a36Sopenharmony_ci	clk_set_rate(rk3328->mclk, INITIAL_FREQ);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
47462306a36Sopenharmony_ci	if (IS_ERR(rk3328->pclk)) {
47562306a36Sopenharmony_ci		dev_err(&pdev->dev, "can't get acodec pclk\n");
47662306a36Sopenharmony_ci		ret = PTR_ERR(rk3328->pclk);
47762306a36Sopenharmony_ci		goto err_unprepare_mclk;
47862306a36Sopenharmony_ci	}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	ret = clk_prepare_enable(rk3328->pclk);
48162306a36Sopenharmony_ci	if (ret < 0) {
48262306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to enable acodec pclk\n");
48362306a36Sopenharmony_ci		goto err_unprepare_mclk;
48462306a36Sopenharmony_ci	}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	base = devm_platform_ioremap_resource(pdev, 0);
48762306a36Sopenharmony_ci	if (IS_ERR(base)) {
48862306a36Sopenharmony_ci		ret = PTR_ERR(base);
48962306a36Sopenharmony_ci		goto err_unprepare_pclk;
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
49362306a36Sopenharmony_ci					       &rk3328_codec_regmap_config);
49462306a36Sopenharmony_ci	if (IS_ERR(rk3328->regmap)) {
49562306a36Sopenharmony_ci		ret = PTR_ERR(rk3328->regmap);
49662306a36Sopenharmony_ci		goto err_unprepare_pclk;
49762306a36Sopenharmony_ci	}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	platform_set_drvdata(pdev, rk3328);
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
50262306a36Sopenharmony_ci					       rk3328_dai,
50362306a36Sopenharmony_ci					       ARRAY_SIZE(rk3328_dai));
50462306a36Sopenharmony_ci	if (ret)
50562306a36Sopenharmony_ci		goto err_unprepare_pclk;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	return 0;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_cierr_unprepare_pclk:
51062306a36Sopenharmony_ci	clk_disable_unprepare(rk3328->pclk);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cierr_unprepare_mclk:
51362306a36Sopenharmony_ci	clk_disable_unprepare(rk3328->mclk);
51462306a36Sopenharmony_ci	return ret;
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistatic const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {
51862306a36Sopenharmony_ci		{ .compatible = "rockchip,rk3328-codec", },
51962306a36Sopenharmony_ci		{},
52062306a36Sopenharmony_ci};
52162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic struct platform_driver rk3328_codec_driver = {
52462306a36Sopenharmony_ci	.driver = {
52562306a36Sopenharmony_ci		   .name = "rk3328-codec",
52662306a36Sopenharmony_ci		   .of_match_table = of_match_ptr(rk3328_codec_of_match),
52762306a36Sopenharmony_ci	},
52862306a36Sopenharmony_ci	.probe = rk3328_platform_probe,
52962306a36Sopenharmony_ci};
53062306a36Sopenharmony_cimodule_platform_driver(rk3328_codec_driver);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ciMODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
53362306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC rk3328 codec driver");
53462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
535