aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh')
-rw-r--r--sound/soc/sh/Kconfig25
-rw-r--r--sound/soc/sh/Makefile6
-rw-r--r--sound/soc/sh/dma-sh7760.c1
-rw-r--r--sound/soc/sh/fsi-ak4642.c30
-rw-r--r--sound/soc/sh/fsi-da7210.c83
-rw-r--r--sound/soc/sh/fsi.c483
-rw-r--r--sound/soc/sh/migor.c218
-rw-r--r--sound/soc/sh/siu.h193
-rw-r--r--sound/soc/sh/siu_dai.c848
-rw-r--r--sound/soc/sh/siu_pcm.c615
10 files changed, 2255 insertions, 247 deletions
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 9154b4363db3..f07f6d8b93e1 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -23,10 +23,17 @@ config SND_SOC_SH4_SSI
23config SND_SOC_SH4_FSI 23config SND_SOC_SH4_FSI
24 tristate "SH4 FSI support" 24 tristate "SH4 FSI support"
25 depends on CPU_SUBTYPE_SH7724 25 depends on CPU_SUBTYPE_SH7724
26 select SH_DMA
27 help 26 help
28 This option enables FSI sound support 27 This option enables FSI sound support
29 28
29config SND_SOC_SH4_SIU
30 tristate
31 depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
32 select DMA_ENGINE
33 select DMADEVICES
34 select SH_DMAE
35 select FW_LOADER
36
30## 37##
31## Boards 38## Boards
32## 39##
@@ -48,4 +55,20 @@ config SND_FSI_AK4642
48 This option enables generic sound support for the 55 This option enables generic sound support for the
49 FSI - AK4642 unit 56 FSI - AK4642 unit
50 57
58config SND_FSI_DA7210
59 bool "FSI-DA7210 sound support"
60 depends on SND_SOC_SH4_FSI
61 select SND_SOC_DA7210
62 help
63 This option enables generic sound support for the
64 FSI - DA7210 unit
65
66config SND_SIU_MIGOR
67 tristate "SIU sound support on Migo-R"
68 depends on SH_MIGOR
69 select SND_SOC_SH4_SIU
70 select SND_SOC_WM8978
71 help
72 This option enables sound support for the SH7722 Migo-R board
73
51endmenu 74endmenu
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index a6997872f24e..8a5a19293bda 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -6,13 +6,19 @@ obj-$(CONFIG_SND_SOC_PCM_SH7760) += snd-soc-dma-sh7760.o
6snd-soc-hac-objs := hac.o 6snd-soc-hac-objs := hac.o
7snd-soc-ssi-objs := ssi.o 7snd-soc-ssi-objs := ssi.o
8snd-soc-fsi-objs := fsi.o 8snd-soc-fsi-objs := fsi.o
9snd-soc-siu-objs := siu_pcm.o siu_dai.o
9obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o 10obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o
10obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o 11obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o
11obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o 12obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o
13obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
12 14
13## boards 15## boards
14snd-soc-sh7760-ac97-objs := sh7760-ac97.o 16snd-soc-sh7760-ac97-objs := sh7760-ac97.o
15snd-soc-fsi-ak4642-objs := fsi-ak4642.o 17snd-soc-fsi-ak4642-objs := fsi-ak4642.o
18snd-soc-fsi-da7210-objs := fsi-da7210.o
19snd-soc-migor-objs := migor.o
16 20
17obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o 21obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
18obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o 22obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o
23obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
24obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index baddb1242c71..0d8bdf07729c 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -13,6 +13,7 @@
13 */ 13 */
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/gfp.h>
16#include <linux/init.h> 17#include <linux/init.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index c7af09729c6e..5263ab18f827 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -42,42 +42,12 @@ static struct snd_soc_device fsi_snd_devdata = {
42 .codec_dev = &soc_codec_dev_ak4642, 42 .codec_dev = &soc_codec_dev_ak4642,
43}; 43};
44 44
45#define AK4642_BUS 0
46#define AK4642_ADR 0x12
47static int ak4642_add_i2c_device(void)
48{
49 struct i2c_board_info info;
50 struct i2c_adapter *adapter;
51 struct i2c_client *client;
52
53 memset(&info, 0, sizeof(struct i2c_board_info));
54 info.addr = AK4642_ADR;
55 strlcpy(info.type, "ak4642", I2C_NAME_SIZE);
56
57 adapter = i2c_get_adapter(AK4642_BUS);
58 if (!adapter) {
59 printk(KERN_DEBUG "can't get i2c adapter\n");
60 return -ENODEV;
61 }
62
63 client = i2c_new_device(adapter, &info);
64 i2c_put_adapter(adapter);
65 if (!client) {
66 printk(KERN_DEBUG "can't add i2c device\n");
67 return -ENODEV;
68 }
69
70 return 0;
71}
72
73static struct platform_device *fsi_snd_device; 45static struct platform_device *fsi_snd_device;
74 46
75static int __init fsi_ak4642_init(void) 47static int __init fsi_ak4642_init(void)
76{ 48{
77 int ret = -ENOMEM; 49 int ret = -ENOMEM;
78 50
79 ak4642_add_i2c_device();
80
81 fsi_snd_device = platform_device_alloc("soc-audio", -1); 51 fsi_snd_device = platform_device_alloc("soc-audio", -1);
82 if (!fsi_snd_device) 52 if (!fsi_snd_device)
83 goto out; 53 goto out;
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
new file mode 100644
index 000000000000..33b4d177f466
--- /dev/null
+++ b/sound/soc/sh/fsi-da7210.c
@@ -0,0 +1,83 @@
1/*
2 * fsi-da7210.c
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/interrupt.h>
14#include <linux/platform_device.h>
15#include <linux/io.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22
23#include <sound/sh_fsi.h>
24#include "../codecs/da7210.h"
25
26static int fsi_da7210_init(struct snd_soc_codec *codec)
27{
28 return snd_soc_dai_set_fmt(&da7210_dai,
29 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
30 SND_SOC_DAIFMT_CBM_CFM);
31}
32
33static struct snd_soc_dai_link fsi_da7210_dai = {
34 .name = "DA7210",
35 .stream_name = "DA7210",
36 .cpu_dai = &fsi_soc_dai[1], /* FSI B */
37 .codec_dai = &da7210_dai,
38 .init = fsi_da7210_init,
39};
40
41static struct snd_soc_card fsi_soc_card = {
42 .name = "FSI",
43 .platform = &fsi_soc_platform,
44 .dai_link = &fsi_da7210_dai,
45 .num_links = 1,
46};
47
48static struct snd_soc_device fsi_da7210_snd_devdata = {
49 .card = &fsi_soc_card,
50 .codec_dev = &soc_codec_dev_da7210,
51};
52
53static struct platform_device *fsi_da7210_snd_device;
54
55static int __init fsi_da7210_sound_init(void)
56{
57 int ret;
58
59 fsi_da7210_snd_device = platform_device_alloc("soc-audio", -1);
60 if (!fsi_da7210_snd_device)
61 return -ENOMEM;
62
63 platform_set_drvdata(fsi_da7210_snd_device, &fsi_da7210_snd_devdata);
64 fsi_da7210_snd_devdata.dev = &fsi_da7210_snd_device->dev;
65 ret = platform_device_add(fsi_da7210_snd_device);
66 if (ret)
67 platform_device_put(fsi_da7210_snd_device);
68
69 return ret;
70}
71
72static void __exit fsi_da7210_sound_exit(void)
73{
74 platform_device_unregister(fsi_da7210_snd_device);
75}
76
77module_init(fsi_da7210_sound_init);
78module_exit(fsi_da7210_sound_exit);
79
80/* Module information */
81MODULE_DESCRIPTION("ALSA SoC FSI DA2710");
82MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
83MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 44123248b630..8dc966f45c36 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -17,8 +17,9 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/clk.h> 20#include <linux/pm_runtime.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/slab.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/initval.h> 25#include <sound/initval.h>
@@ -26,8 +27,6 @@
26#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
27#include <sound/sh_fsi.h> 28#include <sound/sh_fsi.h>
28#include <asm/atomic.h> 29#include <asm/atomic.h>
29#include <asm/dma.h>
30#include <asm/dma-sh.h>
31 30
32#define DO_FMT 0x0000 31#define DO_FMT 0x0000
33#define DOFF_CTL 0x0004 32#define DOFF_CTL 0x0004
@@ -69,6 +68,7 @@
69/* DOFF_ST */ 68/* DOFF_ST */
70#define ERR_OVER 0x00000010 69#define ERR_OVER 0x00000010
71#define ERR_UNDER 0x00000001 70#define ERR_UNDER 0x00000001
71#define ST_ERR (ERR_OVER | ERR_UNDER)
72 72
73/* CLK_RST */ 73/* CLK_RST */
74#define B_CLK 0x00000010 74#define B_CLK 0x00000010
@@ -94,10 +94,10 @@
94struct fsi_priv { 94struct fsi_priv {
95 void __iomem *base; 95 void __iomem *base;
96 struct snd_pcm_substream *substream; 96 struct snd_pcm_substream *substream;
97 struct fsi_master *master;
97 98
98 int fifo_max; 99 int fifo_max;
99 int chan; 100 int chan;
100 int dma_chan;
101 101
102 int byte_offset; 102 int byte_offset;
103 int period_len; 103 int period_len;
@@ -108,14 +108,12 @@ struct fsi_priv {
108struct fsi_master { 108struct fsi_master {
109 void __iomem *base; 109 void __iomem *base;
110 int irq; 110 int irq;
111 struct clk *clk;
112 struct fsi_priv fsia; 111 struct fsi_priv fsia;
113 struct fsi_priv fsib; 112 struct fsi_priv fsib;
114 struct sh_fsi_platform_info *info; 113 struct sh_fsi_platform_info *info;
114 spinlock_t lock;
115}; 115};
116 116
117static struct fsi_master *master;
118
119/************************************************************************ 117/************************************************************************
120 118
121 119
@@ -123,35 +121,35 @@ static struct fsi_master *master;
123 121
124 122
125************************************************************************/ 123************************************************************************/
126static int __fsi_reg_write(u32 reg, u32 data) 124static void __fsi_reg_write(u32 reg, u32 data)
127{ 125{
128 /* valid data area is 24bit */ 126 /* valid data area is 24bit */
129 data &= 0x00ffffff; 127 data &= 0x00ffffff;
130 128
131 return ctrl_outl(data, reg); 129 __raw_writel(data, reg);
132} 130}
133 131
134static u32 __fsi_reg_read(u32 reg) 132static u32 __fsi_reg_read(u32 reg)
135{ 133{
136 return ctrl_inl(reg); 134 return __raw_readl(reg);
137} 135}
138 136
139static int __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) 137static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
140{ 138{
141 u32 val = __fsi_reg_read(reg); 139 u32 val = __fsi_reg_read(reg);
142 140
143 val &= ~mask; 141 val &= ~mask;
144 val |= data & mask; 142 val |= data & mask;
145 143
146 return __fsi_reg_write(reg, val); 144 __fsi_reg_write(reg, val);
147} 145}
148 146
149static int fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) 147static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data)
150{ 148{
151 if (reg > REG_END) 149 if (reg > REG_END)
152 return -1; 150 return;
153 151
154 return __fsi_reg_write((u32)(fsi->base + reg), data); 152 __fsi_reg_write((u32)(fsi->base + reg), data);
155} 153}
156 154
157static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) 155static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg)
@@ -162,39 +160,55 @@ static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg)
162 return __fsi_reg_read((u32)(fsi->base + reg)); 160 return __fsi_reg_read((u32)(fsi->base + reg));
163} 161}
164 162
165static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) 163static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data)
166{ 164{
167 if (reg > REG_END) 165 if (reg > REG_END)
168 return -1; 166 return;
169 167
170 return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); 168 __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data);
171} 169}
172 170
173static int fsi_master_write(u32 reg, u32 data) 171static void fsi_master_write(struct fsi_master *master, u32 reg, u32 data)
174{ 172{
173 unsigned long flags;
174
175 if ((reg < MREG_START) || 175 if ((reg < MREG_START) ||
176 (reg > MREG_END)) 176 (reg > MREG_END))
177 return -1; 177 return;
178 178
179 return __fsi_reg_write((u32)(master->base + reg), data); 179 spin_lock_irqsave(&master->lock, flags);
180 __fsi_reg_write((u32)(master->base + reg), data);
181 spin_unlock_irqrestore(&master->lock, flags);
180} 182}
181 183
182static u32 fsi_master_read(u32 reg) 184static u32 fsi_master_read(struct fsi_master *master, u32 reg)
183{ 185{
186 u32 ret;
187 unsigned long flags;
188
184 if ((reg < MREG_START) || 189 if ((reg < MREG_START) ||
185 (reg > MREG_END)) 190 (reg > MREG_END))
186 return 0; 191 return 0;
187 192
188 return __fsi_reg_read((u32)(master->base + reg)); 193 spin_lock_irqsave(&master->lock, flags);
194 ret = __fsi_reg_read((u32)(master->base + reg));
195 spin_unlock_irqrestore(&master->lock, flags);
196
197 return ret;
189} 198}
190 199
191static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) 200static void fsi_master_mask_set(struct fsi_master *master,
201 u32 reg, u32 mask, u32 data)
192{ 202{
203 unsigned long flags;
204
193 if ((reg < MREG_START) || 205 if ((reg < MREG_START) ||
194 (reg > MREG_END)) 206 (reg > MREG_END))
195 return -1; 207 return;
196 208
197 return __fsi_reg_mask_set((u32)(master->base + reg), mask, data); 209 spin_lock_irqsave(&master->lock, flags);
210 __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
211 spin_unlock_irqrestore(&master->lock, flags);
198} 212}
199 213
200/************************************************************************ 214/************************************************************************
@@ -204,43 +218,35 @@ static int fsi_master_mask_set(u32 reg, u32 mask, u32 data)
204 218
205 219
206************************************************************************/ 220************************************************************************/
207static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream) 221static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
208{ 222{
209 struct snd_soc_pcm_runtime *rtd; 223 return fsi->master;
210 struct fsi_priv *fsi = NULL; 224}
211 225
212 if (!substream || !master) 226static int fsi_is_port_a(struct fsi_priv *fsi)
213 return NULL; 227{
228 return fsi->master->base == fsi->base;
229}
214 230
215 rtd = substream->private_data; 231static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
216 switch (rtd->dai->cpu_dai->id) { 232{
217 case 0: 233 struct snd_soc_pcm_runtime *rtd = substream->private_data;
218 fsi = &master->fsia; 234 struct snd_soc_dai_link *machine = rtd->dai;
219 break;
220 case 1:
221 fsi = &master->fsib;
222 break;
223 }
224 235
225 return fsi; 236 return machine->cpu_dai;
226} 237}
227 238
228static int fsi_is_port_a(struct fsi_priv *fsi) 239static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
229{ 240{
230 /* return 241 struct snd_soc_dai *dai = fsi_get_dai(substream);
231 * 1 : port a
232 * 0 : port b
233 */
234
235 if (fsi == &master->fsia)
236 return 1;
237 242
238 return 0; 243 return dai->private_data;
239} 244}
240 245
241static u32 fsi_get_info_flags(struct fsi_priv *fsi) 246static u32 fsi_get_info_flags(struct fsi_priv *fsi)
242{ 247{
243 int is_porta = fsi_is_port_a(fsi); 248 int is_porta = fsi_is_port_a(fsi);
249 struct fsi_master *master = fsi_get_master(fsi);
244 250
245 return is_porta ? master->info->porta_flags : 251 return is_porta ? master->info->porta_flags :
246 master->info->portb_flags; 252 master->info->portb_flags;
@@ -308,62 +314,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
308 return residue; 314 return residue;
309} 315}
310 316
311static int fsi_get_residue(struct fsi_priv *fsi, int is_play)
312{
313 int residue;
314 int width;
315 struct snd_pcm_runtime *runtime;
316
317 runtime = fsi->substream->runtime;
318
319 /* get 1 channel data width */
320 width = frames_to_bytes(runtime, 1) / fsi->chan;
321
322 if (2 == width)
323 residue = fsi_get_fifo_residue(fsi, is_play);
324 else
325 residue = get_dma_residue(fsi->dma_chan);
326
327 return residue;
328}
329
330/************************************************************************
331
332
333 basic dma function
334
335
336************************************************************************/
337#define PORTA_DMA 0
338#define PORTB_DMA 1
339
340static int fsi_get_dma_chan(void)
341{
342 if (0 != request_dma(PORTA_DMA, "fsia"))
343 return -EIO;
344
345 if (0 != request_dma(PORTB_DMA, "fsib")) {
346 free_dma(PORTA_DMA);
347 return -EIO;
348 }
349
350 master->fsia.dma_chan = PORTA_DMA;
351 master->fsib.dma_chan = PORTB_DMA;
352
353 return 0;
354}
355
356static void fsi_free_dma_chan(void)
357{
358 dma_wait_for_completion(PORTA_DMA);
359 dma_wait_for_completion(PORTB_DMA);
360 free_dma(PORTA_DMA);
361 free_dma(PORTB_DMA);
362
363 master->fsia.dma_chan = -1;
364 master->fsib.dma_chan = -1;
365}
366
367/************************************************************************ 317/************************************************************************
368 318
369 319
@@ -374,27 +324,30 @@ static void fsi_free_dma_chan(void)
374static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) 324static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
375{ 325{
376 u32 data = fsi_port_ab_io_bit(fsi, is_play); 326 u32 data = fsi_port_ab_io_bit(fsi, is_play);
327 struct fsi_master *master = fsi_get_master(fsi);
377 328
378 fsi_master_mask_set(IMSK, data, data); 329 fsi_master_mask_set(master, IMSK, data, data);
379 fsi_master_mask_set(IEMSK, data, data); 330 fsi_master_mask_set(master, IEMSK, data, data);
380} 331}
381 332
382static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) 333static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
383{ 334{
384 u32 data = fsi_port_ab_io_bit(fsi, is_play); 335 u32 data = fsi_port_ab_io_bit(fsi, is_play);
336 struct fsi_master *master = fsi_get_master(fsi);
385 337
386 fsi_master_mask_set(IMSK, data, 0); 338 fsi_master_mask_set(master, IMSK, data, 0);
387 fsi_master_mask_set(IEMSK, data, 0); 339 fsi_master_mask_set(master, IEMSK, data, 0);
388} 340}
389 341
390static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) 342static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
391{ 343{
392 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); 344 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
345 struct fsi_master *master = fsi_get_master(fsi);
393 346
394 if (enable) 347 if (enable)
395 fsi_master_mask_set(CLK_RST, val, val); 348 fsi_master_mask_set(master, CLK_RST, val, val);
396 else 349 else
397 fsi_master_mask_set(CLK_RST, val, 0); 350 fsi_master_mask_set(master, CLK_RST, val, 0);
398} 351}
399 352
400static void fsi_irq_init(struct fsi_priv *fsi, int is_play) 353static void fsi_irq_init(struct fsi_priv *fsi, int is_play)
@@ -415,79 +368,46 @@ static void fsi_irq_init(struct fsi_priv *fsi, int is_play)
415 fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); 368 fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR);
416 369
417 /* clear interrupt factor */ 370 /* clear interrupt factor */
418 fsi_master_mask_set(INT_ST, data, 0); 371 fsi_master_mask_set(fsi_get_master(fsi), INT_ST, data, 0);
419} 372}
420 373
421static void fsi_soft_all_reset(void) 374static void fsi_soft_all_reset(struct fsi_master *master)
422{ 375{
423 u32 status = fsi_master_read(SOFT_RST); 376 u32 status = fsi_master_read(master, SOFT_RST);
424 377
425 /* port AB reset */ 378 /* port AB reset */
426 status &= 0x000000ff; 379 status &= 0x000000ff;
427 fsi_master_write(SOFT_RST, status); 380 fsi_master_write(master, SOFT_RST, status);
428 mdelay(10); 381 mdelay(10);
429 382
430 /* soft reset */ 383 /* soft reset */
431 status &= 0x000000f0; 384 status &= 0x000000f0;
432 fsi_master_write(SOFT_RST, status); 385 fsi_master_write(master, SOFT_RST, status);
433 status |= 0x00000001; 386 status |= 0x00000001;
434 fsi_master_write(SOFT_RST, status); 387 fsi_master_write(master, SOFT_RST, status);
435 mdelay(10); 388 mdelay(10);
436} 389}
437 390
438static void fsi_16data_push(struct fsi_priv *fsi,
439 struct snd_pcm_runtime *runtime,
440 int send)
441{
442 u16 *dma_start;
443 u32 snd;
444 int i;
445
446 /* get dma start position for FSI */
447 dma_start = (u16 *)runtime->dma_area;
448 dma_start += fsi->byte_offset / 2;
449
450 /*
451 * soft dma
452 * FSI can not use DMA when 16bpp
453 */
454 for (i = 0; i < send; i++) {
455 snd = (u32)dma_start[i];
456 fsi_reg_write(fsi, DODT, snd << 8);
457 }
458}
459
460static void fsi_32data_push(struct fsi_priv *fsi,
461 struct snd_pcm_runtime *runtime,
462 int send)
463{
464 u32 *dma_start;
465
466 /* get dma start position for FSI */
467 dma_start = (u32 *)runtime->dma_area;
468 dma_start += fsi->byte_offset / 4;
469
470 dma_wait_for_completion(fsi->dma_chan);
471 dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR));
472 dma_write(fsi->dma_chan, (u32)dma_start,
473 (u32)(fsi->base + DODT), send * 4);
474}
475
476/* playback interrupt */ 391/* playback interrupt */
477static int fsi_data_push(struct fsi_priv *fsi) 392static int fsi_data_push(struct fsi_priv *fsi, int startup)
478{ 393{
479 struct snd_pcm_runtime *runtime; 394 struct snd_pcm_runtime *runtime;
480 struct snd_pcm_substream *substream = NULL; 395 struct snd_pcm_substream *substream = NULL;
396 u32 status;
481 int send; 397 int send;
482 int fifo_free; 398 int fifo_free;
483 int width; 399 int width;
400 u8 *start;
401 int i, over_period;
484 402
485 if (!fsi || 403 if (!fsi ||
486 !fsi->substream || 404 !fsi->substream ||
487 !fsi->substream->runtime) 405 !fsi->substream->runtime)
488 return -EINVAL; 406 return -EINVAL;
489 407
490 runtime = fsi->substream->runtime; 408 over_period = 0;
409 substream = fsi->substream;
410 runtime = substream->runtime;
491 411
492 /* FSI FIFO has limit. 412 /* FSI FIFO has limit.
493 * So, this driver can not send periods data at a time 413 * So, this driver can not send periods data at a time
@@ -495,7 +415,7 @@ static int fsi_data_push(struct fsi_priv *fsi)
495 if (fsi->byte_offset >= 415 if (fsi->byte_offset >=
496 fsi->period_len * (fsi->periods + 1)) { 416 fsi->period_len * (fsi->periods + 1)) {
497 417
498 substream = fsi->substream; 418 over_period = 1;
499 fsi->periods = (fsi->periods + 1) % runtime->periods; 419 fsi->periods = (fsi->periods + 1) % runtime->periods;
500 420
501 if (0 == fsi->periods) 421 if (0 == fsi->periods)
@@ -515,18 +435,122 @@ static int fsi_data_push(struct fsi_priv *fsi)
515 if (fifo_free < send) 435 if (fifo_free < send)
516 send = fifo_free; 436 send = fifo_free;
517 437
518 if (2 == width) 438 start = runtime->dma_area;
519 fsi_16data_push(fsi, runtime, send); 439 start += fsi->byte_offset;
520 else if (4 == width) 440
521 fsi_32data_push(fsi, runtime, send); 441 switch (width) {
522 else 442 case 2:
443 for (i = 0; i < send; i++)
444 fsi_reg_write(fsi, DODT,
445 ((u32)*((u16 *)start + i) << 8));
446 break;
447 case 4:
448 for (i = 0; i < send; i++)
449 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
450 break;
451 default:
523 return -EINVAL; 452 return -EINVAL;
453 }
524 454
525 fsi->byte_offset += send * width; 455 fsi->byte_offset += send * width;
526 456
457 status = fsi_reg_read(fsi, DOFF_ST);
458 if (!startup) {
459 struct snd_soc_dai *dai = fsi_get_dai(substream);
460
461 if (status & ERR_OVER)
462 dev_err(dai->dev, "over run\n");
463 if (status & ERR_UNDER)
464 dev_err(dai->dev, "under run\n");
465 }
466 fsi_reg_write(fsi, DOFF_ST, 0);
467
527 fsi_irq_enable(fsi, 1); 468 fsi_irq_enable(fsi, 1);
528 469
529 if (substream) 470 if (over_period)
471 snd_pcm_period_elapsed(substream);
472
473 return 0;
474}
475
476static int fsi_data_pop(struct fsi_priv *fsi, int startup)
477{
478 struct snd_pcm_runtime *runtime;
479 struct snd_pcm_substream *substream = NULL;
480 u32 status;
481 int free;
482 int fifo_fill;
483 int width;
484 u8 *start;
485 int i, over_period;
486
487 if (!fsi ||
488 !fsi->substream ||
489 !fsi->substream->runtime)
490 return -EINVAL;
491
492 over_period = 0;
493 substream = fsi->substream;
494 runtime = substream->runtime;
495
496 /* FSI FIFO has limit.
497 * So, this driver can not send periods data at a time
498 */
499 if (fsi->byte_offset >=
500 fsi->period_len * (fsi->periods + 1)) {
501
502 over_period = 1;
503 fsi->periods = (fsi->periods + 1) % runtime->periods;
504
505 if (0 == fsi->periods)
506 fsi->byte_offset = 0;
507 }
508
509 /* get 1 channel data width */
510 width = frames_to_bytes(runtime, 1) / fsi->chan;
511
512 /* get free space for alsa */
513 free = (fsi->buffer_len - fsi->byte_offset) / width;
514
515 /* get recv size */
516 fifo_fill = fsi_get_fifo_residue(fsi, 0);
517
518 if (free < fifo_fill)
519 fifo_fill = free;
520
521 start = runtime->dma_area;
522 start += fsi->byte_offset;
523
524 switch (width) {
525 case 2:
526 for (i = 0; i < fifo_fill; i++)
527 *((u16 *)start + i) =
528 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
529 break;
530 case 4:
531 for (i = 0; i < fifo_fill; i++)
532 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
533 break;
534 default:
535 return -EINVAL;
536 }
537
538 fsi->byte_offset += fifo_fill * width;
539
540 status = fsi_reg_read(fsi, DIFF_ST);
541 if (!startup) {
542 struct snd_soc_dai *dai = fsi_get_dai(substream);
543
544 if (status & ERR_OVER)
545 dev_err(dai->dev, "over run\n");
546 if (status & ERR_UNDER)
547 dev_err(dai->dev, "under run\n");
548 }
549 fsi_reg_write(fsi, DIFF_ST, 0);
550
551 fsi_irq_enable(fsi, 0);
552
553 if (over_period)
530 snd_pcm_period_elapsed(substream); 554 snd_pcm_period_elapsed(substream);
531 555
532 return 0; 556 return 0;
@@ -534,19 +558,24 @@ static int fsi_data_push(struct fsi_priv *fsi)
534 558
535static irqreturn_t fsi_interrupt(int irq, void *data) 559static irqreturn_t fsi_interrupt(int irq, void *data)
536{ 560{
537 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; 561 struct fsi_master *master = data;
538 u32 int_st = fsi_master_read(INT_ST); 562 u32 status = fsi_master_read(master, SOFT_RST) & ~0x00000010;
563 u32 int_st = fsi_master_read(master, INT_ST);
539 564
540 /* clear irq status */ 565 /* clear irq status */
541 fsi_master_write(SOFT_RST, status); 566 fsi_master_write(master, SOFT_RST, status);
542 fsi_master_write(SOFT_RST, status | 0x00000010); 567 fsi_master_write(master, SOFT_RST, status | 0x00000010);
543 568
544 if (int_st & INT_A_OUT) 569 if (int_st & INT_A_OUT)
545 fsi_data_push(&master->fsia); 570 fsi_data_push(&master->fsia, 0);
546 if (int_st & INT_B_OUT) 571 if (int_st & INT_B_OUT)
547 fsi_data_push(&master->fsib); 572 fsi_data_push(&master->fsib, 0);
573 if (int_st & INT_A_IN)
574 fsi_data_pop(&master->fsia, 0);
575 if (int_st & INT_B_IN)
576 fsi_data_pop(&master->fsib, 0);
548 577
549 fsi_master_write(INT_ST, 0x0000000); 578 fsi_master_write(master, INT_ST, 0x0000000);
550 579
551 return IRQ_HANDLED; 580 return IRQ_HANDLED;
552} 581}
@@ -561,7 +590,7 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
561static int fsi_dai_startup(struct snd_pcm_substream *substream, 590static int fsi_dai_startup(struct snd_pcm_substream *substream,
562 struct snd_soc_dai *dai) 591 struct snd_soc_dai *dai)
563{ 592{
564 struct fsi_priv *fsi = fsi_get(substream); 593 struct fsi_priv *fsi = fsi_get_priv(substream);
565 const char *msg; 594 const char *msg;
566 u32 flags = fsi_get_info_flags(fsi); 595 u32 flags = fsi_get_info_flags(fsi);
567 u32 fmt; 596 u32 fmt;
@@ -571,7 +600,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
571 int is_master; 600 int is_master;
572 int ret = 0; 601 int ret = 0;
573 602
574 clk_enable(master->clk); 603 pm_runtime_get_sync(dai->dev);
575 604
576 /* CKG1 */ 605 /* CKG1 */
577 data = is_play ? (1 << 0) : (1 << 4); 606 data = is_play ? (1 << 0) : (1 << 4);
@@ -664,8 +693,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
664 } 693 }
665 694
666 fsi_reg_write(fsi, reg, data); 695 fsi_reg_write(fsi, reg, data);
667 dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n",
668 msg, fsi->chan, fsi->dma_chan);
669 696
670 /* 697 /*
671 * clear clk reset if master mode 698 * clear clk reset if master mode
@@ -682,33 +709,29 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
682static void fsi_dai_shutdown(struct snd_pcm_substream *substream, 709static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
683 struct snd_soc_dai *dai) 710 struct snd_soc_dai *dai)
684{ 711{
685 struct fsi_priv *fsi = fsi_get(substream); 712 struct fsi_priv *fsi = fsi_get_priv(substream);
686 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 713 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
687 714
688 fsi_irq_disable(fsi, is_play); 715 fsi_irq_disable(fsi, is_play);
689 fsi_clk_ctrl(fsi, 0); 716 fsi_clk_ctrl(fsi, 0);
690 717
691 clk_disable(master->clk); 718 pm_runtime_put_sync(dai->dev);
692} 719}
693 720
694static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, 721static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
695 struct snd_soc_dai *dai) 722 struct snd_soc_dai *dai)
696{ 723{
697 struct fsi_priv *fsi = fsi_get(substream); 724 struct fsi_priv *fsi = fsi_get_priv(substream);
698 struct snd_pcm_runtime *runtime = substream->runtime; 725 struct snd_pcm_runtime *runtime = substream->runtime;
699 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 726 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
700 int ret = 0; 727 int ret = 0;
701 728
702 /* capture not supported */
703 if (!is_play)
704 return -ENODEV;
705
706 switch (cmd) { 729 switch (cmd) {
707 case SNDRV_PCM_TRIGGER_START: 730 case SNDRV_PCM_TRIGGER_START:
708 fsi_stream_push(fsi, substream, 731 fsi_stream_push(fsi, substream,
709 frames_to_bytes(runtime, runtime->buffer_size), 732 frames_to_bytes(runtime, runtime->buffer_size),
710 frames_to_bytes(runtime, runtime->period_size)); 733 frames_to_bytes(runtime, runtime->period_size));
711 ret = fsi_data_push(fsi); 734 ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1);
712 break; 735 break;
713 case SNDRV_PCM_TRIGGER_STOP: 736 case SNDRV_PCM_TRIGGER_STOP:
714 fsi_irq_disable(fsi, is_play); 737 fsi_irq_disable(fsi, is_play);
@@ -779,11 +802,10 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
779static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) 802static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
780{ 803{
781 struct snd_pcm_runtime *runtime = substream->runtime; 804 struct snd_pcm_runtime *runtime = substream->runtime;
782 struct fsi_priv *fsi = fsi_get(substream); 805 struct fsi_priv *fsi = fsi_get_priv(substream);
783 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
784 long location; 806 long location;
785 807
786 location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); 808 location = (fsi->byte_offset - 1);
787 if (location < 0) 809 if (location < 0)
788 location = 0; 810 location = 0;
789 811
@@ -845,7 +867,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
845 .channels_min = 1, 867 .channels_min = 1,
846 .channels_max = 8, 868 .channels_max = 8,
847 }, 869 },
848 /* capture not supported */ 870 .capture = {
871 .rates = FSI_RATES,
872 .formats = FSI_FMTS,
873 .channels_min = 1,
874 .channels_max = 8,
875 },
849 .ops = &fsi_dai_ops, 876 .ops = &fsi_dai_ops,
850 }, 877 },
851 { 878 {
@@ -857,7 +884,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
857 .channels_min = 1, 884 .channels_min = 1,
858 .channels_max = 8, 885 .channels_max = 8,
859 }, 886 },
860 /* capture not supported */ 887 .capture = {
888 .rates = FSI_RATES,
889 .formats = FSI_FMTS,
890 .channels_min = 1,
891 .channels_max = 8,
892 },
861 .ops = &fsi_dai_ops, 893 .ops = &fsi_dai_ops,
862 }, 894 },
863}; 895};
@@ -880,14 +912,19 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform);
880************************************************************************/ 912************************************************************************/
881static int fsi_probe(struct platform_device *pdev) 913static int fsi_probe(struct platform_device *pdev)
882{ 914{
915 struct fsi_master *master;
883 struct resource *res; 916 struct resource *res;
884 char clk_name[8];
885 unsigned int irq; 917 unsigned int irq;
886 int ret; 918 int ret;
887 919
920 if (0 != pdev->id) {
921 dev_err(&pdev->dev, "current fsi support id 0 only now\n");
922 return -ENODEV;
923 }
924
888 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 925 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
889 irq = platform_get_irq(pdev, 0); 926 irq = platform_get_irq(pdev, 0);
890 if (!res || !irq) { 927 if (!res || (int)irq <= 0) {
891 dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); 928 dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
892 ret = -ENODEV; 929 ret = -ENODEV;
893 goto exit; 930 goto exit;
@@ -910,35 +947,25 @@ static int fsi_probe(struct platform_device *pdev)
910 master->irq = irq; 947 master->irq = irq;
911 master->info = pdev->dev.platform_data; 948 master->info = pdev->dev.platform_data;
912 master->fsia.base = master->base; 949 master->fsia.base = master->base;
950 master->fsia.master = master;
913 master->fsib.base = master->base + 0x40; 951 master->fsib.base = master->base + 0x40;
952 master->fsib.master = master;
953 spin_lock_init(&master->lock);
914 954
915 master->fsia.dma_chan = -1; 955 pm_runtime_enable(&pdev->dev);
916 master->fsib.dma_chan = -1; 956 pm_runtime_resume(&pdev->dev);
917
918 ret = fsi_get_dma_chan();
919 if (ret < 0) {
920 dev_err(&pdev->dev, "cannot get dma api\n");
921 goto exit_iounmap;
922 }
923
924 /* FSI is based on SPU mstp */
925 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
926 master->clk = clk_get(NULL, clk_name);
927 if (IS_ERR(master->clk)) {
928 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
929 ret = -EIO;
930 goto exit_free_dma;
931 }
932 957
933 fsi_soc_dai[0].dev = &pdev->dev; 958 fsi_soc_dai[0].dev = &pdev->dev;
959 fsi_soc_dai[0].private_data = &master->fsia;
934 fsi_soc_dai[1].dev = &pdev->dev; 960 fsi_soc_dai[1].dev = &pdev->dev;
961 fsi_soc_dai[1].private_data = &master->fsib;
935 962
936 fsi_soft_all_reset(); 963 fsi_soft_all_reset(master);
937 964
938 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); 965 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
939 if (ret) { 966 if (ret) {
940 dev_err(&pdev->dev, "irq request err\n"); 967 dev_err(&pdev->dev, "irq request err\n");
941 goto exit_free_dma; 968 goto exit_iounmap;
942 } 969 }
943 970
944 ret = snd_soc_register_platform(&fsi_soc_platform); 971 ret = snd_soc_register_platform(&fsi_soc_platform);
@@ -951,10 +978,9 @@ static int fsi_probe(struct platform_device *pdev)
951 978
952exit_free_irq: 979exit_free_irq:
953 free_irq(irq, master); 980 free_irq(irq, master);
954exit_free_dma:
955 fsi_free_dma_chan();
956exit_iounmap: 981exit_iounmap:
957 iounmap(master->base); 982 iounmap(master->base);
983 pm_runtime_disable(&pdev->dev);
958exit_kfree: 984exit_kfree:
959 kfree(master); 985 kfree(master);
960 master = NULL; 986 master = NULL;
@@ -964,24 +990,49 @@ exit:
964 990
965static int fsi_remove(struct platform_device *pdev) 991static int fsi_remove(struct platform_device *pdev)
966{ 992{
993 struct fsi_master *master;
994
995 master = fsi_get_master(fsi_soc_dai[0].private_data);
996
967 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); 997 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
968 snd_soc_unregister_platform(&fsi_soc_platform); 998 snd_soc_unregister_platform(&fsi_soc_platform);
969 999
970 clk_put(master->clk); 1000 pm_runtime_disable(&pdev->dev);
971
972 fsi_free_dma_chan();
973 1001
974 free_irq(master->irq, master); 1002 free_irq(master->irq, master);
975 1003
976 iounmap(master->base); 1004 iounmap(master->base);
977 kfree(master); 1005 kfree(master);
978 master = NULL; 1006
1007 fsi_soc_dai[0].dev = NULL;
1008 fsi_soc_dai[0].private_data = NULL;
1009 fsi_soc_dai[1].dev = NULL;
1010 fsi_soc_dai[1].private_data = NULL;
1011
1012 return 0;
1013}
1014
1015static int fsi_runtime_nop(struct device *dev)
1016{
1017 /* Runtime PM callback shared between ->runtime_suspend()
1018 * and ->runtime_resume(). Simply returns success.
1019 *
1020 * This driver re-initializes all registers after
1021 * pm_runtime_get_sync() anyway so there is no need
1022 * to save and restore registers here.
1023 */
979 return 0; 1024 return 0;
980} 1025}
981 1026
1027static struct dev_pm_ops fsi_pm_ops = {
1028 .runtime_suspend = fsi_runtime_nop,
1029 .runtime_resume = fsi_runtime_nop,
1030};
1031
982static struct platform_driver fsi_driver = { 1032static struct platform_driver fsi_driver = {
983 .driver = { 1033 .driver = {
984 .name = "sh_fsi", 1034 .name = "sh_fsi",
1035 .pm = &fsi_pm_ops,
985 }, 1036 },
986 .probe = fsi_probe, 1037 .probe = fsi_probe,
987 .remove = fsi_remove, 1038 .remove = fsi_remove,
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
new file mode 100644
index 000000000000..b823a5c9b9bc
--- /dev/null
+++ b/sound/soc/sh/migor.c
@@ -0,0 +1,218 @@
1/*
2 * ALSA SoC driver for Migo-R
3 *
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/device.h>
12#include <linux/firmware.h>
13#include <linux/module.h>
14
15#include <asm/clock.h>
16
17#include <cpu/sh7722.h>
18
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23
24#include "../codecs/wm8978.h"
25#include "siu.h"
26
27/* Default 8000Hz sampling frequency */
28static unsigned long codec_freq = 8000 * 512;
29
30static unsigned int use_count;
31
32/* External clock, sourced from the codec at the SIUMCKB pin */
33static unsigned long siumckb_recalc(struct clk *clk)
34{
35 return codec_freq;
36}
37
38static struct clk_ops siumckb_clk_ops = {
39 .recalc = siumckb_recalc,
40};
41
42static struct clk siumckb_clk = {
43 .name = "siumckb_clk",
44 .id = -1,
45 .ops = &siumckb_clk_ops,
46 .rate = 0, /* initialised at run-time */
47};
48
49static int migor_hw_params(struct snd_pcm_substream *substream,
50 struct snd_pcm_hw_params *params)
51{
52 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
54 int ret;
55 unsigned int rate = params_rate(params);
56
57 ret = snd_soc_dai_set_sysclk(codec_dai, WM8978_PLL, 13000000,
58 SND_SOC_CLOCK_IN);
59 if (ret < 0)
60 return ret;
61
62 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8978_OPCLKRATE, rate * 512);
63 if (ret < 0)
64 return ret;
65
66 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_NB_IF |
67 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);
68 if (ret < 0)
69 return ret;
70
71 ret = snd_soc_dai_set_fmt(rtd->dai->cpu_dai, SND_SOC_DAIFMT_NB_IF |
72 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);
73 if (ret < 0)
74 return ret;
75
76 codec_freq = rate * 512;
77 /*
78 * This propagates the parent frequency change to children and
79 * recalculates the frequency table
80 */
81 clk_set_rate(&siumckb_clk, codec_freq);
82 dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq);
83
84 ret = snd_soc_dai_set_sysclk(rtd->dai->cpu_dai, SIU_CLKB_EXT,
85 codec_freq / 2, SND_SOC_CLOCK_IN);
86
87 if (!ret)
88 use_count++;
89
90 return ret;
91}
92
93static int migor_hw_free(struct snd_pcm_substream *substream)
94{
95 struct snd_soc_pcm_runtime *rtd = substream->private_data;
96 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
97
98 if (use_count) {
99 use_count--;
100
101 if (!use_count)
102 snd_soc_dai_set_sysclk(codec_dai, WM8978_PLL, 0,
103 SND_SOC_CLOCK_IN);
104 } else {
105 dev_dbg(codec_dai->dev, "Unbalanced hw_free!\n");
106 }
107
108 return 0;
109}
110
111static struct snd_soc_ops migor_dai_ops = {
112 .hw_params = migor_hw_params,
113 .hw_free = migor_hw_free,
114};
115
116static const struct snd_soc_dapm_widget migor_dapm_widgets[] = {
117 SND_SOC_DAPM_HP("Headphone", NULL),
118 SND_SOC_DAPM_MIC("Onboard Microphone", NULL),
119 SND_SOC_DAPM_MIC("External Microphone", NULL),
120};
121
122static const struct snd_soc_dapm_route audio_map[] = {
123 /* Headphone output connected to LHP/RHP, enable OUT4 for VMID */
124 { "Headphone", NULL, "OUT4 VMID" },
125 { "OUT4 VMID", NULL, "LHP" },
126 { "OUT4 VMID", NULL, "RHP" },
127
128 /* On-board microphone */
129 { "RMICN", NULL, "Mic Bias" },
130 { "RMICP", NULL, "Mic Bias" },
131 { "Mic Bias", NULL, "Onboard Microphone" },
132
133 /* External microphone */
134 { "LMICN", NULL, "Mic Bias" },
135 { "LMICP", NULL, "Mic Bias" },
136 { "Mic Bias", NULL, "External Microphone" },
137};
138
139static int migor_dai_init(struct snd_soc_codec *codec)
140{
141 snd_soc_dapm_new_controls(codec, migor_dapm_widgets,
142 ARRAY_SIZE(migor_dapm_widgets));
143
144 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
145
146 return 0;
147}
148
149/* migor digital audio interface glue - connects codec <--> CPU */
150static struct snd_soc_dai_link migor_dai = {
151 .name = "wm8978",
152 .stream_name = "WM8978",
153 .cpu_dai = &siu_i2s_dai,
154 .codec_dai = &wm8978_dai,
155 .ops = &migor_dai_ops,
156 .init = migor_dai_init,
157};
158
159/* migor audio machine driver */
160static struct snd_soc_card snd_soc_migor = {
161 .name = "Migo-R",
162 .platform = &siu_platform,
163 .dai_link = &migor_dai,
164 .num_links = 1,
165};
166
167/* migor audio subsystem */
168static struct snd_soc_device migor_snd_devdata = {
169 .card = &snd_soc_migor,
170 .codec_dev = &soc_codec_dev_wm8978,
171};
172
173static struct platform_device *migor_snd_device;
174
175static int __init migor_init(void)
176{
177 int ret;
178
179 ret = clk_register(&siumckb_clk);
180 if (ret < 0)
181 return ret;
182
183 /* Port number used on this machine: port B */
184 migor_snd_device = platform_device_alloc("soc-audio", 1);
185 if (!migor_snd_device) {
186 ret = -ENOMEM;
187 goto epdevalloc;
188 }
189
190 platform_set_drvdata(migor_snd_device, &migor_snd_devdata);
191
192 migor_snd_devdata.dev = &migor_snd_device->dev;
193
194 ret = platform_device_add(migor_snd_device);
195 if (ret)
196 goto epdevadd;
197
198 return 0;
199
200epdevadd:
201 platform_device_put(migor_snd_device);
202epdevalloc:
203 clk_unregister(&siumckb_clk);
204 return ret;
205}
206
207static void __exit migor_exit(void)
208{
209 clk_unregister(&siumckb_clk);
210 platform_device_unregister(migor_snd_device);
211}
212
213module_init(migor_init);
214module_exit(migor_exit);
215
216MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
217MODULE_DESCRIPTION("ALSA SoC Migor");
218MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
new file mode 100644
index 000000000000..c0bfab8fed3d
--- /dev/null
+++ b/sound/soc/sh/siu.h
@@ -0,0 +1,193 @@
1/*
2 * siu.h - ALSA SoC driver for Renesas SH7343, SH7722 SIU peripheral.
3 *
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 * Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#ifndef SIU_H
23#define SIU_H
24
25/* Common kernel and user-space firmware-building defines and types */
26
27#define YRAM0_SIZE (0x0040 / 4) /* 16 */
28#define YRAM1_SIZE (0x0080 / 4) /* 32 */
29#define YRAM2_SIZE (0x0040 / 4) /* 16 */
30#define YRAM3_SIZE (0x0080 / 4) /* 32 */
31#define YRAM4_SIZE (0x0080 / 4) /* 32 */
32#define YRAM_DEF_SIZE (YRAM0_SIZE + YRAM1_SIZE + YRAM2_SIZE + \
33 YRAM3_SIZE + YRAM4_SIZE)
34#define YRAM_FIR_SIZE (0x0400 / 4) /* 256 */
35#define YRAM_IIR_SIZE (0x0200 / 4) /* 128 */
36
37#define XRAM0_SIZE (0x0400 / 4) /* 256 */
38#define XRAM1_SIZE (0x0200 / 4) /* 128 */
39#define XRAM2_SIZE (0x0200 / 4) /* 128 */
40
41/* PRAM program array size */
42#define PRAM0_SIZE (0x0100 / 4) /* 64 */
43#define PRAM1_SIZE ((0x2000 - 0x0100) / 4) /* 1984 */
44
45#include <linux/types.h>
46
47struct siu_spb_param {
48 __u32 ab1a; /* input FIFO address */
49 __u32 ab0a; /* output FIFO address */
50 __u32 dir; /* 0=the ather except CPUOUTPUT, 1=CPUINPUT */
51 __u32 event; /* SPB program starting conditions */
52 __u32 stfifo; /* STFIFO register setting value */
53 __u32 trdat; /* TRDAT register setting value */
54};
55
56struct siu_firmware {
57 __u32 yram_fir_coeff[YRAM_FIR_SIZE];
58 __u32 pram0[PRAM0_SIZE];
59 __u32 pram1[PRAM1_SIZE];
60 __u32 yram0[YRAM0_SIZE];
61 __u32 yram1[YRAM1_SIZE];
62 __u32 yram2[YRAM2_SIZE];
63 __u32 yram3[YRAM3_SIZE];
64 __u32 yram4[YRAM4_SIZE];
65 __u32 spbpar_num;
66 struct siu_spb_param spbpar[32];
67};
68
69#ifdef __KERNEL__
70
71#include <linux/dmaengine.h>
72#include <linux/interrupt.h>
73#include <linux/io.h>
74
75#include <asm/dmaengine.h>
76
77#include <sound/core.h>
78#include <sound/pcm.h>
79#include <sound/soc-dai.h>
80
81#define SIU_PERIOD_BYTES_MAX 8192 /* DMA transfer/period size */
82#define SIU_PERIOD_BYTES_MIN 256 /* DMA transfer/period size */
83#define SIU_PERIODS_MAX 64 /* Max periods in buffer */
84#define SIU_PERIODS_MIN 4 /* Min periods in buffer */
85#define SIU_BUFFER_BYTES_MAX (SIU_PERIOD_BYTES_MAX * SIU_PERIODS_MAX)
86
87/* SIU ports: only one can be used at a time */
88enum {
89 SIU_PORT_A,
90 SIU_PORT_B,
91 SIU_PORT_NUM,
92};
93
94/* SIU clock configuration */
95enum {
96 SIU_CLKA_PLL,
97 SIU_CLKA_EXT,
98 SIU_CLKB_PLL,
99 SIU_CLKB_EXT
100};
101
102struct siu_info {
103 int port_id;
104 u32 __iomem *pram;
105 u32 __iomem *xram;
106 u32 __iomem *yram;
107 u32 __iomem *reg;
108 struct siu_firmware fw;
109};
110
111struct siu_stream {
112 struct tasklet_struct tasklet;
113 struct snd_pcm_substream *substream;
114 snd_pcm_format_t format;
115 size_t buf_bytes;
116 size_t period_bytes;
117 int cur_period; /* Period currently in dma */
118 u32 volume;
119 snd_pcm_sframes_t xfer_cnt; /* Number of frames */
120 u8 rw_flg; /* transfer status */
121 /* DMA status */
122 struct dma_chan *chan; /* DMA channel */
123 struct dma_async_tx_descriptor *tx_desc;
124 dma_cookie_t cookie;
125 struct sh_dmae_slave param;
126};
127
128struct siu_port {
129 unsigned long play_cap; /* Used to track full duplex */
130 struct snd_pcm *pcm;
131 struct siu_stream playback;
132 struct siu_stream capture;
133 u32 stfifo; /* STFIFO value from firmware */
134 u32 trdat; /* TRDAT value from firmware */
135};
136
137extern struct siu_port *siu_ports[SIU_PORT_NUM];
138
139static inline struct siu_port *siu_port_info(struct snd_pcm_substream *substream)
140{
141 struct platform_device *pdev =
142 to_platform_device(substream->pcm->card->dev);
143 return siu_ports[pdev->id];
144}
145
146/* Register access */
147static inline void siu_write32(u32 __iomem *addr, u32 val)
148{
149 __raw_writel(val, addr);
150}
151
152static inline u32 siu_read32(u32 __iomem *addr)
153{
154 return __raw_readl(addr);
155}
156
157/* SIU registers */
158#define SIU_IFCTL (0x000 / sizeof(u32))
159#define SIU_SRCTL (0x004 / sizeof(u32))
160#define SIU_SFORM (0x008 / sizeof(u32))
161#define SIU_CKCTL (0x00c / sizeof(u32))
162#define SIU_TRDAT (0x010 / sizeof(u32))
163#define SIU_STFIFO (0x014 / sizeof(u32))
164#define SIU_DPAK (0x01c / sizeof(u32))
165#define SIU_CKREV (0x020 / sizeof(u32))
166#define SIU_EVNTC (0x028 / sizeof(u32))
167#define SIU_SBCTL (0x040 / sizeof(u32))
168#define SIU_SBPSET (0x044 / sizeof(u32))
169#define SIU_SBFSTS (0x068 / sizeof(u32))
170#define SIU_SBDVCA (0x06c / sizeof(u32))
171#define SIU_SBDVCB (0x070 / sizeof(u32))
172#define SIU_SBACTIV (0x074 / sizeof(u32))
173#define SIU_DMAIA (0x090 / sizeof(u32))
174#define SIU_DMAIB (0x094 / sizeof(u32))
175#define SIU_DMAOA (0x098 / sizeof(u32))
176#define SIU_DMAOB (0x09c / sizeof(u32))
177#define SIU_DMAML (0x0a0 / sizeof(u32))
178#define SIU_SPSTS (0x0cc / sizeof(u32))
179#define SIU_SPCTL (0x0d0 / sizeof(u32))
180#define SIU_BRGASEL (0x100 / sizeof(u32))
181#define SIU_BRRA (0x104 / sizeof(u32))
182#define SIU_BRGBSEL (0x108 / sizeof(u32))
183#define SIU_BRRB (0x10c / sizeof(u32))
184
185extern struct snd_soc_platform siu_platform;
186extern struct snd_soc_dai siu_i2s_dai;
187
188int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card);
189void siu_free_port(struct siu_port *port_info);
190
191#endif
192
193#endif /* SIU_H */
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
new file mode 100644
index 000000000000..d86ee1bfc03a
--- /dev/null
+++ b/sound/soc/sh/siu_dai.c
@@ -0,0 +1,848 @@
1/*
2 * siu_dai.c - ALSA SoC driver for Renesas SH7343, SH7722 SIU peripheral.
3 *
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 * Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/delay.h>
23#include <linux/firmware.h>
24#include <linux/pm_runtime.h>
25#include <linux/slab.h>
26
27#include <asm/clock.h>
28#include <asm/siu.h>
29
30#include <sound/control.h>
31#include <sound/soc-dai.h>
32
33#include "siu.h"
34
35/* Board specifics */
36#if defined(CONFIG_CPU_SUBTYPE_SH7722)
37# define SIU_MAX_VOLUME 0x1000
38#else
39# define SIU_MAX_VOLUME 0x7fff
40#endif
41
42#define PRAM_SIZE 0x2000
43#define XRAM_SIZE 0x800
44#define YRAM_SIZE 0x800
45
46#define XRAM_OFFSET 0x4000
47#define YRAM_OFFSET 0x6000
48#define REG_OFFSET 0xc000
49
50#define PLAYBACK_ENABLED 1
51#define CAPTURE_ENABLED 2
52
53#define VOLUME_CAPTURE 0
54#define VOLUME_PLAYBACK 1
55#define DFLT_VOLUME_LEVEL 0x08000800
56
57/*
58 * SPDIF is only available on port A and on some SIU implementations it is only
59 * available for input. Due to the lack of hardware to test it, SPDIF is left
60 * disabled in this driver version
61 */
62struct format_flag {
63 u32 i2s;
64 u32 pcm;
65 u32 spdif;
66 u32 mask;
67};
68
69struct port_flag {
70 struct format_flag playback;
71 struct format_flag capture;
72};
73
74static struct port_flag siu_flags[SIU_PORT_NUM] = {
75 [SIU_PORT_A] = {
76 .playback = {
77 .i2s = 0x50000000,
78 .pcm = 0x40000000,
79 .spdif = 0x80000000, /* not on all SIU versions */
80 .mask = 0xd0000000,
81 },
82 .capture = {
83 .i2s = 0x05000000,
84 .pcm = 0x04000000,
85 .spdif = 0x08000000,
86 .mask = 0x0d000000,
87 },
88 },
89 [SIU_PORT_B] = {
90 .playback = {
91 .i2s = 0x00500000,
92 .pcm = 0x00400000,
93 .spdif = 0, /* impossible - turn off */
94 .mask = 0x00500000,
95 },
96 .capture = {
97 .i2s = 0x00050000,
98 .pcm = 0x00040000,
99 .spdif = 0, /* impossible - turn off */
100 .mask = 0x00050000,
101 },
102 },
103};
104
105static void siu_dai_start(struct siu_port *port_info)
106{
107 struct siu_info *info = siu_i2s_dai.private_data;
108 u32 __iomem *base = info->reg;
109
110 dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
111
112 /* Turn on SIU clock */
113 pm_runtime_get_sync(siu_i2s_dai.dev);
114
115 /* Issue software reset to siu */
116 siu_write32(base + SIU_SRCTL, 0);
117
118 /* Wait for the reset to take effect */
119 udelay(1);
120
121 port_info->stfifo = 0;
122 port_info->trdat = 0;
123
124 /* portA, portB, SIU operate */
125 siu_write32(base + SIU_SRCTL, 0x301);
126
127 /* portA=256fs, portB=256fs */
128 siu_write32(base + SIU_CKCTL, 0x40400000);
129
130 /* portA's BRG does not divide SIUCKA */
131 siu_write32(base + SIU_BRGASEL, 0);
132 siu_write32(base + SIU_BRRA, 0);
133
134 /* portB's BRG divides SIUCKB by half */
135 siu_write32(base + SIU_BRGBSEL, 1);
136 siu_write32(base + SIU_BRRB, 0);
137
138 siu_write32(base + SIU_IFCTL, 0x44440000);
139
140 /* portA: 32 bit/fs, master; portB: 32 bit/fs, master */
141 siu_write32(base + SIU_SFORM, 0x0c0c0000);
142
143 /*
144 * Volume levels: looks like the DSP firmware implements volume controls
145 * differently from what's described in the datasheet
146 */
147 siu_write32(base + SIU_SBDVCA, port_info->playback.volume);
148 siu_write32(base + SIU_SBDVCB, port_info->capture.volume);
149}
150
151static void siu_dai_stop(void)
152{
153 struct siu_info *info = siu_i2s_dai.private_data;
154 u32 __iomem *base = info->reg;
155
156 /* SIU software reset */
157 siu_write32(base + SIU_SRCTL, 0);
158
159 /* Turn off SIU clock */
160 pm_runtime_put_sync(siu_i2s_dai.dev);
161}
162
163static void siu_dai_spbAselect(struct siu_port *port_info)
164{
165 struct siu_info *info = siu_i2s_dai.private_data;
166 struct siu_firmware *fw = &info->fw;
167 u32 *ydef = fw->yram0;
168 u32 idx;
169
170 /* path A use */
171 if (!info->port_id)
172 idx = 1; /* portA */
173 else
174 idx = 2; /* portB */
175
176 ydef[0] = (fw->spbpar[idx].ab1a << 16) |
177 (fw->spbpar[idx].ab0a << 8) |
178 (fw->spbpar[idx].dir << 7) | 3;
179 ydef[1] = fw->yram0[1]; /* 0x03000300 */
180 ydef[2] = (16 / 2) << 24;
181 ydef[3] = fw->yram0[3]; /* 0 */
182 ydef[4] = fw->yram0[4]; /* 0 */
183 ydef[7] = fw->spbpar[idx].event;
184 port_info->stfifo |= fw->spbpar[idx].stfifo;
185 port_info->trdat |= fw->spbpar[idx].trdat;
186}
187
188static void siu_dai_spbBselect(struct siu_port *port_info)
189{
190 struct siu_info *info = siu_i2s_dai.private_data;
191 struct siu_firmware *fw = &info->fw;
192 u32 *ydef = fw->yram0;
193 u32 idx;
194
195 /* path B use */
196 if (!info->port_id)
197 idx = 7; /* portA */
198 else
199 idx = 8; /* portB */
200
201 ydef[5] = (fw->spbpar[idx].ab1a << 16) |
202 (fw->spbpar[idx].ab0a << 8) | 1;
203 ydef[6] = fw->spbpar[idx].event;
204 port_info->stfifo |= fw->spbpar[idx].stfifo;
205 port_info->trdat |= fw->spbpar[idx].trdat;
206}
207
208static void siu_dai_open(struct siu_stream *siu_stream)
209{
210 struct siu_info *info = siu_i2s_dai.private_data;
211 u32 __iomem *base = info->reg;
212 u32 srctl, ifctl;
213
214 srctl = siu_read32(base + SIU_SRCTL);
215 ifctl = siu_read32(base + SIU_IFCTL);
216
217 switch (info->port_id) {
218 case SIU_PORT_A:
219 /* portA operates */
220 srctl |= 0x200;
221 ifctl &= ~0xc2;
222 break;
223 case SIU_PORT_B:
224 /* portB operates */
225 srctl |= 0x100;
226 ifctl &= ~0x31;
227 break;
228 }
229
230 siu_write32(base + SIU_SRCTL, srctl);
231 /* Unmute and configure portA */
232 siu_write32(base + SIU_IFCTL, ifctl);
233}
234
235/*
236 * At the moment only fixed Left-upper, Left-lower, Right-upper, Right-lower
237 * packing is supported
238 */
239static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
240{
241 struct siu_info *info = siu_i2s_dai.private_data;
242 u32 __iomem *base = info->reg;
243 u32 dpak;
244
245 dpak = siu_read32(base + SIU_DPAK);
246
247 switch (info->port_id) {
248 case SIU_PORT_A:
249 dpak &= ~0xc0000000;
250 break;
251 case SIU_PORT_B:
252 dpak &= ~0x00c00000;
253 break;
254 }
255
256 siu_write32(base + SIU_DPAK, dpak);
257}
258
259static int siu_dai_spbstart(struct siu_port *port_info)
260{
261 struct siu_info *info = siu_i2s_dai.private_data;
262 u32 __iomem *base = info->reg;
263 struct siu_firmware *fw = &info->fw;
264 u32 *ydef = fw->yram0;
265 int cnt;
266 u32 __iomem *add;
267 u32 *ptr;
268
269 /* Load SPB Program in PRAM */
270 ptr = fw->pram0;
271 add = info->pram;
272 for (cnt = 0; cnt < PRAM0_SIZE; cnt++, add++, ptr++)
273 siu_write32(add, *ptr);
274
275 ptr = fw->pram1;
276 add = info->pram + (0x0100 / sizeof(u32));
277 for (cnt = 0; cnt < PRAM1_SIZE; cnt++, add++, ptr++)
278 siu_write32(add, *ptr);
279
280 /* XRAM initialization */
281 add = info->xram;
282 for (cnt = 0; cnt < XRAM0_SIZE + XRAM1_SIZE + XRAM2_SIZE; cnt++, add++)
283 siu_write32(add, 0);
284
285 /* YRAM variable area initialization */
286 add = info->yram;
287 for (cnt = 0; cnt < YRAM_DEF_SIZE; cnt++, add++)
288 siu_write32(add, ydef[cnt]);
289
290 /* YRAM FIR coefficient area initialization */
291 add = info->yram + (0x0200 / sizeof(u32));
292 for (cnt = 0; cnt < YRAM_FIR_SIZE; cnt++, add++)
293 siu_write32(add, fw->yram_fir_coeff[cnt]);
294
295 /* YRAM IIR coefficient area initialization */
296 add = info->yram + (0x0600 / sizeof(u32));
297 for (cnt = 0; cnt < YRAM_IIR_SIZE; cnt++, add++)
298 siu_write32(add, 0);
299
300 siu_write32(base + SIU_TRDAT, port_info->trdat);
301 port_info->trdat = 0x0;
302
303
304 /* SPB start condition: software */
305 siu_write32(base + SIU_SBACTIV, 0);
306 /* Start SPB */
307 siu_write32(base + SIU_SBCTL, 0xc0000000);
308 /* Wait for program to halt */
309 cnt = 0x10000;
310 while (--cnt && siu_read32(base + SIU_SBCTL) != 0x80000000)
311 cpu_relax();
312
313 if (!cnt)
314 return -EBUSY;
315
316 /* SPB program start address setting */
317 siu_write32(base + SIU_SBPSET, 0x00400000);
318 /* SPB hardware start(FIFOCTL source) */
319 siu_write32(base + SIU_SBACTIV, 0xc0000000);
320
321 return 0;
322}
323
324static void siu_dai_spbstop(struct siu_port *port_info)
325{
326 struct siu_info *info = siu_i2s_dai.private_data;
327 u32 __iomem *base = info->reg;
328
329 siu_write32(base + SIU_SBACTIV, 0);
330 /* SPB stop */
331 siu_write32(base + SIU_SBCTL, 0);
332
333 port_info->stfifo = 0;
334}
335
336/* API functions */
337
338/* Playback and capture hardware properties are identical */
339static struct snd_pcm_hardware siu_dai_pcm_hw = {
340 .info = SNDRV_PCM_INFO_INTERLEAVED,
341 .formats = SNDRV_PCM_FMTBIT_S16,
342 .rates = SNDRV_PCM_RATE_8000_48000,
343 .rate_min = 8000,
344 .rate_max = 48000,
345 .channels_min = 2,
346 .channels_max = 2,
347 .buffer_bytes_max = SIU_BUFFER_BYTES_MAX,
348 .period_bytes_min = SIU_PERIOD_BYTES_MIN,
349 .period_bytes_max = SIU_PERIOD_BYTES_MAX,
350 .periods_min = SIU_PERIODS_MIN,
351 .periods_max = SIU_PERIODS_MAX,
352};
353
354static int siu_dai_info_volume(struct snd_kcontrol *kctrl,
355 struct snd_ctl_elem_info *uinfo)
356{
357 struct siu_port *port_info = snd_kcontrol_chip(kctrl);
358
359 dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
360
361 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
362 uinfo->count = 2;
363 uinfo->value.integer.min = 0;
364 uinfo->value.integer.max = SIU_MAX_VOLUME;
365
366 return 0;
367}
368
369static int siu_dai_get_volume(struct snd_kcontrol *kctrl,
370 struct snd_ctl_elem_value *ucontrol)
371{
372 struct siu_port *port_info = snd_kcontrol_chip(kctrl);
373 struct device *dev = port_info->pcm->card->dev;
374 u32 vol;
375
376 dev_dbg(dev, "%s\n", __func__);
377
378 switch (kctrl->private_value) {
379 case VOLUME_PLAYBACK:
380 /* Playback is always on port 0 */
381 vol = port_info->playback.volume;
382 ucontrol->value.integer.value[0] = vol & 0xffff;
383 ucontrol->value.integer.value[1] = vol >> 16 & 0xffff;
384 break;
385 case VOLUME_CAPTURE:
386 /* Capture is always on port 1 */
387 vol = port_info->capture.volume;
388 ucontrol->value.integer.value[0] = vol & 0xffff;
389 ucontrol->value.integer.value[1] = vol >> 16 & 0xffff;
390 break;
391 default:
392 dev_err(dev, "%s() invalid private_value=%ld\n",
393 __func__, kctrl->private_value);
394 return -EINVAL;
395 }
396
397 return 0;
398}
399
400static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
401 struct snd_ctl_elem_value *ucontrol)
402{
403 struct siu_port *port_info = snd_kcontrol_chip(kctrl);
404 struct device *dev = port_info->pcm->card->dev;
405 struct siu_info *info = siu_i2s_dai.private_data;
406 u32 __iomem *base = info->reg;
407 u32 new_vol;
408 u32 cur_vol;
409
410 dev_dbg(dev, "%s\n", __func__);
411
412 if (ucontrol->value.integer.value[0] < 0 ||
413 ucontrol->value.integer.value[0] > SIU_MAX_VOLUME ||
414 ucontrol->value.integer.value[1] < 0 ||
415 ucontrol->value.integer.value[1] > SIU_MAX_VOLUME)
416 return -EINVAL;
417
418 new_vol = ucontrol->value.integer.value[0] |
419 ucontrol->value.integer.value[1] << 16;
420
421 /* See comment above - DSP firmware implementation */
422 switch (kctrl->private_value) {
423 case VOLUME_PLAYBACK:
424 /* Playback is always on port 0 */
425 cur_vol = port_info->playback.volume;
426 siu_write32(base + SIU_SBDVCA, new_vol);
427 port_info->playback.volume = new_vol;
428 break;
429 case VOLUME_CAPTURE:
430 /* Capture is always on port 1 */
431 cur_vol = port_info->capture.volume;
432 siu_write32(base + SIU_SBDVCB, new_vol);
433 port_info->capture.volume = new_vol;
434 break;
435 default:
436 dev_err(dev, "%s() invalid private_value=%ld\n",
437 __func__, kctrl->private_value);
438 return -EINVAL;
439 }
440
441 if (cur_vol != new_vol)
442 return 1;
443
444 return 0;
445}
446
447static struct snd_kcontrol_new playback_controls = {
448 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
449 .name = "PCM Playback Volume",
450 .index = 0,
451 .info = siu_dai_info_volume,
452 .get = siu_dai_get_volume,
453 .put = siu_dai_put_volume,
454 .private_value = VOLUME_PLAYBACK,
455};
456
457static struct snd_kcontrol_new capture_controls = {
458 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
459 .name = "PCM Capture Volume",
460 .index = 0,
461 .info = siu_dai_info_volume,
462 .get = siu_dai_get_volume,
463 .put = siu_dai_put_volume,
464 .private_value = VOLUME_CAPTURE,
465};
466
467int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card)
468{
469 struct device *dev = card->dev;
470 struct snd_kcontrol *kctrl;
471 int ret;
472
473 *port_info = kzalloc(sizeof(**port_info), GFP_KERNEL);
474 if (!*port_info)
475 return -ENOMEM;
476
477 dev_dbg(dev, "%s: port #%d@%p\n", __func__, port, *port_info);
478
479 (*port_info)->playback.volume = DFLT_VOLUME_LEVEL;
480 (*port_info)->capture.volume = DFLT_VOLUME_LEVEL;
481
482 /*
483 * Add mixer support. The SPB is used to change the volume. Both
484 * ports use the same SPB. Therefore, we only register one
485 * control instance since it will be used by both channels.
486 * In error case we continue without controls.
487 */
488 kctrl = snd_ctl_new1(&playback_controls, *port_info);
489 ret = snd_ctl_add(card, kctrl);
490 if (ret < 0)
491 dev_err(dev,
492 "failed to add playback controls %p port=%d err=%d\n",
493 kctrl, port, ret);
494
495 kctrl = snd_ctl_new1(&capture_controls, *port_info);
496 ret = snd_ctl_add(card, kctrl);
497 if (ret < 0)
498 dev_err(dev,
499 "failed to add capture controls %p port=%d err=%d\n",
500 kctrl, port, ret);
501
502 return 0;
503}
504
505void siu_free_port(struct siu_port *port_info)
506{
507 kfree(port_info);
508}
509
510static int siu_dai_startup(struct snd_pcm_substream *substream,
511 struct snd_soc_dai *dai)
512{
513 struct siu_info *info = siu_i2s_dai.private_data;
514 struct snd_pcm_runtime *rt = substream->runtime;
515 struct siu_port *port_info = siu_port_info(substream);
516 int ret;
517
518 dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
519 info->port_id, port_info);
520
521 snd_soc_set_runtime_hwparams(substream, &siu_dai_pcm_hw);
522
523 ret = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
524 if (unlikely(ret < 0))
525 return ret;
526
527 siu_dai_start(port_info);
528
529 return 0;
530}
531
532static void siu_dai_shutdown(struct snd_pcm_substream *substream,
533 struct snd_soc_dai *dai)
534{
535 struct siu_info *info = siu_i2s_dai.private_data;
536 struct siu_port *port_info = siu_port_info(substream);
537
538 dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
539 info->port_id, port_info);
540
541 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
542 port_info->play_cap &= ~PLAYBACK_ENABLED;
543 else
544 port_info->play_cap &= ~CAPTURE_ENABLED;
545
546 /* Stop the siu if the other stream is not using it */
547 if (!port_info->play_cap) {
548 /* during stmread or stmwrite ? */
549 BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg);
550 siu_dai_spbstop(port_info);
551 siu_dai_stop();
552 }
553}
554
555/* PCM part of siu_dai_playback_prepare() / siu_dai_capture_prepare() */
556static int siu_dai_prepare(struct snd_pcm_substream *substream,
557 struct snd_soc_dai *dai)
558{
559 struct siu_info *info = siu_i2s_dai.private_data;
560 struct snd_pcm_runtime *rt = substream->runtime;
561 struct siu_port *port_info = siu_port_info(substream);
562 struct siu_stream *siu_stream;
563 int self, ret;
564
565 dev_dbg(substream->pcm->card->dev,
566 "%s: port %d, active streams %lx, %d channels\n",
567 __func__, info->port_id, port_info->play_cap, rt->channels);
568
569 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
570 self = PLAYBACK_ENABLED;
571 siu_stream = &port_info->playback;
572 } else {
573 self = CAPTURE_ENABLED;
574 siu_stream = &port_info->capture;
575 }
576
577 /* Set up the siu if not already done */
578 if (!port_info->play_cap) {
579 siu_stream->rw_flg = 0; /* stream-data transfer flag */
580
581 siu_dai_spbAselect(port_info);
582 siu_dai_spbBselect(port_info);
583
584 siu_dai_open(siu_stream);
585
586 siu_dai_pcmdatapack(siu_stream);
587
588 ret = siu_dai_spbstart(port_info);
589 if (ret < 0)
590 goto fail;
591 }
592
593 port_info->play_cap |= self;
594
595fail:
596 return ret;
597}
598
599/*
600 * SIU can set bus format to I2S / PCM / SPDIF independently for playback and
601 * capture, however, the current API sets the bus format globally for a DAI.
602 */
603static int siu_dai_set_fmt(struct snd_soc_dai *dai,
604 unsigned int fmt)
605{
606 struct siu_info *info = siu_i2s_dai.private_data;
607 u32 __iomem *base = info->reg;
608 u32 ifctl;
609
610 dev_dbg(dai->dev, "%s: fmt 0x%x on port %d\n",
611 __func__, fmt, info->port_id);
612
613 if (info->port_id < 0)
614 return -ENODEV;
615
616 /* Here select between I2S / PCM / SPDIF */
617 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
618 case SND_SOC_DAIFMT_I2S:
619 ifctl = siu_flags[info->port_id].playback.i2s |
620 siu_flags[info->port_id].capture.i2s;
621 break;
622 case SND_SOC_DAIFMT_LEFT_J:
623 ifctl = siu_flags[info->port_id].playback.pcm |
624 siu_flags[info->port_id].capture.pcm;
625 break;
626 /* SPDIF disabled - see comment at the top */
627 default:
628 return -EINVAL;
629 }
630
631 ifctl |= ~(siu_flags[info->port_id].playback.mask |
632 siu_flags[info->port_id].capture.mask) &
633 siu_read32(base + SIU_IFCTL);
634 siu_write32(base + SIU_IFCTL, ifctl);
635
636 return 0;
637}
638
639static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
640 unsigned int freq, int dir)
641{
642 struct clk *siu_clk, *parent_clk;
643 char *siu_name, *parent_name;
644 int ret;
645
646 if (dir != SND_SOC_CLOCK_IN)
647 return -EINVAL;
648
649 dev_dbg(dai->dev, "%s: using clock %d\n", __func__, clk_id);
650
651 switch (clk_id) {
652 case SIU_CLKA_PLL:
653 siu_name = "siua_clk";
654 parent_name = "pll_clk";
655 break;
656 case SIU_CLKA_EXT:
657 siu_name = "siua_clk";
658 parent_name = "siumcka_clk";
659 break;
660 case SIU_CLKB_PLL:
661 siu_name = "siub_clk";
662 parent_name = "pll_clk";
663 break;
664 case SIU_CLKB_EXT:
665 siu_name = "siub_clk";
666 parent_name = "siumckb_clk";
667 break;
668 default:
669 return -EINVAL;
670 }
671
672 siu_clk = clk_get(siu_i2s_dai.dev, siu_name);
673 if (IS_ERR(siu_clk))
674 return PTR_ERR(siu_clk);
675
676 parent_clk = clk_get(siu_i2s_dai.dev, parent_name);
677 if (!IS_ERR(parent_clk)) {
678 ret = clk_set_parent(siu_clk, parent_clk);
679 if (!ret)
680 clk_set_rate(siu_clk, freq);
681 clk_put(parent_clk);
682 }
683
684 clk_put(siu_clk);
685
686 return 0;
687}
688
689static struct snd_soc_dai_ops siu_dai_ops = {
690 .startup = siu_dai_startup,
691 .shutdown = siu_dai_shutdown,
692 .prepare = siu_dai_prepare,
693 .set_sysclk = siu_dai_set_sysclk,
694 .set_fmt = siu_dai_set_fmt,
695};
696
697struct snd_soc_dai siu_i2s_dai = {
698 .name = "sh-siu",
699 .id = 0,
700 .playback = {
701 .channels_min = 2,
702 .channels_max = 2,
703 .formats = SNDRV_PCM_FMTBIT_S16,
704 .rates = SNDRV_PCM_RATE_8000_48000,
705 },
706 .capture = {
707 .channels_min = 2,
708 .channels_max = 2,
709 .formats = SNDRV_PCM_FMTBIT_S16,
710 .rates = SNDRV_PCM_RATE_8000_48000,
711 },
712 .ops = &siu_dai_ops,
713};
714EXPORT_SYMBOL_GPL(siu_i2s_dai);
715
716static int __devinit siu_probe(struct platform_device *pdev)
717{
718 const struct firmware *fw_entry;
719 struct resource *res, *region;
720 struct siu_info *info;
721 int ret;
722
723 info = kmalloc(sizeof(*info), GFP_KERNEL);
724 if (!info)
725 return -ENOMEM;
726
727 ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);
728 if (ret)
729 goto ereqfw;
730
731 /*
732 * Loaded firmware is "const" - read only, but we have to modify it in
733 * snd_siu_sh7343_spbAselect() and snd_siu_sh7343_spbBselect()
734 */
735 memcpy(&info->fw, fw_entry->data, fw_entry->size);
736
737 release_firmware(fw_entry);
738
739 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
740 if (!res) {
741 ret = -ENODEV;
742 goto egetres;
743 }
744
745 region = request_mem_region(res->start, resource_size(res),
746 pdev->name);
747 if (!region) {
748 dev_err(&pdev->dev, "SIU region already claimed\n");
749 ret = -EBUSY;
750 goto ereqmemreg;
751 }
752
753 ret = -ENOMEM;
754 info->pram = ioremap(res->start, PRAM_SIZE);
755 if (!info->pram)
756 goto emappram;
757 info->xram = ioremap(res->start + XRAM_OFFSET, XRAM_SIZE);
758 if (!info->xram)
759 goto emapxram;
760 info->yram = ioremap(res->start + YRAM_OFFSET, YRAM_SIZE);
761 if (!info->yram)
762 goto emapyram;
763 info->reg = ioremap(res->start + REG_OFFSET, resource_size(res) -
764 REG_OFFSET);
765 if (!info->reg)
766 goto emapreg;
767
768 siu_i2s_dai.dev = &pdev->dev;
769 siu_i2s_dai.private_data = info;
770
771 ret = snd_soc_register_dais(&siu_i2s_dai, 1);
772 if (ret < 0)
773 goto edaiinit;
774
775 ret = snd_soc_register_platform(&siu_platform);
776 if (ret < 0)
777 goto esocregp;
778
779 pm_runtime_enable(&pdev->dev);
780
781 return ret;
782
783esocregp:
784 snd_soc_unregister_dais(&siu_i2s_dai, 1);
785edaiinit:
786 iounmap(info->reg);
787emapreg:
788 iounmap(info->yram);
789emapyram:
790 iounmap(info->xram);
791emapxram:
792 iounmap(info->pram);
793emappram:
794 release_mem_region(res->start, resource_size(res));
795ereqmemreg:
796egetres:
797ereqfw:
798 kfree(info);
799
800 return ret;
801}
802
803static int __devexit siu_remove(struct platform_device *pdev)
804{
805 struct siu_info *info = siu_i2s_dai.private_data;
806 struct resource *res;
807
808 pm_runtime_disable(&pdev->dev);
809
810 snd_soc_unregister_platform(&siu_platform);
811 snd_soc_unregister_dais(&siu_i2s_dai, 1);
812
813 iounmap(info->reg);
814 iounmap(info->yram);
815 iounmap(info->xram);
816 iounmap(info->pram);
817 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
818 if (res)
819 release_mem_region(res->start, resource_size(res));
820 kfree(info);
821
822 return 0;
823}
824
825static struct platform_driver siu_driver = {
826 .driver = {
827 .name = "sh_siu",
828 },
829 .probe = siu_probe,
830 .remove = __devexit_p(siu_remove),
831};
832
833static int __init siu_init(void)
834{
835 return platform_driver_register(&siu_driver);
836}
837
838static void __exit siu_exit(void)
839{
840 platform_driver_unregister(&siu_driver);
841}
842
843module_init(siu_init)
844module_exit(siu_exit)
845
846MODULE_AUTHOR("Carlos Munoz <carlos@kenati.com>");
847MODULE_DESCRIPTION("ALSA SoC SH7722 SIU driver");
848MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
new file mode 100644
index 000000000000..8f85719212f9
--- /dev/null
+++ b/sound/soc/sh/siu_pcm.c
@@ -0,0 +1,615 @@
1/*
2 * siu_pcm.c - ALSA driver for Renesas SH7343, SH7722 SIU peripheral.
3 *
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 * Copyright (C) 2006 Carlos Munoz <carlos@kenati.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21#include <linux/delay.h>
22#include <linux/dma-mapping.h>
23#include <linux/dmaengine.h>
24#include <linux/interrupt.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27
28#include <sound/control.h>
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc-dai.h>
33
34#include <asm/dmaengine.h>
35#include <asm/siu.h>
36
37#include "siu.h"
38
39#define GET_MAX_PERIODS(buf_bytes, period_bytes) \
40 ((buf_bytes) / (period_bytes))
41#define PERIOD_OFFSET(buf_addr, period_num, period_bytes) \
42 ((buf_addr) + ((period_num) * (period_bytes)))
43
44#define RWF_STM_RD 0x01 /* Read in progress */
45#define RWF_STM_WT 0x02 /* Write in progress */
46
47struct siu_port *siu_ports[SIU_PORT_NUM];
48
49/* transfersize is number of u32 dma transfers per period */
50static int siu_pcm_stmwrite_stop(struct siu_port *port_info)
51{
52 struct siu_info *info = siu_i2s_dai.private_data;
53 u32 __iomem *base = info->reg;
54 struct siu_stream *siu_stream = &port_info->playback;
55 u32 stfifo;
56
57 if (!siu_stream->rw_flg)
58 return -EPERM;
59
60 /* output FIFO disable */
61 stfifo = siu_read32(base + SIU_STFIFO);
62 siu_write32(base + SIU_STFIFO, stfifo & ~0x0c180c18);
63 pr_debug("%s: STFIFO %x -> %x\n", __func__,
64 stfifo, stfifo & ~0x0c180c18);
65
66 /* during stmwrite clear */
67 siu_stream->rw_flg = 0;
68
69 return 0;
70}
71
72static int siu_pcm_stmwrite_start(struct siu_port *port_info)
73{
74 struct siu_stream *siu_stream = &port_info->playback;
75
76 if (siu_stream->rw_flg)
77 return -EPERM;
78
79 /* Current period in buffer */
80 port_info->playback.cur_period = 0;
81
82 /* during stmwrite flag set */
83 siu_stream->rw_flg = RWF_STM_WT;
84
85 /* DMA transfer start */
86 tasklet_schedule(&siu_stream->tasklet);
87
88 return 0;
89}
90
91static void siu_dma_tx_complete(void *arg)
92{
93 struct siu_stream *siu_stream = arg;
94
95 if (!siu_stream->rw_flg)
96 return;
97
98 /* Update completed period count */
99 if (++siu_stream->cur_period >=
100 GET_MAX_PERIODS(siu_stream->buf_bytes,
101 siu_stream->period_bytes))
102 siu_stream->cur_period = 0;
103
104 pr_debug("%s: done period #%d (%u/%u bytes), cookie %d\n",
105 __func__, siu_stream->cur_period,
106 siu_stream->cur_period * siu_stream->period_bytes,
107 siu_stream->buf_bytes, siu_stream->cookie);
108
109 tasklet_schedule(&siu_stream->tasklet);
110
111 /* Notify alsa: a period is done */
112 snd_pcm_period_elapsed(siu_stream->substream);
113}
114
115static int siu_pcm_wr_set(struct siu_port *port_info,
116 dma_addr_t buff, u32 size)
117{
118 struct siu_info *info = siu_i2s_dai.private_data;
119 u32 __iomem *base = info->reg;
120 struct siu_stream *siu_stream = &port_info->playback;
121 struct snd_pcm_substream *substream = siu_stream->substream;
122 struct device *dev = substream->pcm->card->dev;
123 struct dma_async_tx_descriptor *desc;
124 dma_cookie_t cookie;
125 struct scatterlist sg;
126 u32 stfifo;
127
128 sg_init_table(&sg, 1);
129 sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
130 size, offset_in_page(buff));
131 sg_dma_address(&sg) = buff;
132
133 desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
134 &sg, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
135 if (!desc) {
136 dev_err(dev, "Failed to allocate a dma descriptor\n");
137 return -ENOMEM;
138 }
139
140 desc->callback = siu_dma_tx_complete;
141 desc->callback_param = siu_stream;
142 cookie = desc->tx_submit(desc);
143 if (cookie < 0) {
144 dev_err(dev, "Failed to submit a dma transfer\n");
145 return cookie;
146 }
147
148 siu_stream->tx_desc = desc;
149 siu_stream->cookie = cookie;
150
151 dma_async_issue_pending(siu_stream->chan);
152
153 /* only output FIFO enable */
154 stfifo = siu_read32(base + SIU_STFIFO);
155 siu_write32(base + SIU_STFIFO, stfifo | (port_info->stfifo & 0x0c180c18));
156 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
157 stfifo, stfifo | (port_info->stfifo & 0x0c180c18));
158
159 return 0;
160}
161
162static int siu_pcm_rd_set(struct siu_port *port_info,
163 dma_addr_t buff, size_t size)
164{
165 struct siu_info *info = siu_i2s_dai.private_data;
166 u32 __iomem *base = info->reg;
167 struct siu_stream *siu_stream = &port_info->capture;
168 struct snd_pcm_substream *substream = siu_stream->substream;
169 struct device *dev = substream->pcm->card->dev;
170 struct dma_async_tx_descriptor *desc;
171 dma_cookie_t cookie;
172 struct scatterlist sg;
173 u32 stfifo;
174
175 dev_dbg(dev, "%s: %u@%llx\n", __func__, size, (unsigned long long)buff);
176
177 sg_init_table(&sg, 1);
178 sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
179 size, offset_in_page(buff));
180 sg_dma_address(&sg) = buff;
181
182 desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
183 &sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
184 if (!desc) {
185 dev_err(dev, "Failed to allocate dma descriptor\n");
186 return -ENOMEM;
187 }
188
189 desc->callback = siu_dma_tx_complete;
190 desc->callback_param = siu_stream;
191 cookie = desc->tx_submit(desc);
192 if (cookie < 0) {
193 dev_err(dev, "Failed to submit dma descriptor\n");
194 return cookie;
195 }
196
197 siu_stream->tx_desc = desc;
198 siu_stream->cookie = cookie;
199
200 dma_async_issue_pending(siu_stream->chan);
201
202 /* only input FIFO enable */
203 stfifo = siu_read32(base + SIU_STFIFO);
204 siu_write32(base + SIU_STFIFO, siu_read32(base + SIU_STFIFO) |
205 (port_info->stfifo & 0x13071307));
206 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
207 stfifo, stfifo | (port_info->stfifo & 0x13071307));
208
209 return 0;
210}
211
212static void siu_io_tasklet(unsigned long data)
213{
214 struct siu_stream *siu_stream = (struct siu_stream *)data;
215 struct snd_pcm_substream *substream = siu_stream->substream;
216 struct device *dev = substream->pcm->card->dev;
217 struct snd_pcm_runtime *rt = substream->runtime;
218 struct siu_port *port_info = siu_port_info(substream);
219
220 dev_dbg(dev, "%s: flags %x\n", __func__, siu_stream->rw_flg);
221
222 if (!siu_stream->rw_flg) {
223 dev_dbg(dev, "%s: stream inactive\n", __func__);
224 return;
225 }
226
227 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
228 dma_addr_t buff;
229 size_t count;
230 u8 *virt;
231
232 buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr,
233 siu_stream->cur_period,
234 siu_stream->period_bytes);
235 virt = PERIOD_OFFSET(rt->dma_area,
236 siu_stream->cur_period,
237 siu_stream->period_bytes);
238 count = siu_stream->period_bytes;
239
240 /* DMA transfer start */
241 siu_pcm_rd_set(port_info, buff, count);
242 } else {
243 siu_pcm_wr_set(port_info,
244 (dma_addr_t)PERIOD_OFFSET(rt->dma_addr,
245 siu_stream->cur_period,
246 siu_stream->period_bytes),
247 siu_stream->period_bytes);
248 }
249}
250
251/* Capture */
252static int siu_pcm_stmread_start(struct siu_port *port_info)
253{
254 struct siu_stream *siu_stream = &port_info->capture;
255
256 if (siu_stream->xfer_cnt > 0x1000000)
257 return -EINVAL;
258 if (siu_stream->rw_flg)
259 return -EPERM;
260
261 /* Current period in buffer */
262 siu_stream->cur_period = 0;
263
264 /* during stmread flag set */
265 siu_stream->rw_flg = RWF_STM_RD;
266
267 tasklet_schedule(&siu_stream->tasklet);
268
269 return 0;
270}
271
272static int siu_pcm_stmread_stop(struct siu_port *port_info)
273{
274 struct siu_info *info = siu_i2s_dai.private_data;
275 u32 __iomem *base = info->reg;
276 struct siu_stream *siu_stream = &port_info->capture;
277 struct device *dev = siu_stream->substream->pcm->card->dev;
278 u32 stfifo;
279
280 if (!siu_stream->rw_flg)
281 return -EPERM;
282
283 /* input FIFO disable */
284 stfifo = siu_read32(base + SIU_STFIFO);
285 siu_write32(base + SIU_STFIFO, stfifo & ~0x13071307);
286 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__,
287 stfifo, stfifo & ~0x13071307);
288
289 /* during stmread flag clear */
290 siu_stream->rw_flg = 0;
291
292 return 0;
293}
294
295static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
296 struct snd_pcm_hw_params *hw_params)
297{
298 struct siu_info *info = siu_i2s_dai.private_data;
299 struct device *dev = ss->pcm->card->dev;
300 int ret;
301
302 dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
303
304 ret = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
305 if (ret < 0)
306 dev_err(dev, "snd_pcm_lib_malloc_pages() failed\n");
307
308 return ret;
309}
310
311static int siu_pcm_hw_free(struct snd_pcm_substream *ss)
312{
313 struct siu_info *info = siu_i2s_dai.private_data;
314 struct siu_port *port_info = siu_port_info(ss);
315 struct device *dev = ss->pcm->card->dev;
316 struct siu_stream *siu_stream;
317
318 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
319 siu_stream = &port_info->playback;
320 else
321 siu_stream = &port_info->capture;
322
323 dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
324
325 return snd_pcm_lib_free_pages(ss);
326}
327
328static bool filter(struct dma_chan *chan, void *slave)
329{
330 struct sh_dmae_slave *param = slave;
331
332 pr_debug("%s: slave ID %d\n", __func__, param->slave_id);
333
334 if (unlikely(param->dma_dev != chan->device->dev))
335 return false;
336
337 chan->private = param;
338 return true;
339}
340
341static int siu_pcm_open(struct snd_pcm_substream *ss)
342{
343 /* Playback / Capture */
344 struct siu_info *info = siu_i2s_dai.private_data;
345 struct siu_port *port_info = siu_port_info(ss);
346 struct siu_stream *siu_stream;
347 u32 port = info->port_id;
348 struct siu_platform *pdata = siu_i2s_dai.dev->platform_data;
349 struct device *dev = ss->pcm->card->dev;
350 dma_cap_mask_t mask;
351 struct sh_dmae_slave *param;
352
353 dma_cap_zero(mask);
354 dma_cap_set(DMA_SLAVE, mask);
355
356 dev_dbg(dev, "%s, port=%d@%p\n", __func__, port, port_info);
357
358 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) {
359 siu_stream = &port_info->playback;
360 param = &siu_stream->param;
361 param->slave_id = port ? SHDMA_SLAVE_SIUB_TX :
362 SHDMA_SLAVE_SIUA_TX;
363 } else {
364 siu_stream = &port_info->capture;
365 param = &siu_stream->param;
366 param->slave_id = port ? SHDMA_SLAVE_SIUB_RX :
367 SHDMA_SLAVE_SIUA_RX;
368 }
369
370 param->dma_dev = pdata->dma_dev;
371 /* Get DMA channel */
372 siu_stream->chan = dma_request_channel(mask, filter, param);
373 if (!siu_stream->chan) {
374 dev_err(dev, "DMA channel allocation failed!\n");
375 return -EBUSY;
376 }
377
378 siu_stream->substream = ss;
379
380 return 0;
381}
382
383static int siu_pcm_close(struct snd_pcm_substream *ss)
384{
385 struct siu_info *info = siu_i2s_dai.private_data;
386 struct device *dev = ss->pcm->card->dev;
387 struct siu_port *port_info = siu_port_info(ss);
388 struct siu_stream *siu_stream;
389
390 dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id);
391
392 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
393 siu_stream = &port_info->playback;
394 else
395 siu_stream = &port_info->capture;
396
397 dma_release_channel(siu_stream->chan);
398 siu_stream->chan = NULL;
399
400 siu_stream->substream = NULL;
401
402 return 0;
403}
404
405static int siu_pcm_prepare(struct snd_pcm_substream *ss)
406{
407 struct siu_info *info = siu_i2s_dai.private_data;
408 struct siu_port *port_info = siu_port_info(ss);
409 struct device *dev = ss->pcm->card->dev;
410 struct snd_pcm_runtime *rt = ss->runtime;
411 struct siu_stream *siu_stream;
412 snd_pcm_sframes_t xfer_cnt;
413
414 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
415 siu_stream = &port_info->playback;
416 else
417 siu_stream = &port_info->capture;
418
419 rt = siu_stream->substream->runtime;
420
421 siu_stream->buf_bytes = snd_pcm_lib_buffer_bytes(ss);
422 siu_stream->period_bytes = snd_pcm_lib_period_bytes(ss);
423
424 dev_dbg(dev, "%s: port=%d, %d channels, period=%u bytes\n", __func__,
425 info->port_id, rt->channels, siu_stream->period_bytes);
426
427 /* We only support buffers that are multiples of the period */
428 if (siu_stream->buf_bytes % siu_stream->period_bytes) {
429 dev_err(dev, "%s() - buffer=%d not multiple of period=%d\n",
430 __func__, siu_stream->buf_bytes,
431 siu_stream->period_bytes);
432 return -EINVAL;
433 }
434
435 xfer_cnt = bytes_to_frames(rt, siu_stream->period_bytes);
436 if (!xfer_cnt || xfer_cnt > 0x1000000)
437 return -EINVAL;
438
439 siu_stream->format = rt->format;
440 siu_stream->xfer_cnt = xfer_cnt;
441
442 dev_dbg(dev, "port=%d buf=%lx buf_bytes=%d period_bytes=%d "
443 "format=%d channels=%d xfer_cnt=%d\n", info->port_id,
444 (unsigned long)rt->dma_addr, siu_stream->buf_bytes,
445 siu_stream->period_bytes,
446 siu_stream->format, rt->channels, (int)xfer_cnt);
447
448 return 0;
449}
450
451static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
452{
453 struct siu_info *info = siu_i2s_dai.private_data;
454 struct device *dev = ss->pcm->card->dev;
455 struct siu_port *port_info = siu_port_info(ss);
456 int ret;
457
458 dev_dbg(dev, "%s: port=%d@%p, cmd=%d\n", __func__,
459 info->port_id, port_info, cmd);
460
461 switch (cmd) {
462 case SNDRV_PCM_TRIGGER_START:
463 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
464 ret = siu_pcm_stmwrite_start(port_info);
465 else
466 ret = siu_pcm_stmread_start(port_info);
467
468 if (ret < 0)
469 dev_warn(dev, "%s: start failed on port=%d\n",
470 __func__, info->port_id);
471
472 break;
473 case SNDRV_PCM_TRIGGER_STOP:
474 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
475 siu_pcm_stmwrite_stop(port_info);
476 else
477 siu_pcm_stmread_stop(port_info);
478 ret = 0;
479
480 break;
481 default:
482 dev_err(dev, "%s() unsupported cmd=%d\n", __func__, cmd);
483 ret = -EINVAL;
484 }
485
486 return ret;
487}
488
489/*
490 * So far only resolution of one period is supported, subject to extending the
491 * dmangine API
492 */
493static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
494{
495 struct device *dev = ss->pcm->card->dev;
496 struct siu_info *info = siu_i2s_dai.private_data;
497 u32 __iomem *base = info->reg;
498 struct siu_port *port_info = siu_port_info(ss);
499 struct snd_pcm_runtime *rt = ss->runtime;
500 size_t ptr;
501 struct siu_stream *siu_stream;
502
503 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
504 siu_stream = &port_info->playback;
505 else
506 siu_stream = &port_info->capture;
507
508 /*
509 * ptr is the offset into the buffer where the dma is currently at. We
510 * check if the dma buffer has just wrapped.
511 */
512 ptr = PERIOD_OFFSET(rt->dma_addr,
513 siu_stream->cur_period,
514 siu_stream->period_bytes) - rt->dma_addr;
515
516 dev_dbg(dev,
517 "%s: port=%d, events %x, FSTS %x, xferred %u/%u, cookie %d\n",
518 __func__, info->port_id, siu_read32(base + SIU_EVNTC),
519 siu_read32(base + SIU_SBFSTS), ptr, siu_stream->buf_bytes,
520 siu_stream->cookie);
521
522 if (ptr >= siu_stream->buf_bytes)
523 ptr = 0;
524
525 return bytes_to_frames(ss->runtime, ptr);
526}
527
528static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
529 struct snd_pcm *pcm)
530{
531 /* card->dev == socdev->dev, see snd_soc_new_pcms() */
532 struct siu_info *info = siu_i2s_dai.private_data;
533 struct platform_device *pdev = to_platform_device(card->dev);
534 int ret;
535 int i;
536
537 /* pdev->id selects between SIUA and SIUB */
538 if (pdev->id < 0 || pdev->id >= SIU_PORT_NUM)
539 return -EINVAL;
540
541 info->port_id = pdev->id;
542
543 /*
544 * While the siu has 2 ports, only one port can be on at a time (only 1
545 * SPB). So far all the boards using the siu had only one of the ports
546 * wired to a codec. To simplify things, we only register one port with
547 * alsa. In case both ports are needed, it should be changed here
548 */
549 for (i = pdev->id; i < pdev->id + 1; i++) {
550 struct siu_port **port_info = &siu_ports[i];
551
552 ret = siu_init_port(i, port_info, card);
553 if (ret < 0)
554 return ret;
555
556 ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
557 SNDRV_DMA_TYPE_DEV, NULL,
558 SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX);
559 if (ret < 0) {
560 dev_err(card->dev,
561 "snd_pcm_lib_preallocate_pages_for_all() err=%d",
562 ret);
563 goto fail;
564 }
565
566 (*port_info)->pcm = pcm;
567
568 /* IO tasklets */
569 tasklet_init(&(*port_info)->playback.tasklet, siu_io_tasklet,
570 (unsigned long)&(*port_info)->playback);
571 tasklet_init(&(*port_info)->capture.tasklet, siu_io_tasklet,
572 (unsigned long)&(*port_info)->capture);
573 }
574
575 dev_info(card->dev, "SuperH SIU driver initialized.\n");
576 return 0;
577
578fail:
579 siu_free_port(siu_ports[pdev->id]);
580 dev_err(card->dev, "SIU: failed to initialize.\n");
581 return ret;
582}
583
584static void siu_pcm_free(struct snd_pcm *pcm)
585{
586 struct platform_device *pdev = to_platform_device(pcm->card->dev);
587 struct siu_port *port_info = siu_ports[pdev->id];
588
589 tasklet_kill(&port_info->capture.tasklet);
590 tasklet_kill(&port_info->playback.tasklet);
591
592 siu_free_port(port_info);
593 snd_pcm_lib_preallocate_free_for_all(pcm);
594
595 dev_dbg(pcm->card->dev, "%s\n", __func__);
596}
597
598static struct snd_pcm_ops siu_pcm_ops = {
599 .open = siu_pcm_open,
600 .close = siu_pcm_close,
601 .ioctl = snd_pcm_lib_ioctl,
602 .hw_params = siu_pcm_hw_params,
603 .hw_free = siu_pcm_hw_free,
604 .prepare = siu_pcm_prepare,
605 .trigger = siu_pcm_trigger,
606 .pointer = siu_pcm_pointer_dma,
607};
608
609struct snd_soc_platform siu_platform = {
610 .name = "siu-audio",
611 .pcm_ops = &siu_pcm_ops,
612 .pcm_new = siu_pcm_new,
613 .pcm_free = siu_pcm_free,
614};
615EXPORT_SYMBOL_GPL(siu_platform);