brintos

brintos / linux-shallow public Read only

0
0
Text · 16.1 KiB · 250ae37 Raw
612 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * linux/sound/soc/m8m/hi6210_i2s.c - I2S IP driver4 *5 * Copyright (C) 2015 Linaro, Ltd6 * Author: Andy Green <andy.green@linaro.org>7 *8 * This driver only deals with S2 interface (BT)9 */10 11#include <linux/init.h>12#include <linux/module.h>13#include <linux/device.h>14#include <linux/delay.h>15#include <linux/clk.h>16#include <linux/jiffies.h>17#include <linux/io.h>18#include <sound/core.h>19#include <sound/pcm.h>20#include <sound/pcm_params.h>21#include <sound/dmaengine_pcm.h>22#include <sound/initval.h>23#include <sound/soc.h>24#include <linux/interrupt.h>25#include <linux/reset.h>26#include <linux/of_address.h>27#include <linux/of_irq.h>28#include <linux/mfd/syscon.h>29#include <linux/reset-controller.h>30 31#include "hi6210-i2s.h"32 33struct hi6210_i2s {34	struct device *dev;35	struct reset_control *rc;36	struct clk *clk[8];37	int clocks;38	struct snd_soc_dai_driver dai;39	void __iomem *base;40	struct regmap *sysctrl;41	phys_addr_t base_phys;42	struct snd_dmaengine_dai_dma_data dma_data[2];43	int clk_rate;44	spinlock_t lock;45	int rate;46	int format;47	u8 bits;48	u8 channels;49	u8 id;50	u8 channel_length;51	u8 use;52	u32 master:1;53	u32 status:1;54};55 56#define SC_PERIPH_CLKEN1	0x21057#define SC_PERIPH_CLKDIS1	0x21458 59#define SC_PERIPH_CLKEN3	0x23060#define SC_PERIPH_CLKDIS3	0x23461 62#define SC_PERIPH_CLKEN12	0x27063#define SC_PERIPH_CLKDIS12	0x27464 65#define SC_PERIPH_RSTEN1	0x31066#define SC_PERIPH_RSTDIS1	0x31467#define SC_PERIPH_RSTSTAT1	0x31868 69#define SC_PERIPH_RSTEN2	0x32070#define SC_PERIPH_RSTDIS2	0x32471#define SC_PERIPH_RSTSTAT2	0x32872 73#define SOC_PMCTRL_BBPPLLALIAS	0x4874 75enum {76	CLK_DACODEC,77	CLK_I2S_BASE,78};79 80static inline void hi6210_write_reg(struct hi6210_i2s *i2s, int reg, u32 val)81{82	writel(val, i2s->base + reg);83}84 85static inline u32 hi6210_read_reg(struct hi6210_i2s *i2s, int reg)86{87	return readl(i2s->base + reg);88}89 90static int hi6210_i2s_startup(struct snd_pcm_substream *substream,91			      struct snd_soc_dai *cpu_dai)92{93	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);94	int ret, n;95	u32 val;96 97	/* deassert reset on ABB */98	regmap_read(i2s->sysctrl, SC_PERIPH_RSTSTAT2, &val);99	if (val & BIT(4))100		regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS2, BIT(4));101 102	for (n = 0; n < i2s->clocks; n++) {103		ret = clk_prepare_enable(i2s->clk[n]);104		if (ret)105			goto err_unprepare_clk;106	}107 108	ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000);109	if (ret) {110		dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n",111			__func__, ret);112		goto err_unprepare_clk;113	}114 115	/* enable clock before frequency division */116	regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN12, BIT(9));117 118	/* enable codec working clock / == "codec bus clock" */119	regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN1, BIT(5));120 121	/* deassert reset on codec / interface clock / working clock */122	regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5));123	regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS1, BIT(5));124 125	/* not interested in i2s irqs */126	val = hi6210_read_reg(i2s, HII2S_CODEC_IRQ_MASK);127	val |= 0x3f;128	hi6210_write_reg(i2s, HII2S_CODEC_IRQ_MASK, val);129 130 131	/* reset the stereo downlink fifo */132	val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1);133	val |= (BIT(5) | BIT(4));134	hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val);135 136	val = hi6210_read_reg(i2s, HII2S_APB_AFIFO_CFG_1);137	val &= ~(BIT(5) | BIT(4));138	hi6210_write_reg(i2s, HII2S_APB_AFIFO_CFG_1, val);139 140 141	val = hi6210_read_reg(i2s, HII2S_SW_RST_N);142	val &= ~(HII2S_SW_RST_N__ST_DL_WORDLEN_MASK <<143			HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT);144	val |= (HII2S_BITS_16 << HII2S_SW_RST_N__ST_DL_WORDLEN_SHIFT);145	hi6210_write_reg(i2s, HII2S_SW_RST_N, val);146 147	val = hi6210_read_reg(i2s, HII2S_MISC_CFG);148	/* mux 11/12 = APB not i2s */149	val &= ~HII2S_MISC_CFG__ST_DL_TEST_SEL;150	/* BT R ch  0 = mixer op of DACR ch */151	val &= ~HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL;152	val &= ~HII2S_MISC_CFG__S2_DOUT_TEST_SEL;153 154	val |= HII2S_MISC_CFG__S2_DOUT_RIGHT_SEL;155	/* BT L ch = 1 = mux 7 = "mixer output of DACL */156	val |= HII2S_MISC_CFG__S2_DOUT_TEST_SEL;157	hi6210_write_reg(i2s, HII2S_MISC_CFG, val);158 159	val = hi6210_read_reg(i2s, HII2S_SW_RST_N);160	val |= HII2S_SW_RST_N__SW_RST_N;161	hi6210_write_reg(i2s, HII2S_SW_RST_N, val);162 163	return 0;164 165err_unprepare_clk:166	while (n--)167		clk_disable_unprepare(i2s->clk[n]);168	return ret;169}170 171static void hi6210_i2s_shutdown(struct snd_pcm_substream *substream,172				struct snd_soc_dai *cpu_dai)173{174	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);175	int n;176 177	for (n = 0; n < i2s->clocks; n++)178		clk_disable_unprepare(i2s->clk[n]);179 180	regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5));181}182 183static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on)184{185	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);186	u32 val;187 188	spin_lock(&i2s->lock);189	if (on) {190		/* enable S2 TX */191		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);192		val |= HII2S_I2S_CFG__S2_IF_TX_EN;193		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);194	} else {195		/* disable S2 TX */196		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);197		val &= ~HII2S_I2S_CFG__S2_IF_TX_EN;198		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);199	}200	spin_unlock(&i2s->lock);201}202 203static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on)204{205	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);206	u32 val;207 208	spin_lock(&i2s->lock);209	if (on) {210		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);211		val |= HII2S_I2S_CFG__S2_IF_RX_EN;212		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);213	} else {214		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);215		val &= ~HII2S_I2S_CFG__S2_IF_RX_EN;216		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);217	}218	spin_unlock(&i2s->lock);219}220 221static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)222{223	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);224 225	/*226	 * We don't actually set the hardware until the hw_params227	 * call, but we need to validate the user input here.228	 */229	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {230	case SND_SOC_DAIFMT_BC_FC:231	case SND_SOC_DAIFMT_BP_FP:232		break;233	default:234		return -EINVAL;235	}236 237	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {238	case SND_SOC_DAIFMT_I2S:239	case SND_SOC_DAIFMT_LEFT_J:240	case SND_SOC_DAIFMT_RIGHT_J:241		break;242	default:243		return -EINVAL;244	}245 246	i2s->format = fmt;247	i2s->master = (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) ==248		      SND_SOC_DAIFMT_BP_FP;249 250	return 0;251}252 253static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream,254			    struct snd_pcm_hw_params *params,255			    struct snd_soc_dai *cpu_dai)256{257	struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);258	u32 bits = 0, rate = 0, signed_data = 0, fmt = 0;259	u32 val;260	struct snd_dmaengine_dai_dma_data *dma_data;261 262	switch (params_format(params)) {263	case SNDRV_PCM_FORMAT_U16_LE:264		signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;265		fallthrough;266	case SNDRV_PCM_FORMAT_S16_LE:267		bits = HII2S_BITS_16;268		break;269	case SNDRV_PCM_FORMAT_U24_LE:270		signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;271		fallthrough;272	case SNDRV_PCM_FORMAT_S24_LE:273		bits = HII2S_BITS_24;274		break;275	default:276		dev_err(cpu_dai->dev, "Bad format\n");277		return -EINVAL;278	}279 280 281	switch (params_rate(params)) {282	case 8000:283		rate = HII2S_FS_RATE_8KHZ;284		break;285	case 16000:286		rate = HII2S_FS_RATE_16KHZ;287		break;288	case 32000:289		rate = HII2S_FS_RATE_32KHZ;290		break;291	case 48000:292		rate = HII2S_FS_RATE_48KHZ;293		break;294	case 96000:295		rate = HII2S_FS_RATE_96KHZ;296		break;297	case 192000:298		rate = HII2S_FS_RATE_192KHZ;299		break;300	default:301		dev_err(cpu_dai->dev, "Bad rate: %d\n", params_rate(params));302		return -EINVAL;303	}304 305	if (!(params_channels(params))) {306		dev_err(cpu_dai->dev, "Bad channels\n");307		return -EINVAL;308	}309 310	dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);311 312	switch (bits) {313	case HII2S_BITS_24:314		i2s->bits = 32;315		dma_data->addr_width = 3;316		break;317	default:318		i2s->bits = 16;319		dma_data->addr_width = 2;320		break;321	}322	i2s->rate = params_rate(params);323	i2s->channels = params_channels(params);324	i2s->channel_length = i2s->channels * i2s->bits;325 326	val = hi6210_read_reg(i2s, HII2S_ST_DL_FIFO_TH_CFG);327	val &= ~((HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_MASK <<328			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT) |329		(HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_MASK <<330			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT) |331		(HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_MASK <<332			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT) |333		(HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_MASK <<334			HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT));335	val |= ((16 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AEMPTY_SHIFT) |336		(30 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_R_AFULL_SHIFT) |337		(16 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AEMPTY_SHIFT) |338		(30 << HII2S_ST_DL_FIFO_TH_CFG__ST_DL_L_AFULL_SHIFT));339	hi6210_write_reg(i2s, HII2S_ST_DL_FIFO_TH_CFG, val);340 341 342	val = hi6210_read_reg(i2s, HII2S_IF_CLK_EN_CFG);343	val |= (BIT(19) | BIT(18) | BIT(17) |344		HII2S_IF_CLK_EN_CFG__S2_IF_CLK_EN |345		HII2S_IF_CLK_EN_CFG__S2_OL_MIXER_EN |346		HII2S_IF_CLK_EN_CFG__S2_OL_SRC_EN |347		HII2S_IF_CLK_EN_CFG__ST_DL_R_EN |348		HII2S_IF_CLK_EN_CFG__ST_DL_L_EN);349	hi6210_write_reg(i2s, HII2S_IF_CLK_EN_CFG, val);350 351 352	val = hi6210_read_reg(i2s, HII2S_DIG_FILTER_CLK_EN_CFG);353	val &= ~(HII2S_DIG_FILTER_CLK_EN_CFG__DACR_SDM_EN |354		 HII2S_DIG_FILTER_CLK_EN_CFG__DACR_HBF2I_EN |355		 HII2S_DIG_FILTER_CLK_EN_CFG__DACR_AGC_EN |356		 HII2S_DIG_FILTER_CLK_EN_CFG__DACL_SDM_EN |357		 HII2S_DIG_FILTER_CLK_EN_CFG__DACL_HBF2I_EN |358		 HII2S_DIG_FILTER_CLK_EN_CFG__DACL_AGC_EN);359	val |= (HII2S_DIG_FILTER_CLK_EN_CFG__DACR_MIXER_EN |360		HII2S_DIG_FILTER_CLK_EN_CFG__DACL_MIXER_EN);361	hi6210_write_reg(i2s, HII2S_DIG_FILTER_CLK_EN_CFG, val);362 363 364	val = hi6210_read_reg(i2s, HII2S_DIG_FILTER_MODULE_CFG);365	val &= ~(HII2S_DIG_FILTER_MODULE_CFG__DACR_MIXER_IN2_MUTE |366		 HII2S_DIG_FILTER_MODULE_CFG__DACL_MIXER_IN2_MUTE);367	hi6210_write_reg(i2s, HII2S_DIG_FILTER_MODULE_CFG, val);368 369	val = hi6210_read_reg(i2s, HII2S_MUX_TOP_MODULE_CFG);370	val &= ~(HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN1_MUTE |371		 HII2S_MUX_TOP_MODULE_CFG__S2_OL_MIXER_IN2_MUTE |372		 HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN1_MUTE |373		 HII2S_MUX_TOP_MODULE_CFG__VOICE_DLINK_MIXER_IN2_MUTE);374	hi6210_write_reg(i2s, HII2S_MUX_TOP_MODULE_CFG, val);375 376 377	switch (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {378	case SND_SOC_DAIFMT_BC_FC:379		i2s->master = false;380		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);381		val |= HII2S_I2S_CFG__S2_MST_SLV;382		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);383		break;384	case SND_SOC_DAIFMT_BP_FP:385		i2s->master = true;386		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);387		val &= ~HII2S_I2S_CFG__S2_MST_SLV;388		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);389		break;390	default:391		WARN_ONCE(1, "Invalid i2s->fmt CLOCK_PROVIDER_MASK. This shouldn't happen\n");392		return -EINVAL;393	}394 395	switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) {396	case SND_SOC_DAIFMT_I2S:397		fmt = HII2S_FORMAT_I2S;398		break;399	case SND_SOC_DAIFMT_LEFT_J:400		fmt = HII2S_FORMAT_LEFT_JUST;401		break;402	case SND_SOC_DAIFMT_RIGHT_J:403		fmt = HII2S_FORMAT_RIGHT_JUST;404		break;405	default:406		WARN_ONCE(1, "Invalid i2s->fmt FORMAT_MASK. This shouldn't happen\n");407		return -EINVAL;408	}409 410	val = hi6210_read_reg(i2s, HII2S_I2S_CFG);411	val &= ~(HII2S_I2S_CFG__S2_FUNC_MODE_MASK <<412			HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT);413	val |= fmt << HII2S_I2S_CFG__S2_FUNC_MODE_SHIFT;414	hi6210_write_reg(i2s, HII2S_I2S_CFG, val);415 416 417	val = hi6210_read_reg(i2s, HII2S_CLK_SEL);418	val &= ~(HII2S_CLK_SEL__I2S_BT_FM_SEL | /* BT gets the I2S */419			HII2S_CLK_SEL__EXT_12_288MHZ_SEL);420	hi6210_write_reg(i2s, HII2S_CLK_SEL, val);421 422	dma_data->maxburst = 2;423 424	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)425		dma_data->addr = i2s->base_phys + HII2S_ST_DL_CHANNEL;426	else427		dma_data->addr = i2s->base_phys + HII2S_STEREO_UPLINK_CHANNEL;428 429	switch (i2s->channels) {430	case 1:431		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);432		val |= HII2S_I2S_CFG__S2_FRAME_MODE;433		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);434		break;435	default:436		val = hi6210_read_reg(i2s, HII2S_I2S_CFG);437		val &= ~HII2S_I2S_CFG__S2_FRAME_MODE;438		hi6210_write_reg(i2s, HII2S_I2S_CFG, val);439		break;440	}441 442	/* clear loopback, set signed type and word length */443	val = hi6210_read_reg(i2s, HII2S_I2S_CFG);444	val &= ~HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT;445	val &= ~(HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_MASK <<446			HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT);447	val &= ~(HII2S_I2S_CFG__S2_DIRECT_LOOP_MASK <<448			HII2S_I2S_CFG__S2_DIRECT_LOOP_SHIFT);449	val |= signed_data;450	val |= (bits << HII2S_I2S_CFG__S2_CODEC_IO_WORDLENGTH_SHIFT);451	hi6210_write_reg(i2s, HII2S_I2S_CFG, val);452 453 454	if (!i2s->master)455		return 0;456 457	/* set DAC and related units to correct rate */458	val = hi6210_read_reg(i2s, HII2S_FS_CFG);459	val &= ~(HII2S_FS_CFG__FS_S2_MASK << HII2S_FS_CFG__FS_S2_SHIFT);460	val &= ~(HII2S_FS_CFG__FS_DACLR_MASK << HII2S_FS_CFG__FS_DACLR_SHIFT);461	val &= ~(HII2S_FS_CFG__FS_ST_DL_R_MASK <<462					HII2S_FS_CFG__FS_ST_DL_R_SHIFT);463	val &= ~(HII2S_FS_CFG__FS_ST_DL_L_MASK <<464					HII2S_FS_CFG__FS_ST_DL_L_SHIFT);465	val |= (rate << HII2S_FS_CFG__FS_S2_SHIFT);466	val |= (rate << HII2S_FS_CFG__FS_DACLR_SHIFT);467	val |= (rate << HII2S_FS_CFG__FS_ST_DL_R_SHIFT);468	val |= (rate << HII2S_FS_CFG__FS_ST_DL_L_SHIFT);469	hi6210_write_reg(i2s, HII2S_FS_CFG, val);470 471	return 0;472}473 474static int hi6210_i2s_trigger(struct snd_pcm_substream *substream, int cmd,475			  struct snd_soc_dai *cpu_dai)476{477	pr_debug("%s\n", __func__);478	switch (cmd) {479	case SNDRV_PCM_TRIGGER_START:480	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:481		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)482			hi6210_i2s_rxctrl(cpu_dai, 1);483		else484			hi6210_i2s_txctrl(cpu_dai, 1);485		break;486	case SNDRV_PCM_TRIGGER_STOP:487	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:488		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)489			hi6210_i2s_rxctrl(cpu_dai, 0);490		else491			hi6210_i2s_txctrl(cpu_dai, 0);492		break;493	default:494		dev_err(cpu_dai->dev, "unknown cmd\n");495		return -EINVAL;496	}497	return 0;498}499 500static int hi6210_i2s_dai_probe(struct snd_soc_dai *dai)501{502	struct hi6210_i2s *i2s = snd_soc_dai_get_drvdata(dai);503 504	snd_soc_dai_init_dma_data(dai,505				  &i2s->dma_data[SNDRV_PCM_STREAM_PLAYBACK],506				  &i2s->dma_data[SNDRV_PCM_STREAM_CAPTURE]);507 508	return 0;509}510 511 512static const struct snd_soc_dai_ops hi6210_i2s_dai_ops = {513	.probe		= hi6210_i2s_dai_probe,514	.trigger	= hi6210_i2s_trigger,515	.hw_params	= hi6210_i2s_hw_params,516	.set_fmt	= hi6210_i2s_set_fmt,517	.startup	= hi6210_i2s_startup,518	.shutdown	= hi6210_i2s_shutdown,519};520 521static const struct snd_soc_dai_driver hi6210_i2s_dai_init = {522	.playback = {523		.channels_min = 2,524		.channels_max = 2,525		.formats = SNDRV_PCM_FMTBIT_S16_LE |526			   SNDRV_PCM_FMTBIT_U16_LE,527		.rates = SNDRV_PCM_RATE_48000,528	},529	.capture = {530		.channels_min = 2,531		.channels_max = 2,532		.formats = SNDRV_PCM_FMTBIT_S16_LE |533			   SNDRV_PCM_FMTBIT_U16_LE,534		.rates = SNDRV_PCM_RATE_48000,535	},536	.ops = &hi6210_i2s_dai_ops,537};538 539static const struct snd_soc_component_driver hi6210_i2s_i2s_comp = {540	.name = "hi6210_i2s-i2s",541	.legacy_dai_naming = 1,542};543 544static int hi6210_i2s_probe(struct platform_device *pdev)545{546	struct device_node *node = pdev->dev.of_node;547	struct device *dev = &pdev->dev;548	struct hi6210_i2s *i2s;549	struct resource *res;550	int ret;551 552	i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);553	if (!i2s)554		return -ENOMEM;555 556	i2s->dev = dev;557	spin_lock_init(&i2s->lock);558 559	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);560	if (IS_ERR(i2s->base))561		return PTR_ERR(i2s->base);562 563	i2s->base_phys = (phys_addr_t)res->start;564	i2s->dai = hi6210_i2s_dai_init;565 566	dev_set_drvdata(dev, i2s);567 568	i2s->sysctrl = syscon_regmap_lookup_by_phandle(node,569						"hisilicon,sysctrl-syscon");570	if (IS_ERR(i2s->sysctrl))571		return PTR_ERR(i2s->sysctrl);572 573	i2s->clk[CLK_DACODEC] = devm_clk_get(dev, "dacodec");574	if (IS_ERR(i2s->clk[CLK_DACODEC]))575		return PTR_ERR(i2s->clk[CLK_DACODEC]);576	i2s->clocks++;577 578	i2s->clk[CLK_I2S_BASE] = devm_clk_get(dev, "i2s-base");579	if (IS_ERR(i2s->clk[CLK_I2S_BASE]))580		return PTR_ERR(i2s->clk[CLK_I2S_BASE]);581	i2s->clocks++;582 583	ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0);584	if (ret)585		return ret;586 587	ret = devm_snd_soc_register_component(dev, &hi6210_i2s_i2s_comp,588					 &i2s->dai, 1);589	return ret;590}591 592static const struct of_device_id hi6210_i2s_dt_ids[] = {593	{ .compatible = "hisilicon,hi6210-i2s" },594	{ /* sentinel */ }595};596 597MODULE_DEVICE_TABLE(of, hi6210_i2s_dt_ids);598 599static struct platform_driver hi6210_i2s_driver = {600	.probe = hi6210_i2s_probe,601	.driver = {602		.name = "hi6210_i2s",603		.of_match_table = hi6210_i2s_dt_ids,604	},605};606 607module_platform_driver(hi6210_i2s_driver);608 609MODULE_DESCRIPTION("Hisilicon HI6210 I2S driver");610MODULE_AUTHOR("Andy Green <andy.green@linaro.org>");611MODULE_LICENSE("GPL");612