aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.txt37
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/codecs/rl6231.c19
-rw-r--r--sound/soc/codecs/rt286.c74
-rw-r--r--sound/soc/codecs/rt5640.c10
-rw-r--r--sound/soc/codecs/rt5645.c10
-rw-r--r--sound/soc/rockchip/Kconfig12
-rw-r--r--sound/soc/rockchip/Makefile4
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c529
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h223
11 files changed, 847 insertions, 73 deletions
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
new file mode 100644
index 000000000000..6c55fcfe5e1d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -0,0 +1,37 @@
1* Rockchip I2S controller
2
3The I2S bus (Inter-IC sound bus) is a serial link for digital
4audio data transfer between devices in the system.
5
6Required properties:
7
8- compatible: should be one of the followings
9 - "rockchip,rk3066-i2s": for rk3066
10 - "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
11 - "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
12- reg: physical base address of the controller and length of memory mapped
13 region.
14- interrupts: should contain the I2S interrupt.
15- #address-cells: should be 1.
16- #size-cells: should be 0.
17- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
18 Documentation/devicetree/bindings/dma/dma.txt
19- dma-names: should include "tx" and "rx".
20- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
21- clock-names: should contain followings:
22 - "i2s_hclk": clock for I2S BUS
23 - "i2s_clk" : clock for I2S controller
24
25Example for rk3288 I2S controller:
26
27i2s@ff890000 {
28 compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
29 reg = <0xff890000 0x10000>;
30 interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
31 #address-cells = <1>;
32 #size-cells = <0>;
33 dmas = <&pdma1 0>, <&pdma1 1>;
34 dma-names = "rx", "tx";
35 clock-names = "i2s_hclk", "i2s_clk";
36 clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
37};
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 0060b31cc3f3..0e9623368ab0 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig"
47source "sound/soc/intel/Kconfig" 47source "sound/soc/intel/Kconfig"
48source "sound/soc/mxs/Kconfig" 48source "sound/soc/mxs/Kconfig"
49source "sound/soc/pxa/Kconfig" 49source "sound/soc/pxa/Kconfig"
50source "sound/soc/rockchip/Kconfig"
50source "sound/soc/samsung/Kconfig" 51source "sound/soc/samsung/Kconfig"
51source "sound/soc/s6000/Kconfig" 52source "sound/soc/s6000/Kconfig"
52source "sound/soc/sh/Kconfig" 53source "sound/soc/sh/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 5f1df02984f8..534714a1ca44 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC) += nuc900/
24obj-$(CONFIG_SND_SOC) += omap/ 24obj-$(CONFIG_SND_SOC) += omap/
25obj-$(CONFIG_SND_SOC) += kirkwood/ 25obj-$(CONFIG_SND_SOC) += kirkwood/
26obj-$(CONFIG_SND_SOC) += pxa/ 26obj-$(CONFIG_SND_SOC) += pxa/
27obj-$(CONFIG_SND_SOC) += rockchip/
27obj-$(CONFIG_SND_SOC) += samsung/ 28obj-$(CONFIG_SND_SOC) += samsung/
28obj-$(CONFIG_SND_SOC) += s6000/ 29obj-$(CONFIG_SND_SOC) += s6000/
29obj-$(CONFIG_SND_SOC) += sh/ 30obj-$(CONFIG_SND_SOC) += sh/
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c
index 7b82fbe0d14c..56650d6c2f53 100644
--- a/sound/soc/codecs/rl6231.c
+++ b/sound/soc/codecs/rl6231.c
@@ -11,25 +11,6 @@
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/gpio.h>
19#include <linux/i2c.h>
20#include <linux/regmap.h>
21#include <linux/of.h>
22#include <linux/of_gpio.h>
23#include <linux/platform_device.h>
24#include <linux/spi/spi.h>
25#include <linux/acpi.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/soc.h>
30#include <sound/soc-dapm.h>
31#include <sound/initval.h>
32#include <sound/tlv.h>
33 14
34#include "rl6231.h" 15#include "rl6231.h"
35 16
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 218f86efd196..e4f6102efc1a 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -36,7 +36,6 @@
36 36
37struct rt286_priv { 37struct rt286_priv {
38 struct regmap *regmap; 38 struct regmap *regmap;
39 struct snd_soc_codec *codec;
40 struct rt286_platform_data pdata; 39 struct rt286_platform_data pdata;
41 struct i2c_client *i2c; 40 struct i2c_client *i2c;
42 struct snd_soc_jack *jack; 41 struct snd_soc_jack *jack;
@@ -295,9 +294,8 @@ static int rt286_support_power_controls[] = {
295}; 294};
296#define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls) 295#define RT286_POWER_REG_LEN ARRAY_SIZE(rt286_support_power_controls)
297 296
298static int rt286_jack_detect(struct snd_soc_codec *codec, bool *hp, bool *mic) 297static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic)
299{ 298{
300 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
301 unsigned int val, buf; 299 unsigned int val, buf;
302 int i; 300 int i;
303 301
@@ -305,23 +303,23 @@ static int rt286_jack_detect(struct snd_soc_codec *codec, bool *hp, bool *mic)
305 *mic = false; 303 *mic = false;
306 304
307 if (rt286->pdata.cbj_en) { 305 if (rt286->pdata.cbj_en) {
308 buf = snd_soc_read(codec, RT286_GET_HP_SENSE); 306 regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf);
309 *hp = buf & 0x80000000; 307 *hp = buf & 0x80000000;
310 if (*hp) { 308 if (*hp) {
311 /* power on HV,VERF */ 309 /* power on HV,VERF */
312 snd_soc_update_bits(codec, 310 regmap_update_bits(rt286->regmap,
313 RT286_POWER_CTRL1, 0x1001, 0x0); 311 RT286_POWER_CTRL1, 0x1001, 0x0);
314 /* power LDO1 */ 312 /* power LDO1 */
315 snd_soc_update_bits(codec, 313 regmap_update_bits(rt286->regmap,
316 RT286_POWER_CTRL2, 0x4, 0x4); 314 RT286_POWER_CTRL2, 0x4, 0x4);
317 snd_soc_write(codec, RT286_SET_MIC1, 0x24); 315 regmap_write(rt286->regmap, RT286_SET_MIC1, 0x24);
318 val = snd_soc_read(codec, RT286_CBJ_CTRL2); 316 regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val);
319 317
320 msleep(200); 318 msleep(200);
321 i = 40; 319 i = 40;
322 while (((val & 0x0800) == 0) && (i > 0)) { 320 while (((val & 0x0800) == 0) && (i > 0)) {
323 val = snd_soc_read(codec, 321 regmap_read(rt286->regmap,
324 RT286_CBJ_CTRL2); 322 RT286_CBJ_CTRL2, &val);
325 i--; 323 i--;
326 msleep(20); 324 msleep(20);
327 } 325 }
@@ -329,53 +327,53 @@ static int rt286_jack_detect(struct snd_soc_codec *codec, bool *hp, bool *mic)
329 if (0x0400 == (val & 0x0700)) { 327 if (0x0400 == (val & 0x0700)) {
330 *mic = false; 328 *mic = false;
331 329
332 snd_soc_write(codec, 330 regmap_write(rt286->regmap,
333 RT286_SET_MIC1, 0x20); 331 RT286_SET_MIC1, 0x20);
334 /* power off HV,VERF */ 332 /* power off HV,VERF */
335 snd_soc_update_bits(codec, 333 regmap_update_bits(rt286->regmap,
336 RT286_POWER_CTRL1, 0x1001, 0x1001); 334 RT286_POWER_CTRL1, 0x1001, 0x1001);
337 snd_soc_update_bits(codec, 335 regmap_update_bits(rt286->regmap,
338 RT286_A_BIAS_CTRL3, 0xc000, 0x0000); 336 RT286_A_BIAS_CTRL3, 0xc000, 0x0000);
339 snd_soc_update_bits(codec, 337 regmap_update_bits(rt286->regmap,
340 RT286_CBJ_CTRL1, 0x0030, 0x0000); 338 RT286_CBJ_CTRL1, 0x0030, 0x0000);
341 snd_soc_update_bits(codec, 339 regmap_update_bits(rt286->regmap,
342 RT286_A_BIAS_CTRL2, 0xc000, 0x0000); 340 RT286_A_BIAS_CTRL2, 0xc000, 0x0000);
343 } else if ((0x0200 == (val & 0x0700)) || 341 } else if ((0x0200 == (val & 0x0700)) ||
344 (0x0100 == (val & 0x0700))) { 342 (0x0100 == (val & 0x0700))) {
345 *mic = true; 343 *mic = true;
346 snd_soc_update_bits(codec, 344 regmap_update_bits(rt286->regmap,
347 RT286_A_BIAS_CTRL3, 0xc000, 0x8000); 345 RT286_A_BIAS_CTRL3, 0xc000, 0x8000);
348 snd_soc_update_bits(codec, 346 regmap_update_bits(rt286->regmap,
349 RT286_CBJ_CTRL1, 0x0030, 0x0020); 347 RT286_CBJ_CTRL1, 0x0030, 0x0020);
350 snd_soc_update_bits(codec, 348 regmap_update_bits(rt286->regmap,
351 RT286_A_BIAS_CTRL2, 0xc000, 0x8000); 349 RT286_A_BIAS_CTRL2, 0xc000, 0x8000);
352 } else { 350 } else {
353 *mic = false; 351 *mic = false;
354 } 352 }
355 353
356 snd_soc_update_bits(codec, 354 regmap_update_bits(rt286->regmap,
357 RT286_MISC_CTRL1, 355 RT286_MISC_CTRL1,
358 0x0060, 0x0000); 356 0x0060, 0x0000);
359 } else { 357 } else {
360 snd_soc_update_bits(codec, 358 regmap_update_bits(rt286->regmap,
361 RT286_MISC_CTRL1, 359 RT286_MISC_CTRL1,
362 0x0060, 0x0020); 360 0x0060, 0x0020);
363 snd_soc_update_bits(codec, 361 regmap_update_bits(rt286->regmap,
364 RT286_A_BIAS_CTRL3, 362 RT286_A_BIAS_CTRL3,
365 0xc000, 0x8000); 363 0xc000, 0x8000);
366 snd_soc_update_bits(codec, 364 regmap_update_bits(rt286->regmap,
367 RT286_CBJ_CTRL1, 365 RT286_CBJ_CTRL1,
368 0x0030, 0x0020); 366 0x0030, 0x0020);
369 snd_soc_update_bits(codec, 367 regmap_update_bits(rt286->regmap,
370 RT286_A_BIAS_CTRL2, 368 RT286_A_BIAS_CTRL2,
371 0xc000, 0x8000); 369 0xc000, 0x8000);
372 370
373 *mic = false; 371 *mic = false;
374 } 372 }
375 } else { 373 } else {
376 buf = snd_soc_read(codec, RT286_GET_HP_SENSE); 374 regmap_read(rt286->regmap, RT286_GET_HP_SENSE, &buf);
377 *hp = buf & 0x80000000; 375 *hp = buf & 0x80000000;
378 buf = snd_soc_read(codec, RT286_GET_MIC1_SENSE); 376 regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf);
379 *mic = buf & 0x80000000; 377 *mic = buf & 0x80000000;
380 } 378 }
381 379
@@ -390,7 +388,7 @@ static void rt286_jack_detect_work(struct work_struct *work)
390 bool hp = false; 388 bool hp = false;
391 bool mic = false; 389 bool mic = false;
392 390
393 rt286_jack_detect(rt286->codec, &hp, &mic); 391 rt286_jack_detect(rt286, &hp, &mic);
394 392
395 if (hp == true) 393 if (hp == true)
396 status |= SND_JACK_HEADPHONE; 394 status |= SND_JACK_HEADPHONE;
@@ -940,11 +938,10 @@ static irqreturn_t rt286_irq(int irq, void *data)
940 bool mic = false; 938 bool mic = false;
941 int status = 0; 939 int status = 0;
942 940
943 rt286_jack_detect(rt286->codec, &hp, &mic); 941 rt286_jack_detect(rt286, &hp, &mic);
944 942
945 /* Clear IRQ */ 943 /* Clear IRQ */
946 snd_soc_update_bits(rt286->codec, 944 regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x1, 0x1);
947 RT286_IRQ_CTRL, 0x1, 0x1);
948 945
949 if (hp == true) 946 if (hp == true)
950 status |= SND_JACK_HEADPHONE; 947 status |= SND_JACK_HEADPHONE;
@@ -965,7 +962,16 @@ static int rt286_probe(struct snd_soc_codec *codec)
965 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec); 962 struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
966 963
967 codec->dapm.bias_level = SND_SOC_BIAS_OFF; 964 codec->dapm.bias_level = SND_SOC_BIAS_OFF;
968 rt286->codec = codec; 965
966 if (rt286->i2c->irq) {
967 regmap_update_bits(rt286->regmap,
968 RT286_IRQ_CTRL, 0x2, 0x2);
969
970 INIT_DELAYED_WORK(&rt286->jack_detect_work,
971 rt286_jack_detect_work);
972 schedule_delayed_work(&rt286->jack_detect_work,
973 msecs_to_jiffies(1250));
974 }
969 975
970 return 0; 976 return 0;
971} 977}
@@ -1171,14 +1177,6 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
1171 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); 1177 regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
1172 1178
1173 if (rt286->i2c->irq) { 1179 if (rt286->i2c->irq) {
1174 regmap_update_bits(rt286->regmap,
1175 RT286_IRQ_CTRL, 0x2, 0x2);
1176
1177 INIT_DELAYED_WORK(&rt286->jack_detect_work,
1178 rt286_jack_detect_work);
1179 schedule_delayed_work(&rt286->jack_detect_work,
1180 msecs_to_jiffies(1250));
1181
1182 ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq, 1180 ret = request_threaded_irq(rt286->i2c->irq, NULL, rt286_irq,
1183 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286); 1181 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "rt286", rt286);
1184 if (ret != 0) { 1182 if (ret != 0) {
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index de80e89b5fd8..6bc6efdec550 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2215,14 +2215,8 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
2215 2215
2216 rt5640->hp_mute = 1; 2216 rt5640->hp_mute = 1;
2217 2217
2218 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, 2218 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
2219 rt5640_dai, ARRAY_SIZE(rt5640_dai)); 2219 rt5640_dai, ARRAY_SIZE(rt5640_dai));
2220 if (ret < 0)
2221 goto err;
2222
2223 return 0;
2224err:
2225 return ret;
2226} 2220}
2227 2221
2228static int rt5640_i2c_remove(struct i2c_client *i2c) 2222static int rt5640_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 02147be2b302..a7762d0a623e 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -2345,14 +2345,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
2345 2345
2346 } 2346 }
2347 2347
2348 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, 2348 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
2349 rt5645_dai, ARRAY_SIZE(rt5645_dai)); 2349 rt5645_dai, ARRAY_SIZE(rt5645_dai));
2350 if (ret < 0)
2351 goto err;
2352
2353 return 0;
2354err:
2355 return ret;
2356} 2350}
2357 2351
2358static int rt5645_i2c_remove(struct i2c_client *i2c) 2352static int rt5645_i2c_remove(struct i2c_client *i2c)
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
new file mode 100644
index 000000000000..c196a466eef6
--- /dev/null
+++ b/sound/soc/rockchip/Kconfig
@@ -0,0 +1,12 @@
1config SND_SOC_ROCKCHIP
2 tristate "ASoC support for Rockchip"
3 depends on COMPILE_TEST || ARCH_ROCKCHIP
4 select SND_SOC_GENERIC_DMAENGINE_PCM
5 select SND_ROCKCHIP_I2S
6 help
7 Say Y or M if you want to add support for codecs attached to
8 the Rockchip SoCs' Audio interfaces. You will also need to
9 select the audio interfaces to support below.
10
11config SND_ROCKCHIP_I2S
12 tristate
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
new file mode 100644
index 000000000000..1006418e1394
--- /dev/null
+++ b/sound/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
1# ROCKCHIP Platform Support
2snd-soc-i2s-objs := rockchip_i2s.o
3
4obj-$(CONFIG_SND_ROCKCHIP_I2S) += snd-soc-i2s.o
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
new file mode 100644
index 000000000000..8d8e4b59049f
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -0,0 +1,529 @@
1/* sound/soc/rockchip/rockchip_i2s.c
2 *
3 * ALSA SoC Audio Layer - Rockchip I2S Controller driver
4 *
5 * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
6 * Author: Jianqun <jay.xu@rock-chips.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/delay.h>
15#include <linux/of_gpio.h>
16#include <linux/clk.h>
17#include <linux/pm_runtime.h>
18#include <linux/regmap.h>
19#include <sound/pcm_params.h>
20#include <sound/dmaengine_pcm.h>
21
22#include "rockchip_i2s.h"
23
24#define DRV_NAME "rockchip-i2s"
25
26struct rk_i2s_dev {
27 struct device *dev;
28
29 struct clk *hclk;
30 struct clk *mclk;
31
32 struct snd_dmaengine_dai_dma_data capture_dma_data;
33 struct snd_dmaengine_dai_dma_data playback_dma_data;
34
35 struct regmap *regmap;
36
37/*
38 * Used to indicate the tx/rx status.
39 * I2S controller hopes to start the tx and rx together,
40 * also to stop them when they are both try to stop.
41*/
42 bool tx_start;
43 bool rx_start;
44};
45
46static int i2s_runtime_suspend(struct device *dev)
47{
48 struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
49
50 clk_disable_unprepare(i2s->mclk);
51
52 return 0;
53}
54
55static int i2s_runtime_resume(struct device *dev)
56{
57 struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
58 int ret;
59
60 ret = clk_prepare_enable(i2s->mclk);
61 if (ret) {
62 dev_err(i2s->dev, "clock enable failed %d\n", ret);
63 return ret;
64 }
65
66 return 0;
67}
68
69static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
70{
71 return snd_soc_dai_get_drvdata(dai);
72}
73
74static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
75{
76 unsigned int val = 0;
77 int retry = 10;
78
79 if (on) {
80 regmap_update_bits(i2s->regmap, I2S_DMACR,
81 I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
82
83 regmap_update_bits(i2s->regmap, I2S_XFER,
84 I2S_XFER_TXS_START | I2S_XFER_RXS_START,
85 I2S_XFER_TXS_START | I2S_XFER_RXS_START);
86
87 i2s->tx_start = true;
88 } else {
89 i2s->tx_start = false;
90
91 regmap_update_bits(i2s->regmap, I2S_DMACR,
92 I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
93
94 if (!i2s->rx_start) {
95 regmap_update_bits(i2s->regmap, I2S_XFER,
96 I2S_XFER_TXS_START |
97 I2S_XFER_RXS_START,
98 I2S_XFER_TXS_STOP |
99 I2S_XFER_RXS_STOP);
100
101 regmap_update_bits(i2s->regmap, I2S_CLR,
102 I2S_CLR_TXC | I2S_CLR_RXC,
103 I2S_CLR_TXC | I2S_CLR_RXC);
104
105 regmap_read(i2s->regmap, I2S_CLR, &val);
106
107 /* Should wait for clear operation to finish */
108 while (val) {
109 regmap_read(i2s->regmap, I2S_CLR, &val);
110 retry--;
111 if (!retry)
112 dev_warn(i2s->dev, "fail to clear\n");
113 }
114 }
115 }
116}
117
118static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
119{
120 unsigned int val = 0;
121 int retry = 10;
122
123 if (on) {
124 regmap_update_bits(i2s->regmap, I2S_DMACR,
125 I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
126
127 regmap_update_bits(i2s->regmap, I2S_XFER,
128 I2S_XFER_TXS_START | I2S_XFER_RXS_START,
129 I2S_XFER_TXS_START | I2S_XFER_RXS_START);
130
131 i2s->rx_start = true;
132 } else {
133 i2s->rx_start = false;
134
135 regmap_update_bits(i2s->regmap, I2S_DMACR,
136 I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
137
138 if (!i2s->tx_start) {
139 regmap_update_bits(i2s->regmap, I2S_XFER,
140 I2S_XFER_TXS_START |
141 I2S_XFER_RXS_START,
142 I2S_XFER_TXS_STOP |
143 I2S_XFER_RXS_STOP);
144
145 regmap_update_bits(i2s->regmap, I2S_CLR,
146 I2S_CLR_TXC | I2S_CLR_RXC,
147 I2S_CLR_TXC | I2S_CLR_RXC);
148
149 regmap_read(i2s->regmap, I2S_CLR, &val);
150
151 /* Should wait for clear operation to finish */
152 while (val) {
153 regmap_read(i2s->regmap, I2S_CLR, &val);
154 retry--;
155 if (!retry)
156 dev_warn(i2s->dev, "fail to clear\n");
157 }
158 }
159 }
160}
161
162static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
163 unsigned int fmt)
164{
165 struct rk_i2s_dev *i2s = to_info(cpu_dai);
166 unsigned int mask = 0, val = 0;
167
168 mask = I2S_CKR_MSS_SLAVE;
169 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
170 case SND_SOC_DAIFMT_CBS_CFS:
171 val = I2S_CKR_MSS_SLAVE;
172 break;
173 case SND_SOC_DAIFMT_CBM_CFM:
174 val = I2S_CKR_MSS_MASTER;
175 break;
176 default:
177 return -EINVAL;
178 }
179
180 regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
181
182 mask = I2S_TXCR_IBM_MASK;
183 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
184 case SND_SOC_DAIFMT_RIGHT_J:
185 val = I2S_TXCR_IBM_RSJM;
186 break;
187 case SND_SOC_DAIFMT_LEFT_J:
188 val = I2S_TXCR_IBM_LSJM;
189 break;
190 case SND_SOC_DAIFMT_I2S:
191 val = I2S_TXCR_IBM_NORMAL;
192 break;
193 default:
194 return -EINVAL;
195 }
196
197 regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
198
199 mask = I2S_RXCR_IBM_MASK;
200 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
201 case SND_SOC_DAIFMT_RIGHT_J:
202 val = I2S_RXCR_IBM_RSJM;
203 break;
204 case SND_SOC_DAIFMT_LEFT_J:
205 val = I2S_RXCR_IBM_LSJM;
206 break;
207 case SND_SOC_DAIFMT_I2S:
208 val = I2S_RXCR_IBM_NORMAL;
209 break;
210 default:
211 return -EINVAL;
212 }
213
214 regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
215
216 return 0;
217}
218
219static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
220 struct snd_pcm_hw_params *params,
221 struct snd_soc_dai *dai)
222{
223 struct rk_i2s_dev *i2s = to_info(dai);
224 unsigned int val = 0;
225
226 switch (params_format(params)) {
227 case SNDRV_PCM_FORMAT_S8:
228 val |= I2S_TXCR_VDW(8);
229 break;
230 case SNDRV_PCM_FORMAT_S16_LE:
231 val |= I2S_TXCR_VDW(16);
232 break;
233 case SNDRV_PCM_FORMAT_S20_3LE:
234 val |= I2S_TXCR_VDW(20);
235 break;
236 case SNDRV_PCM_FORMAT_S24_LE:
237 val |= I2S_TXCR_VDW(24);
238 break;
239 default:
240 return -EINVAL;
241 }
242
243 regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val);
244 regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val);
245
246 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
247 dai->playback_dma_data = &i2s->playback_dma_data;
248 regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
249 I2S_DMACR_TDL(1) | I2S_DMACR_TDE_ENABLE);
250 } else {
251 dai->capture_dma_data = &i2s->capture_dma_data;
252 regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
253 I2S_DMACR_RDL(1) | I2S_DMACR_RDE_ENABLE);
254 }
255
256 return 0;
257}
258
259static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
260 int cmd, struct snd_soc_dai *dai)
261{
262 struct rk_i2s_dev *i2s = to_info(dai);
263 int ret = 0;
264
265 switch (cmd) {
266 case SNDRV_PCM_TRIGGER_START:
267 case SNDRV_PCM_TRIGGER_RESUME:
268 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
269 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
270 rockchip_snd_rxctrl(i2s, 1);
271 else
272 rockchip_snd_txctrl(i2s, 1);
273 break;
274 case SNDRV_PCM_TRIGGER_SUSPEND:
275 case SNDRV_PCM_TRIGGER_STOP:
276 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
277 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
278 rockchip_snd_rxctrl(i2s, 0);
279 else
280 rockchip_snd_txctrl(i2s, 0);
281 break;
282 default:
283 ret = -EINVAL;
284 break;
285 }
286
287 return ret;
288}
289
290static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
291 unsigned int freq, int dir)
292{
293 struct rk_i2s_dev *i2s = to_info(cpu_dai);
294 int ret;
295
296 ret = clk_set_rate(i2s->mclk, freq);
297 if (ret)
298 dev_err(i2s->dev, "Fail to set mclk %d\n", ret);
299
300 return ret;
301}
302
303static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
304 .hw_params = rockchip_i2s_hw_params,
305 .set_sysclk = rockchip_i2s_set_sysclk,
306 .set_fmt = rockchip_i2s_set_fmt,
307 .trigger = rockchip_i2s_trigger,
308};
309
310static struct snd_soc_dai_driver rockchip_i2s_dai = {
311 .playback = {
312 .channels_min = 2,
313 .channels_max = 8,
314 .rates = SNDRV_PCM_RATE_8000_192000,
315 .formats = (SNDRV_PCM_FMTBIT_S8 |
316 SNDRV_PCM_FMTBIT_S16_LE |
317 SNDRV_PCM_FMTBIT_S20_3LE |
318 SNDRV_PCM_FMTBIT_S24_LE),
319 },
320 .capture = {
321 .channels_min = 2,
322 .channels_max = 2,
323 .rates = SNDRV_PCM_RATE_8000_192000,
324 .formats = (SNDRV_PCM_FMTBIT_S8 |
325 SNDRV_PCM_FMTBIT_S16_LE |
326 SNDRV_PCM_FMTBIT_S20_3LE |
327 SNDRV_PCM_FMTBIT_S24_LE),
328 },
329 .ops = &rockchip_i2s_dai_ops,
330};
331
332static const struct snd_soc_component_driver rockchip_i2s_component = {
333 .name = DRV_NAME,
334};
335
336static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg)
337{
338 switch (reg) {
339 case I2S_TXCR:
340 case I2S_RXCR:
341 case I2S_CKR:
342 case I2S_DMACR:
343 case I2S_INTCR:
344 case I2S_XFER:
345 case I2S_CLR:
346 case I2S_TXDR:
347 return true;
348 default:
349 return false;
350 }
351}
352
353static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)
354{
355 switch (reg) {
356 case I2S_TXCR:
357 case I2S_RXCR:
358 case I2S_CKR:
359 case I2S_DMACR:
360 case I2S_INTCR:
361 case I2S_XFER:
362 case I2S_CLR:
363 case I2S_RXDR:
364 return true;
365 default:
366 return false;
367 }
368}
369
370static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
371{
372 switch (reg) {
373 case I2S_FIFOLR:
374 case I2S_INTSR:
375 return true;
376 default:
377 return false;
378 }
379}
380
381static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
382{
383 switch (reg) {
384 case I2S_FIFOLR:
385 return true;
386 default:
387 return false;
388 }
389}
390
391static const struct regmap_config rockchip_i2s_regmap_config = {
392 .reg_bits = 32,
393 .reg_stride = 4,
394 .val_bits = 32,
395 .max_register = I2S_RXDR,
396 .writeable_reg = rockchip_i2s_wr_reg,
397 .readable_reg = rockchip_i2s_rd_reg,
398 .volatile_reg = rockchip_i2s_volatile_reg,
399 .precious_reg = rockchip_i2s_precious_reg,
400 .cache_type = REGCACHE_FLAT,
401};
402
403static int rockchip_i2s_probe(struct platform_device *pdev)
404{
405 struct rk_i2s_dev *i2s;
406 struct resource *res;
407 void __iomem *regs;
408 int ret;
409
410 i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
411 if (!i2s) {
412 dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
413 return -ENOMEM;
414 }
415
416 /* try to prepare related clocks */
417 i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
418 if (IS_ERR(i2s->hclk)) {
419 dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
420 return PTR_ERR(i2s->hclk);
421 }
422
423 i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
424 if (IS_ERR(i2s->mclk)) {
425 dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
426 return PTR_ERR(i2s->mclk);
427 }
428
429 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
430 regs = devm_ioremap_resource(&pdev->dev, res);
431 if (IS_ERR(regs))
432 return PTR_ERR(regs);
433
434 i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
435 &rockchip_i2s_regmap_config);
436 if (IS_ERR(i2s->regmap)) {
437 dev_err(&pdev->dev,
438 "Failed to initialise managed register map\n");
439 return PTR_ERR(i2s->regmap);
440 }
441
442 i2s->playback_dma_data.addr = res->start + I2S_TXDR;
443 i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
444 i2s->playback_dma_data.maxburst = 16;
445
446 i2s->capture_dma_data.addr = res->start + I2S_RXDR;
447 i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
448 i2s->capture_dma_data.maxburst = 16;
449
450 i2s->dev = &pdev->dev;
451 dev_set_drvdata(&pdev->dev, i2s);
452
453 pm_runtime_enable(&pdev->dev);
454 if (!pm_runtime_enabled(&pdev->dev)) {
455 ret = i2s_runtime_resume(&pdev->dev);
456 if (ret)
457 goto err_pm_disable;
458 }
459
460 ret = devm_snd_soc_register_component(&pdev->dev,
461 &rockchip_i2s_component,
462 &rockchip_i2s_dai, 1);
463 if (ret) {
464 dev_err(&pdev->dev, "Could not register DAI\n");
465 goto err_suspend;
466 }
467
468 ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
469 if (ret) {
470 dev_err(&pdev->dev, "Could not register PCM\n");
471 goto err_pcm_register;
472 }
473
474 return 0;
475
476err_pcm_register:
477 snd_dmaengine_pcm_unregister(&pdev->dev);
478err_suspend:
479 if (!pm_runtime_status_suspended(&pdev->dev))
480 i2s_runtime_suspend(&pdev->dev);
481err_pm_disable:
482 pm_runtime_disable(&pdev->dev);
483
484 return ret;
485}
486
487static int rockchip_i2s_remove(struct platform_device *pdev)
488{
489 struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
490
491 pm_runtime_disable(&pdev->dev);
492 if (!pm_runtime_status_suspended(&pdev->dev))
493 i2s_runtime_suspend(&pdev->dev);
494
495 clk_disable_unprepare(i2s->mclk);
496 clk_disable_unprepare(i2s->hclk);
497 snd_dmaengine_pcm_unregister(&pdev->dev);
498 snd_soc_unregister_component(&pdev->dev);
499
500 return 0;
501}
502
503static const struct of_device_id rockchip_i2s_match[] = {
504 { .compatible = "rockchip,rk3066-i2s", },
505 {},
506};
507
508static const struct dev_pm_ops rockchip_i2s_pm_ops = {
509 SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
510 NULL)
511};
512
513static struct platform_driver rockchip_i2s_driver = {
514 .probe = rockchip_i2s_probe,
515 .remove = rockchip_i2s_remove,
516 .driver = {
517 .name = DRV_NAME,
518 .owner = THIS_MODULE,
519 .of_match_table = of_match_ptr(rockchip_i2s_match),
520 .pm = &rockchip_i2s_pm_ops,
521 },
522};
523module_platform_driver(rockchip_i2s_driver);
524
525MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
526MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");
527MODULE_LICENSE("GPL v2");
528MODULE_ALIAS("platform:" DRV_NAME);
529MODULE_DEVICE_TABLE(of, rockchip_i2s_match);
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h
new file mode 100644
index 000000000000..89a5d8bc6ee7
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -0,0 +1,223 @@
1/*
2 * sound/soc/rockchip/rockchip_i2s.h
3 *
4 * ALSA SoC Audio Layer - Rockchip I2S Controller driver
5 *
6 * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
7 * Author: Jianqun xu <jay.xu@rock-chips.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#ifndef _ROCKCHIP_IIS_H
15#define _ROCKCHIP_IIS_H
16
17/*
18 * TXCR
19 * transmit operation control register
20*/
21#define I2S_TXCR_RCNT_SHIFT 17
22#define I2S_TXCR_RCNT_MASK (0x3f << I2S_TXCR_RCNT_SHIFT)
23#define I2S_TXCR_CSR_SHIFT 15
24#define I2S_TXCR_CSR(x) (x << I2S_TXCR_CSR_SHIFT)
25#define I2S_TXCR_CSR_MASK (3 << I2S_TXCR_CSR_SHIFT)
26#define I2S_TXCR_HWT BIT(14)
27#define I2S_TXCR_SJM_SHIFT 12
28#define I2S_TXCR_SJM_R (0 << I2S_TXCR_SJM_SHIFT)
29#define I2S_TXCR_SJM_L (1 << I2S_TXCR_SJM_SHIFT)
30#define I2S_TXCR_FBM_SHIFT 11
31#define I2S_TXCR_FBM_MSB (0 << I2S_TXCR_FBM_SHIFT)
32#define I2S_TXCR_FBM_LSB (1 << I2S_TXCR_FBM_SHIFT)
33#define I2S_TXCR_IBM_SHIFT 9
34#define I2S_TXCR_IBM_NORMAL (0 << I2S_TXCR_IBM_SHIFT)
35#define I2S_TXCR_IBM_LSJM (1 << I2S_TXCR_IBM_SHIFT)
36#define I2S_TXCR_IBM_RSJM (2 << I2S_TXCR_IBM_SHIFT)
37#define I2S_TXCR_IBM_MASK (3 << I2S_TXCR_IBM_SHIFT)
38#define I2S_TXCR_PBM_SHIFT 7
39#define I2S_TXCR_PBM_MODE(x) (x << I2S_TXCR_PBM_SHIFT)
40#define I2S_TXCR_PBM_MASK (3 << I2S_TXCR_PBM_SHIFT)
41#define I2S_TXCR_TFS_SHIFT 5
42#define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT)
43#define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT)
44#define I2S_TXCR_VDW_SHIFT 0
45#define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT)
46#define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT)
47
48/*
49 * RXCR
50 * receive operation control register
51*/
52#define I2S_RXCR_HWT BIT(14)
53#define I2S_RXCR_SJM_SHIFT 12
54#define I2S_RXCR_SJM_R (0 << I2S_RXCR_SJM_SHIFT)
55#define I2S_RXCR_SJM_L (1 << I2S_RXCR_SJM_SHIFT)
56#define I2S_RXCR_FBM_SHIFT 11
57#define I2S_RXCR_FBM_MSB (0 << I2S_RXCR_FBM_SHIFT)
58#define I2S_RXCR_FBM_LSB (1 << I2S_RXCR_FBM_SHIFT)
59#define I2S_RXCR_IBM_SHIFT 9
60#define I2S_RXCR_IBM_NORMAL (0 << I2S_RXCR_IBM_SHIFT)
61#define I2S_RXCR_IBM_LSJM (1 << I2S_RXCR_IBM_SHIFT)
62#define I2S_RXCR_IBM_RSJM (2 << I2S_RXCR_IBM_SHIFT)
63#define I2S_RXCR_IBM_MASK (3 << I2S_RXCR_IBM_SHIFT)
64#define I2S_RXCR_PBM_SHIFT 7
65#define I2S_RXCR_PBM_MODE(x) (x << I2S_RXCR_PBM_SHIFT)
66#define I2S_RXCR_PBM_MASK (3 << I2S_RXCR_PBM_SHIFT)
67#define I2S_RXCR_TFS_SHIFT 5
68#define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT)
69#define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT)
70#define I2S_RXCR_VDW_SHIFT 0
71#define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT)
72#define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT)
73
74/*
75 * CKR
76 * clock generation register
77*/
78#define I2S_CKR_MSS_SHIFT 27
79#define I2S_CKR_MSS_MASTER (0 << I2S_CKR_MSS_SHIFT)
80#define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT)
81#define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT)
82#define I2S_CKR_CKP_SHIFT 26
83#define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT)
84#define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT)
85#define I2S_CKR_RLP_SHIFT 25
86#define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT)
87#define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT)
88#define I2S_CKR_TLP_SHIFT 24
89#define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT)
90#define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT)
91#define I2S_CKR_MDIV_SHIFT 16
92#define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT)
93#define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT)
94#define I2S_CKR_RSD_SHIFT 8
95#define I2S_CKR_RSD(x) ((x - 1) << I2S_CKR_RSD_SHIFT)
96#define I2S_CKR_RSD_MASK (0xff << I2S_CKR_RSD_SHIFT)
97#define I2S_CKR_TSD_SHIFT 0
98#define I2S_CKR_TSD(x) ((x - 1) << I2S_CKR_TSD_SHIFT)
99#define I2S_CKR_TSD_MASK (0xff << I2S_CKR_TSD_SHIFT)
100
101/*
102 * FIFOLR
103 * FIFO level register
104*/
105#define I2S_FIFOLR_RFL_SHIFT 24
106#define I2S_FIFOLR_RFL_MASK (0x3f << I2S_FIFOLR_RFL_SHIFT)
107#define I2S_FIFOLR_TFL3_SHIFT 18
108#define I2S_FIFOLR_TFL3_MASK (0x3f << I2S_FIFOLR_TFL3_SHIFT)
109#define I2S_FIFOLR_TFL2_SHIFT 12
110#define I2S_FIFOLR_TFL2_MASK (0x3f << I2S_FIFOLR_TFL2_SHIFT)
111#define I2S_FIFOLR_TFL1_SHIFT 6
112#define I2S_FIFOLR_TFL1_MASK (0x3f << I2S_FIFOLR_TFL1_SHIFT)
113#define I2S_FIFOLR_TFL0_SHIFT 0
114#define I2S_FIFOLR_TFL0_MASK (0x3f << I2S_FIFOLR_TFL0_SHIFT)
115
116/*
117 * DMACR
118 * DMA control register
119*/
120#define I2S_DMACR_RDE_SHIFT 24
121#define I2S_DMACR_RDE_DISABLE (0 << I2S_DMACR_RDE_SHIFT)
122#define I2S_DMACR_RDE_ENABLE (1 << I2S_DMACR_RDE_SHIFT)
123#define I2S_DMACR_RDL_SHIFT 16
124#define I2S_DMACR_RDL(x) ((x - 1) << I2S_DMACR_RDL_SHIFT)
125#define I2S_DMACR_RDL_MASK (0x1f << I2S_DMACR_RDL_SHIFT)
126#define I2S_DMACR_TDE_SHIFT 8
127#define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT)
128#define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT)
129#define I2S_DMACR_TDL_SHIFT 0
130#define I2S_DMACR_TDL(x) ((x - 1) << I2S_DMACR_TDL_SHIFT)
131#define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT)
132
133/*
134 * INTCR
135 * interrupt control register
136*/
137#define I2S_INTCR_RFT_SHIFT 20
138#define I2S_INTCR_RFT(x) ((x - 1) << I2S_INTCR_RFT_SHIFT)
139#define I2S_INTCR_RXOIC BIT(18)
140#define I2S_INTCR_RXOIE_SHIFT 17
141#define I2S_INTCR_RXOIE_DISABLE (0 << I2S_INTCR_RXOIE_SHIFT)
142#define I2S_INTCR_RXOIE_ENABLE (1 << I2S_INTCR_RXOIE_SHIFT)
143#define I2S_INTCR_RXFIE_SHIFT 16
144#define I2S_INTCR_RXFIE_DISABLE (0 << I2S_INTCR_RXFIE_SHIFT)
145#define I2S_INTCR_RXFIE_ENABLE (1 << I2S_INTCR_RXFIE_SHIFT)
146#define I2S_INTCR_TFT_SHIFT 4
147#define I2S_INTCR_TFT(x) ((x - 1) << I2S_INTCR_TFT_SHIFT)
148#define I2S_INTCR_TFT_MASK (0x1f << I2S_INTCR_TFT_SHIFT)
149#define I2S_INTCR_TXUIC BIT(2)
150#define I2S_INTCR_TXUIE_SHIFT 1
151#define I2S_INTCR_TXUIE_DISABLE (0 << I2S_INTCR_TXUIE_SHIFT)
152#define I2S_INTCR_TXUIE_ENABLE (1 << I2S_INTCR_TXUIE_SHIFT)
153
154/*
155 * INTSR
156 * interrupt status register
157*/
158#define I2S_INTSR_TXEIE_SHIFT 0
159#define I2S_INTSR_TXEIE_DISABLE (0 << I2S_INTSR_TXEIE_SHIFT)
160#define I2S_INTSR_TXEIE_ENABLE (1 << I2S_INTSR_TXEIE_SHIFT)
161#define I2S_INTSR_RXOI_SHIFT 17
162#define I2S_INTSR_RXOI_INA (0 << I2S_INTSR_RXOI_SHIFT)
163#define I2S_INTSR_RXOI_ACT (1 << I2S_INTSR_RXOI_SHIFT)
164#define I2S_INTSR_RXFI_SHIFT 16
165#define I2S_INTSR_RXFI_INA (0 << I2S_INTSR_RXFI_SHIFT)
166#define I2S_INTSR_RXFI_ACT (1 << I2S_INTSR_RXFI_SHIFT)
167#define I2S_INTSR_TXUI_SHIFT 1
168#define I2S_INTSR_TXUI_INA (0 << I2S_INTSR_TXUI_SHIFT)
169#define I2S_INTSR_TXUI_ACT (1 << I2S_INTSR_TXUI_SHIFT)
170#define I2S_INTSR_TXEI_SHIFT 0
171#define I2S_INTSR_TXEI_INA (0 << I2S_INTSR_TXEI_SHIFT)
172#define I2S_INTSR_TXEI_ACT (1 << I2S_INTSR_TXEI_SHIFT)
173
174/*
175 * XFER
176 * Transfer start register
177*/
178#define I2S_XFER_RXS_SHIFT 1
179#define I2S_XFER_RXS_STOP (0 << I2S_XFER_RXS_SHIFT)
180#define I2S_XFER_RXS_START (1 << I2S_XFER_RXS_SHIFT)
181#define I2S_XFER_TXS_SHIFT 0
182#define I2S_XFER_TXS_STOP (0 << I2S_XFER_TXS_SHIFT)
183#define I2S_XFER_TXS_START (1 << I2S_XFER_TXS_SHIFT)
184
185/*
186 * CLR
187 * clear SCLK domain logic register
188*/
189#define I2S_CLR_RXC BIT(1)
190#define I2S_CLR_TXC BIT(0)
191
192/*
193 * TXDR
194 * Transimt FIFO data register, write only.
195*/
196#define I2S_TXDR_MASK (0xff)
197
198/*
199 * RXDR
200 * Receive FIFO data register, write only.
201*/
202#define I2S_RXDR_MASK (0xff)
203
204/* Clock divider id */
205enum {
206 ROCKCHIP_DIV_MCLK = 0,
207 ROCKCHIP_DIV_BCLK,
208};
209
210/* I2S REGS */
211#define I2S_TXCR (0x0000)
212#define I2S_RXCR (0x0004)
213#define I2S_CKR (0x0008)
214#define I2S_FIFOLR (0x000c)
215#define I2S_DMACR (0x0010)
216#define I2S_INTCR (0x0014)
217#define I2S_INTSR (0x0018)
218#define I2S_XFER (0x001c)
219#define I2S_CLR (0x0020)
220#define I2S_TXDR (0x0024)
221#define I2S_RXDR (0x0028)
222
223#endif /* _ROCKCHIP_IIS_H */