diff options
Diffstat (limited to 'sound/soc/sh/fsi.c')
-rw-r--r-- | sound/soc/sh/fsi.c | 227 |
1 files changed, 144 insertions, 83 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 42813b808389..993abb730dfa 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -67,6 +67,7 @@ | |||
67 | /* DOFF_ST */ | 67 | /* DOFF_ST */ |
68 | #define ERR_OVER 0x00000010 | 68 | #define ERR_OVER 0x00000010 |
69 | #define ERR_UNDER 0x00000001 | 69 | #define ERR_UNDER 0x00000001 |
70 | #define ST_ERR (ERR_OVER | ERR_UNDER) | ||
70 | 71 | ||
71 | /* CLK_RST */ | 72 | /* CLK_RST */ |
72 | #define B_CLK 0x00000010 | 73 | #define B_CLK 0x00000010 |
@@ -92,6 +93,7 @@ | |||
92 | struct fsi_priv { | 93 | struct fsi_priv { |
93 | void __iomem *base; | 94 | void __iomem *base; |
94 | struct snd_pcm_substream *substream; | 95 | struct snd_pcm_substream *substream; |
96 | struct fsi_master *master; | ||
95 | 97 | ||
96 | int fifo_max; | 98 | int fifo_max; |
97 | int chan; | 99 | int chan; |
@@ -108,10 +110,9 @@ struct fsi_master { | |||
108 | struct fsi_priv fsia; | 110 | struct fsi_priv fsia; |
109 | struct fsi_priv fsib; | 111 | struct fsi_priv fsib; |
110 | struct sh_fsi_platform_info *info; | 112 | struct sh_fsi_platform_info *info; |
113 | spinlock_t lock; | ||
111 | }; | 114 | }; |
112 | 115 | ||
113 | static struct fsi_master *master; | ||
114 | |||
115 | /************************************************************************ | 116 | /************************************************************************ |
116 | 117 | ||
117 | 118 | ||
@@ -119,35 +120,35 @@ static struct fsi_master *master; | |||
119 | 120 | ||
120 | 121 | ||
121 | ************************************************************************/ | 122 | ************************************************************************/ |
122 | static int __fsi_reg_write(u32 reg, u32 data) | 123 | static void __fsi_reg_write(u32 reg, u32 data) |
123 | { | 124 | { |
124 | /* valid data area is 24bit */ | 125 | /* valid data area is 24bit */ |
125 | data &= 0x00ffffff; | 126 | data &= 0x00ffffff; |
126 | 127 | ||
127 | return ctrl_outl(data, reg); | 128 | __raw_writel(data, reg); |
128 | } | 129 | } |
129 | 130 | ||
130 | static u32 __fsi_reg_read(u32 reg) | 131 | static u32 __fsi_reg_read(u32 reg) |
131 | { | 132 | { |
132 | return ctrl_inl(reg); | 133 | return __raw_readl(reg); |
133 | } | 134 | } |
134 | 135 | ||
135 | static int __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) | 136 | static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) |
136 | { | 137 | { |
137 | u32 val = __fsi_reg_read(reg); | 138 | u32 val = __fsi_reg_read(reg); |
138 | 139 | ||
139 | val &= ~mask; | 140 | val &= ~mask; |
140 | val |= data & mask; | 141 | val |= data & mask; |
141 | 142 | ||
142 | return __fsi_reg_write(reg, val); | 143 | __fsi_reg_write(reg, val); |
143 | } | 144 | } |
144 | 145 | ||
145 | static int fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) | 146 | static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) |
146 | { | 147 | { |
147 | if (reg > REG_END) | 148 | if (reg > REG_END) |
148 | return -1; | 149 | return; |
149 | 150 | ||
150 | return __fsi_reg_write((u32)(fsi->base + reg), data); | 151 | __fsi_reg_write((u32)(fsi->base + reg), data); |
151 | } | 152 | } |
152 | 153 | ||
153 | static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) | 154 | static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) |
@@ -158,39 +159,55 @@ static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) | |||
158 | return __fsi_reg_read((u32)(fsi->base + reg)); | 159 | return __fsi_reg_read((u32)(fsi->base + reg)); |
159 | } | 160 | } |
160 | 161 | ||
161 | static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) | 162 | static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) |
162 | { | 163 | { |
163 | if (reg > REG_END) | 164 | if (reg > REG_END) |
164 | return -1; | 165 | return; |
165 | 166 | ||
166 | return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); | 167 | __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); |
167 | } | 168 | } |
168 | 169 | ||
169 | static int fsi_master_write(u32 reg, u32 data) | 170 | static void fsi_master_write(struct fsi_master *master, u32 reg, u32 data) |
170 | { | 171 | { |
172 | unsigned long flags; | ||
173 | |||
171 | if ((reg < MREG_START) || | 174 | if ((reg < MREG_START) || |
172 | (reg > MREG_END)) | 175 | (reg > MREG_END)) |
173 | return -1; | 176 | return; |
174 | 177 | ||
175 | return __fsi_reg_write((u32)(master->base + reg), data); | 178 | spin_lock_irqsave(&master->lock, flags); |
179 | __fsi_reg_write((u32)(master->base + reg), data); | ||
180 | spin_unlock_irqrestore(&master->lock, flags); | ||
176 | } | 181 | } |
177 | 182 | ||
178 | static u32 fsi_master_read(u32 reg) | 183 | static u32 fsi_master_read(struct fsi_master *master, u32 reg) |
179 | { | 184 | { |
185 | u32 ret; | ||
186 | unsigned long flags; | ||
187 | |||
180 | if ((reg < MREG_START) || | 188 | if ((reg < MREG_START) || |
181 | (reg > MREG_END)) | 189 | (reg > MREG_END)) |
182 | return 0; | 190 | return 0; |
183 | 191 | ||
184 | return __fsi_reg_read((u32)(master->base + reg)); | 192 | spin_lock_irqsave(&master->lock, flags); |
193 | ret = __fsi_reg_read((u32)(master->base + reg)); | ||
194 | spin_unlock_irqrestore(&master->lock, flags); | ||
195 | |||
196 | return ret; | ||
185 | } | 197 | } |
186 | 198 | ||
187 | static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) | 199 | static void fsi_master_mask_set(struct fsi_master *master, |
200 | u32 reg, u32 mask, u32 data) | ||
188 | { | 201 | { |
202 | unsigned long flags; | ||
203 | |||
189 | if ((reg < MREG_START) || | 204 | if ((reg < MREG_START) || |
190 | (reg > MREG_END)) | 205 | (reg > MREG_END)) |
191 | return -1; | 206 | return; |
192 | 207 | ||
193 | return __fsi_reg_mask_set((u32)(master->base + reg), mask, data); | 208 | spin_lock_irqsave(&master->lock, flags); |
209 | __fsi_reg_mask_set((u32)(master->base + reg), mask, data); | ||
210 | spin_unlock_irqrestore(&master->lock, flags); | ||
194 | } | 211 | } |
195 | 212 | ||
196 | /************************************************************************ | 213 | /************************************************************************ |
@@ -200,43 +217,35 @@ static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) | |||
200 | 217 | ||
201 | 218 | ||
202 | ************************************************************************/ | 219 | ************************************************************************/ |
203 | static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream) | 220 | static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) |
204 | { | 221 | { |
205 | struct snd_soc_pcm_runtime *rtd; | 222 | return fsi->master; |
206 | struct fsi_priv *fsi = NULL; | 223 | } |
207 | 224 | ||
208 | if (!substream || !master) | 225 | static int fsi_is_port_a(struct fsi_priv *fsi) |
209 | return NULL; | 226 | { |
227 | return fsi->master->base == fsi->base; | ||
228 | } | ||
210 | 229 | ||
211 | rtd = substream->private_data; | 230 | static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) |
212 | switch (rtd->dai->cpu_dai->id) { | 231 | { |
213 | case 0: | 232 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
214 | fsi = &master->fsia; | 233 | struct snd_soc_dai_link *machine = rtd->dai; |
215 | break; | ||
216 | case 1: | ||
217 | fsi = &master->fsib; | ||
218 | break; | ||
219 | } | ||
220 | 234 | ||
221 | return fsi; | 235 | return machine->cpu_dai; |
222 | } | 236 | } |
223 | 237 | ||
224 | static int fsi_is_port_a(struct fsi_priv *fsi) | 238 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) |
225 | { | 239 | { |
226 | /* return | 240 | struct snd_soc_dai *dai = fsi_get_dai(substream); |
227 | * 1 : port a | ||
228 | * 0 : port b | ||
229 | */ | ||
230 | 241 | ||
231 | if (fsi == &master->fsia) | 242 | return dai->private_data; |
232 | return 1; | ||
233 | |||
234 | return 0; | ||
235 | } | 243 | } |
236 | 244 | ||
237 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 245 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) |
238 | { | 246 | { |
239 | int is_porta = fsi_is_port_a(fsi); | 247 | int is_porta = fsi_is_port_a(fsi); |
248 | struct fsi_master *master = fsi_get_master(fsi); | ||
240 | 249 | ||
241 | return is_porta ? master->info->porta_flags : | 250 | return is_porta ? master->info->porta_flags : |
242 | master->info->portb_flags; | 251 | master->info->portb_flags; |
@@ -314,27 +323,30 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) | |||
314 | static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) | 323 | static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) |
315 | { | 324 | { |
316 | u32 data = fsi_port_ab_io_bit(fsi, is_play); | 325 | u32 data = fsi_port_ab_io_bit(fsi, is_play); |
326 | struct fsi_master *master = fsi_get_master(fsi); | ||
317 | 327 | ||
318 | fsi_master_mask_set(IMSK, data, data); | 328 | fsi_master_mask_set(master, IMSK, data, data); |
319 | fsi_master_mask_set(IEMSK, data, data); | 329 | fsi_master_mask_set(master, IEMSK, data, data); |
320 | } | 330 | } |
321 | 331 | ||
322 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) | 332 | static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) |
323 | { | 333 | { |
324 | u32 data = fsi_port_ab_io_bit(fsi, is_play); | 334 | u32 data = fsi_port_ab_io_bit(fsi, is_play); |
335 | struct fsi_master *master = fsi_get_master(fsi); | ||
325 | 336 | ||
326 | fsi_master_mask_set(IMSK, data, 0); | 337 | fsi_master_mask_set(master, IMSK, data, 0); |
327 | fsi_master_mask_set(IEMSK, data, 0); | 338 | fsi_master_mask_set(master, IEMSK, data, 0); |
328 | } | 339 | } |
329 | 340 | ||
330 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) | 341 | static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) |
331 | { | 342 | { |
332 | u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); | 343 | u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); |
344 | struct fsi_master *master = fsi_get_master(fsi); | ||
333 | 345 | ||
334 | if (enable) | 346 | if (enable) |
335 | fsi_master_mask_set(CLK_RST, val, val); | 347 | fsi_master_mask_set(master, CLK_RST, val, val); |
336 | else | 348 | else |
337 | fsi_master_mask_set(CLK_RST, val, 0); | 349 | fsi_master_mask_set(master, CLK_RST, val, 0); |
338 | } | 350 | } |
339 | 351 | ||
340 | static void fsi_irq_init(struct fsi_priv *fsi, int is_play) | 352 | static void fsi_irq_init(struct fsi_priv *fsi, int is_play) |
@@ -355,43 +367,46 @@ static void fsi_irq_init(struct fsi_priv *fsi, int is_play) | |||
355 | fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); | 367 | fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); |
356 | 368 | ||
357 | /* clear interrupt factor */ | 369 | /* clear interrupt factor */ |
358 | fsi_master_mask_set(INT_ST, data, 0); | 370 | fsi_master_mask_set(fsi_get_master(fsi), INT_ST, data, 0); |
359 | } | 371 | } |
360 | 372 | ||
361 | static void fsi_soft_all_reset(void) | 373 | static void fsi_soft_all_reset(struct fsi_master *master) |
362 | { | 374 | { |
363 | u32 status = fsi_master_read(SOFT_RST); | 375 | u32 status = fsi_master_read(master, SOFT_RST); |
364 | 376 | ||
365 | /* port AB reset */ | 377 | /* port AB reset */ |
366 | status &= 0x000000ff; | 378 | status &= 0x000000ff; |
367 | fsi_master_write(SOFT_RST, status); | 379 | fsi_master_write(master, SOFT_RST, status); |
368 | mdelay(10); | 380 | mdelay(10); |
369 | 381 | ||
370 | /* soft reset */ | 382 | /* soft reset */ |
371 | status &= 0x000000f0; | 383 | status &= 0x000000f0; |
372 | fsi_master_write(SOFT_RST, status); | 384 | fsi_master_write(master, SOFT_RST, status); |
373 | status |= 0x00000001; | 385 | status |= 0x00000001; |
374 | fsi_master_write(SOFT_RST, status); | 386 | fsi_master_write(master, SOFT_RST, status); |
375 | mdelay(10); | 387 | mdelay(10); |
376 | } | 388 | } |
377 | 389 | ||
378 | /* playback interrupt */ | 390 | /* playback interrupt */ |
379 | static int fsi_data_push(struct fsi_priv *fsi) | 391 | static int fsi_data_push(struct fsi_priv *fsi, int startup) |
380 | { | 392 | { |
381 | struct snd_pcm_runtime *runtime; | 393 | struct snd_pcm_runtime *runtime; |
382 | struct snd_pcm_substream *substream = NULL; | 394 | struct snd_pcm_substream *substream = NULL; |
395 | u32 status; | ||
383 | int send; | 396 | int send; |
384 | int fifo_free; | 397 | int fifo_free; |
385 | int width; | 398 | int width; |
386 | u8 *start; | 399 | u8 *start; |
387 | int i; | 400 | int i, over_period; |
388 | 401 | ||
389 | if (!fsi || | 402 | if (!fsi || |
390 | !fsi->substream || | 403 | !fsi->substream || |
391 | !fsi->substream->runtime) | 404 | !fsi->substream->runtime) |
392 | return -EINVAL; | 405 | return -EINVAL; |
393 | 406 | ||
394 | runtime = fsi->substream->runtime; | 407 | over_period = 0; |
408 | substream = fsi->substream; | ||
409 | runtime = substream->runtime; | ||
395 | 410 | ||
396 | /* FSI FIFO has limit. | 411 | /* FSI FIFO has limit. |
397 | * So, this driver can not send periods data at a time | 412 | * So, this driver can not send periods data at a time |
@@ -399,7 +414,7 @@ static int fsi_data_push(struct fsi_priv *fsi) | |||
399 | if (fsi->byte_offset >= | 414 | if (fsi->byte_offset >= |
400 | fsi->period_len * (fsi->periods + 1)) { | 415 | fsi->period_len * (fsi->periods + 1)) { |
401 | 416 | ||
402 | substream = fsi->substream; | 417 | over_period = 1; |
403 | fsi->periods = (fsi->periods + 1) % runtime->periods; | 418 | fsi->periods = (fsi->periods + 1) % runtime->periods; |
404 | 419 | ||
405 | if (0 == fsi->periods) | 420 | if (0 == fsi->periods) |
@@ -438,30 +453,44 @@ static int fsi_data_push(struct fsi_priv *fsi) | |||
438 | 453 | ||
439 | fsi->byte_offset += send * width; | 454 | fsi->byte_offset += send * width; |
440 | 455 | ||
456 | status = fsi_reg_read(fsi, DOFF_ST); | ||
457 | if (!startup) { | ||
458 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
459 | |||
460 | if (status & ERR_OVER) | ||
461 | dev_err(dai->dev, "over run\n"); | ||
462 | if (status & ERR_UNDER) | ||
463 | dev_err(dai->dev, "under run\n"); | ||
464 | } | ||
465 | fsi_reg_write(fsi, DOFF_ST, 0); | ||
466 | |||
441 | fsi_irq_enable(fsi, 1); | 467 | fsi_irq_enable(fsi, 1); |
442 | 468 | ||
443 | if (substream) | 469 | if (over_period) |
444 | snd_pcm_period_elapsed(substream); | 470 | snd_pcm_period_elapsed(substream); |
445 | 471 | ||
446 | return 0; | 472 | return 0; |
447 | } | 473 | } |
448 | 474 | ||
449 | static int fsi_data_pop(struct fsi_priv *fsi) | 475 | static int fsi_data_pop(struct fsi_priv *fsi, int startup) |
450 | { | 476 | { |
451 | struct snd_pcm_runtime *runtime; | 477 | struct snd_pcm_runtime *runtime; |
452 | struct snd_pcm_substream *substream = NULL; | 478 | struct snd_pcm_substream *substream = NULL; |
479 | u32 status; | ||
453 | int free; | 480 | int free; |
454 | int fifo_fill; | 481 | int fifo_fill; |
455 | int width; | 482 | int width; |
456 | u8 *start; | 483 | u8 *start; |
457 | int i; | 484 | int i, over_period; |
458 | 485 | ||
459 | if (!fsi || | 486 | if (!fsi || |
460 | !fsi->substream || | 487 | !fsi->substream || |
461 | !fsi->substream->runtime) | 488 | !fsi->substream->runtime) |
462 | return -EINVAL; | 489 | return -EINVAL; |
463 | 490 | ||
464 | runtime = fsi->substream->runtime; | 491 | over_period = 0; |
492 | substream = fsi->substream; | ||
493 | runtime = substream->runtime; | ||
465 | 494 | ||
466 | /* FSI FIFO has limit. | 495 | /* FSI FIFO has limit. |
467 | * So, this driver can not send periods data at a time | 496 | * So, this driver can not send periods data at a time |
@@ -469,7 +498,7 @@ static int fsi_data_pop(struct fsi_priv *fsi) | |||
469 | if (fsi->byte_offset >= | 498 | if (fsi->byte_offset >= |
470 | fsi->period_len * (fsi->periods + 1)) { | 499 | fsi->period_len * (fsi->periods + 1)) { |
471 | 500 | ||
472 | substream = fsi->substream; | 501 | over_period = 1; |
473 | fsi->periods = (fsi->periods + 1) % runtime->periods; | 502 | fsi->periods = (fsi->periods + 1) % runtime->periods; |
474 | 503 | ||
475 | if (0 == fsi->periods) | 504 | if (0 == fsi->periods) |
@@ -507,9 +536,20 @@ static int fsi_data_pop(struct fsi_priv *fsi) | |||
507 | 536 | ||
508 | fsi->byte_offset += fifo_fill * width; | 537 | fsi->byte_offset += fifo_fill * width; |
509 | 538 | ||
539 | status = fsi_reg_read(fsi, DIFF_ST); | ||
540 | if (!startup) { | ||
541 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
542 | |||
543 | if (status & ERR_OVER) | ||
544 | dev_err(dai->dev, "over run\n"); | ||
545 | if (status & ERR_UNDER) | ||
546 | dev_err(dai->dev, "under run\n"); | ||
547 | } | ||
548 | fsi_reg_write(fsi, DIFF_ST, 0); | ||
549 | |||
510 | fsi_irq_enable(fsi, 0); | 550 | fsi_irq_enable(fsi, 0); |
511 | 551 | ||
512 | if (substream) | 552 | if (over_period) |
513 | snd_pcm_period_elapsed(substream); | 553 | snd_pcm_period_elapsed(substream); |
514 | 554 | ||
515 | return 0; | 555 | return 0; |
@@ -517,23 +557,24 @@ static int fsi_data_pop(struct fsi_priv *fsi) | |||
517 | 557 | ||
518 | static irqreturn_t fsi_interrupt(int irq, void *data) | 558 | static irqreturn_t fsi_interrupt(int irq, void *data) |
519 | { | 559 | { |
520 | u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; | 560 | struct fsi_master *master = data; |
521 | u32 int_st = fsi_master_read(INT_ST); | 561 | u32 status = fsi_master_read(master, SOFT_RST) & ~0x00000010; |
562 | u32 int_st = fsi_master_read(master, INT_ST); | ||
522 | 563 | ||
523 | /* clear irq status */ | 564 | /* clear irq status */ |
524 | fsi_master_write(SOFT_RST, status); | 565 | fsi_master_write(master, SOFT_RST, status); |
525 | fsi_master_write(SOFT_RST, status | 0x00000010); | 566 | fsi_master_write(master, SOFT_RST, status | 0x00000010); |
526 | 567 | ||
527 | if (int_st & INT_A_OUT) | 568 | if (int_st & INT_A_OUT) |
528 | fsi_data_push(&master->fsia); | 569 | fsi_data_push(&master->fsia, 0); |
529 | if (int_st & INT_B_OUT) | 570 | if (int_st & INT_B_OUT) |
530 | fsi_data_push(&master->fsib); | 571 | fsi_data_push(&master->fsib, 0); |
531 | if (int_st & INT_A_IN) | 572 | if (int_st & INT_A_IN) |
532 | fsi_data_pop(&master->fsia); | 573 | fsi_data_pop(&master->fsia, 0); |
533 | if (int_st & INT_B_IN) | 574 | if (int_st & INT_B_IN) |
534 | fsi_data_pop(&master->fsib); | 575 | fsi_data_pop(&master->fsib, 0); |
535 | 576 | ||
536 | fsi_master_write(INT_ST, 0x0000000); | 577 | fsi_master_write(master, INT_ST, 0x0000000); |
537 | 578 | ||
538 | return IRQ_HANDLED; | 579 | return IRQ_HANDLED; |
539 | } | 580 | } |
@@ -548,7 +589,7 @@ static irqreturn_t fsi_interrupt(int irq, void *data) | |||
548 | static int fsi_dai_startup(struct snd_pcm_substream *substream, | 589 | static int fsi_dai_startup(struct snd_pcm_substream *substream, |
549 | struct snd_soc_dai *dai) | 590 | struct snd_soc_dai *dai) |
550 | { | 591 | { |
551 | struct fsi_priv *fsi = fsi_get(substream); | 592 | struct fsi_priv *fsi = fsi_get_priv(substream); |
552 | const char *msg; | 593 | const char *msg; |
553 | u32 flags = fsi_get_info_flags(fsi); | 594 | u32 flags = fsi_get_info_flags(fsi); |
554 | u32 fmt; | 595 | u32 fmt; |
@@ -667,7 +708,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
667 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | 708 | static void fsi_dai_shutdown(struct snd_pcm_substream *substream, |
668 | struct snd_soc_dai *dai) | 709 | struct snd_soc_dai *dai) |
669 | { | 710 | { |
670 | struct fsi_priv *fsi = fsi_get(substream); | 711 | struct fsi_priv *fsi = fsi_get_priv(substream); |
671 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 712 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
672 | 713 | ||
673 | fsi_irq_disable(fsi, is_play); | 714 | fsi_irq_disable(fsi, is_play); |
@@ -679,7 +720,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
679 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | 720 | static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
680 | struct snd_soc_dai *dai) | 721 | struct snd_soc_dai *dai) |
681 | { | 722 | { |
682 | struct fsi_priv *fsi = fsi_get(substream); | 723 | struct fsi_priv *fsi = fsi_get_priv(substream); |
683 | struct snd_pcm_runtime *runtime = substream->runtime; | 724 | struct snd_pcm_runtime *runtime = substream->runtime; |
684 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 725 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
685 | int ret = 0; | 726 | int ret = 0; |
@@ -689,7 +730,7 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
689 | fsi_stream_push(fsi, substream, | 730 | fsi_stream_push(fsi, substream, |
690 | frames_to_bytes(runtime, runtime->buffer_size), | 731 | frames_to_bytes(runtime, runtime->buffer_size), |
691 | frames_to_bytes(runtime, runtime->period_size)); | 732 | frames_to_bytes(runtime, runtime->period_size)); |
692 | ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); | 733 | ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1); |
693 | break; | 734 | break; |
694 | case SNDRV_PCM_TRIGGER_STOP: | 735 | case SNDRV_PCM_TRIGGER_STOP: |
695 | fsi_irq_disable(fsi, is_play); | 736 | fsi_irq_disable(fsi, is_play); |
@@ -760,7 +801,7 @@ static int fsi_hw_free(struct snd_pcm_substream *substream) | |||
760 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) | 801 | static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) |
761 | { | 802 | { |
762 | struct snd_pcm_runtime *runtime = substream->runtime; | 803 | struct snd_pcm_runtime *runtime = substream->runtime; |
763 | struct fsi_priv *fsi = fsi_get(substream); | 804 | struct fsi_priv *fsi = fsi_get_priv(substream); |
764 | long location; | 805 | long location; |
765 | 806 | ||
766 | location = (fsi->byte_offset - 1); | 807 | location = (fsi->byte_offset - 1); |
@@ -870,10 +911,16 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform); | |||
870 | ************************************************************************/ | 911 | ************************************************************************/ |
871 | static int fsi_probe(struct platform_device *pdev) | 912 | static int fsi_probe(struct platform_device *pdev) |
872 | { | 913 | { |
914 | struct fsi_master *master; | ||
873 | struct resource *res; | 915 | struct resource *res; |
874 | unsigned int irq; | 916 | unsigned int irq; |
875 | int ret; | 917 | int ret; |
876 | 918 | ||
919 | if (0 != pdev->id) { | ||
920 | dev_err(&pdev->dev, "current fsi support id 0 only now\n"); | ||
921 | return -ENODEV; | ||
922 | } | ||
923 | |||
877 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 924 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
878 | irq = platform_get_irq(pdev, 0); | 925 | irq = platform_get_irq(pdev, 0); |
879 | if (!res || (int)irq <= 0) { | 926 | if (!res || (int)irq <= 0) { |
@@ -899,15 +946,20 @@ static int fsi_probe(struct platform_device *pdev) | |||
899 | master->irq = irq; | 946 | master->irq = irq; |
900 | master->info = pdev->dev.platform_data; | 947 | master->info = pdev->dev.platform_data; |
901 | master->fsia.base = master->base; | 948 | master->fsia.base = master->base; |
949 | master->fsia.master = master; | ||
902 | master->fsib.base = master->base + 0x40; | 950 | master->fsib.base = master->base + 0x40; |
951 | master->fsib.master = master; | ||
952 | spin_lock_init(&master->lock); | ||
903 | 953 | ||
904 | pm_runtime_enable(&pdev->dev); | 954 | pm_runtime_enable(&pdev->dev); |
905 | pm_runtime_resume(&pdev->dev); | 955 | pm_runtime_resume(&pdev->dev); |
906 | 956 | ||
907 | fsi_soc_dai[0].dev = &pdev->dev; | 957 | fsi_soc_dai[0].dev = &pdev->dev; |
958 | fsi_soc_dai[0].private_data = &master->fsia; | ||
908 | fsi_soc_dai[1].dev = &pdev->dev; | 959 | fsi_soc_dai[1].dev = &pdev->dev; |
960 | fsi_soc_dai[1].private_data = &master->fsib; | ||
909 | 961 | ||
910 | fsi_soft_all_reset(); | 962 | fsi_soft_all_reset(master); |
911 | 963 | ||
912 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); | 964 | ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); |
913 | if (ret) { | 965 | if (ret) { |
@@ -937,6 +989,10 @@ exit: | |||
937 | 989 | ||
938 | static int fsi_remove(struct platform_device *pdev) | 990 | static int fsi_remove(struct platform_device *pdev) |
939 | { | 991 | { |
992 | struct fsi_master *master; | ||
993 | |||
994 | master = fsi_get_master(fsi_soc_dai[0].private_data); | ||
995 | |||
940 | snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); | 996 | snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); |
941 | snd_soc_unregister_platform(&fsi_soc_platform); | 997 | snd_soc_unregister_platform(&fsi_soc_platform); |
942 | 998 | ||
@@ -946,7 +1002,12 @@ static int fsi_remove(struct platform_device *pdev) | |||
946 | 1002 | ||
947 | iounmap(master->base); | 1003 | iounmap(master->base); |
948 | kfree(master); | 1004 | kfree(master); |
949 | master = NULL; | 1005 | |
1006 | fsi_soc_dai[0].dev = NULL; | ||
1007 | fsi_soc_dai[0].private_data = NULL; | ||
1008 | fsi_soc_dai[1].dev = NULL; | ||
1009 | fsi_soc_dai[1].private_data = NULL; | ||
1010 | |||
950 | return 0; | 1011 | return 0; |
951 | } | 1012 | } |
952 | 1013 | ||