diff options
Diffstat (limited to 'sound/soc/sh/fsi.c')
-rw-r--r-- | sound/soc/sh/fsi.c | 483 |
1 files changed, 267 insertions, 216 deletions
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 @@ | |||
94 | struct fsi_priv { | 94 | struct 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 { | |||
108 | struct fsi_master { | 108 | struct 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 | ||
117 | static 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 | ************************************************************************/ |
126 | static int __fsi_reg_write(u32 reg, u32 data) | 124 | static 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 | ||
134 | static u32 __fsi_reg_read(u32 reg) | 132 | static u32 __fsi_reg_read(u32 reg) |
135 | { | 133 | { |
136 | return ctrl_inl(reg); | 134 | return __raw_readl(reg); |
137 | } | 135 | } |
138 | 136 | ||
139 | static int __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) | 137 | static 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 | ||
149 | static int fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) | 147 | static 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 | ||
157 | static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) | 155 | static 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 | ||
165 | static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) | 163 | static 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 | ||
173 | static int fsi_master_write(u32 reg, u32 data) | 171 | static 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 | ||
182 | static u32 fsi_master_read(u32 reg) | 184 | static 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 | ||
191 | static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) | 200 | static 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 | ************************************************************************/ |
207 | static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream) | 221 | static 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) | 226 | static 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; | 231 | static 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 | ||
228 | static int fsi_is_port_a(struct fsi_priv *fsi) | 239 | static 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 | ||
241 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 246 | static 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 | ||
311 | static 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 | |||
340 | static 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 | |||
356 | static 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) | |||
374 | static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) | 324 | static 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 | ||
382 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) | 333 | static 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 | ||
390 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) | 342 | static 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 | ||
400 | static void fsi_irq_init(struct fsi_priv *fsi, int is_play) | 353 | static 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 | ||
421 | static void fsi_soft_all_reset(void) | 374 | static 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 | ||
438 | static 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 | |||
460 | static 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 */ |
477 | static int fsi_data_push(struct fsi_priv *fsi) | 392 | static 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 | |||
476 | static 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 | ||
535 | static irqreturn_t fsi_interrupt(int irq, void *data) | 559 | static 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) | |||
561 | static int fsi_dai_startup(struct snd_pcm_substream *substream, | 590 | static 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, | |||
682 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | 709 | static 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 | ||
694 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 721 | static 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) | |||
779 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) | 802 | static 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 | ************************************************************************/ |
881 | static int fsi_probe(struct platform_device *pdev) | 913 | static 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 | ||
952 | exit_free_irq: | 979 | exit_free_irq: |
953 | free_irq(irq, master); | 980 | free_irq(irq, master); |
954 | exit_free_dma: | ||
955 | fsi_free_dma_chan(); | ||
956 | exit_iounmap: | 981 | exit_iounmap: |
957 | iounmap(master->base); | 982 | iounmap(master->base); |
983 | pm_runtime_disable(&pdev->dev); | ||
958 | exit_kfree: | 984 | exit_kfree: |
959 | kfree(master); | 985 | kfree(master); |
960 | master = NULL; | 986 | master = NULL; |
@@ -964,24 +990,49 @@ exit: | |||
964 | 990 | ||
965 | static int fsi_remove(struct platform_device *pdev) | 991 | static 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 | |||
1015 | static 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 | ||
1027 | static struct dev_pm_ops fsi_pm_ops = { | ||
1028 | .runtime_suspend = fsi_runtime_nop, | ||
1029 | .runtime_resume = fsi_runtime_nop, | ||
1030 | }; | ||
1031 | |||
982 | static struct platform_driver fsi_driver = { | 1032 | static 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, |