diff options
Diffstat (limited to 'sound/soc/sh/rcar/ssi.c')
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 160 |
1 files changed, 114 insertions, 46 deletions
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 7bb9c087f3dc..2fbe59f7f9b5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -66,6 +66,7 @@ struct rsnd_ssi { | |||
66 | 66 | ||
67 | u32 cr_own; | 67 | u32 cr_own; |
68 | u32 cr_clk; | 68 | u32 cr_clk; |
69 | int chan; | ||
69 | int err; | 70 | int err; |
70 | unsigned int usrcnt; | 71 | unsigned int usrcnt; |
71 | }; | 72 | }; |
@@ -80,16 +81,15 @@ struct rsnd_ssi { | |||
80 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) | 81 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) |
81 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) | 82 | #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) |
82 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) | 83 | #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) |
83 | #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) | 84 | #define rsnd_ssi_parent(ssi) ((ssi)->parent) |
84 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) | 85 | #define rsnd_ssi_mode_flags(p) ((p)->info->flags) |
85 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) | 86 | #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) |
86 | #define rsnd_ssi_of_node(priv) \ | 87 | #define rsnd_ssi_of_node(priv) \ |
87 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi") | 88 | of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi") |
88 | 89 | ||
89 | int rsnd_ssi_use_busif(struct rsnd_mod *mod) | 90 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod) |
90 | { | 91 | { |
91 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 92 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
92 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
93 | int use_busif = 0; | 93 | int use_busif = 0; |
94 | 94 | ||
95 | if (!rsnd_ssi_is_dma_mode(mod)) | 95 | if (!rsnd_ssi_is_dma_mode(mod)) |
@@ -189,22 +189,26 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
189 | rsnd_mod_hw_start(&ssi->mod); | 189 | rsnd_mod_hw_start(&ssi->mod); |
190 | 190 | ||
191 | if (rsnd_rdai_is_clk_master(rdai)) { | 191 | if (rsnd_rdai_is_clk_master(rdai)) { |
192 | if (rsnd_ssi_clk_from_parent(ssi)) | 192 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); |
193 | rsnd_ssi_hw_start(ssi->parent, io); | 193 | |
194 | if (ssi_parent) | ||
195 | rsnd_ssi_hw_start(ssi_parent, io); | ||
194 | else | 196 | else |
195 | rsnd_ssi_master_clk_start(ssi, io); | 197 | rsnd_ssi_master_clk_start(ssi, io); |
196 | } | 198 | } |
197 | } | 199 | } |
198 | 200 | ||
199 | cr_mode = rsnd_ssi_is_dma_mode(&ssi->mod) ? | 201 | if (rsnd_ssi_is_dma_mode(&ssi->mod)) { |
200 | DMEN : /* DMA : enable DMA */ | 202 | cr_mode = UIEN | OIEN | /* over/under run */ |
201 | DIEN; /* PIO : enable Data interrupt */ | 203 | DMEN; /* DMA : enable DMA */ |
202 | 204 | } else { | |
205 | cr_mode = DIEN; /* PIO : enable Data interrupt */ | ||
206 | } | ||
203 | 207 | ||
204 | cr = ssi->cr_own | | 208 | cr = ssi->cr_own | |
205 | ssi->cr_clk | | 209 | ssi->cr_clk | |
206 | cr_mode | | 210 | cr_mode | |
207 | UIEN | OIEN | EN; | 211 | EN; |
208 | 212 | ||
209 | rsnd_mod_write(&ssi->mod, SSICR, cr); | 213 | rsnd_mod_write(&ssi->mod, SSICR, cr); |
210 | 214 | ||
@@ -221,16 +225,17 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, | |||
221 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); | 225 | rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); |
222 | } | 226 | } |
223 | 227 | ||
224 | static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | 228 | static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi) |
225 | { | 229 | { |
226 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); | 230 | struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); |
227 | struct rsnd_dai_stream *io = rsnd_mod_to_io(&ssi->mod); | ||
228 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 231 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
229 | struct device *dev = rsnd_priv_to_dev(priv); | 232 | struct device *dev = rsnd_priv_to_dev(priv); |
230 | u32 cr; | 233 | u32 cr; |
231 | 234 | ||
232 | if (0 == ssi->usrcnt) /* stop might be called without start */ | 235 | if (0 == ssi->usrcnt) { |
236 | dev_err(dev, "%s called without starting\n", __func__); | ||
233 | return; | 237 | return; |
238 | } | ||
234 | 239 | ||
235 | ssi->usrcnt--; | 240 | ssi->usrcnt--; |
236 | 241 | ||
@@ -253,13 +258,17 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | |||
253 | rsnd_ssi_status_check(&ssi->mod, IIRQ); | 258 | rsnd_ssi_status_check(&ssi->mod, IIRQ); |
254 | 259 | ||
255 | if (rsnd_rdai_is_clk_master(rdai)) { | 260 | if (rsnd_rdai_is_clk_master(rdai)) { |
256 | if (rsnd_ssi_clk_from_parent(ssi)) | 261 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); |
257 | rsnd_ssi_hw_stop(ssi->parent); | 262 | |
263 | if (ssi_parent) | ||
264 | rsnd_ssi_hw_stop(io, ssi_parent); | ||
258 | else | 265 | else |
259 | rsnd_ssi_master_clk_stop(ssi); | 266 | rsnd_ssi_master_clk_stop(ssi); |
260 | } | 267 | } |
261 | 268 | ||
262 | rsnd_mod_hw_stop(&ssi->mod); | 269 | rsnd_mod_hw_stop(&ssi->mod); |
270 | |||
271 | ssi->chan = 0; | ||
263 | } | 272 | } |
264 | 273 | ||
265 | dev_dbg(dev, "%s[%d] hw stopped\n", | 274 | dev_dbg(dev, "%s[%d] hw stopped\n", |
@@ -270,10 +279,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | |||
270 | * SSI mod common functions | 279 | * SSI mod common functions |
271 | */ | 280 | */ |
272 | static int rsnd_ssi_init(struct rsnd_mod *mod, | 281 | static int rsnd_ssi_init(struct rsnd_mod *mod, |
282 | struct rsnd_dai_stream *io, | ||
273 | struct rsnd_priv *priv) | 283 | struct rsnd_priv *priv) |
274 | { | 284 | { |
275 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 285 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
276 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
277 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | 286 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
278 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 287 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
279 | u32 cr; | 288 | u32 cr; |
@@ -321,6 +330,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
321 | } | 330 | } |
322 | 331 | ||
323 | static int rsnd_ssi_quit(struct rsnd_mod *mod, | 332 | static int rsnd_ssi_quit(struct rsnd_mod *mod, |
333 | struct rsnd_dai_stream *io, | ||
324 | struct rsnd_priv *priv) | 334 | struct rsnd_priv *priv) |
325 | { | 335 | { |
326 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 336 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
@@ -336,6 +346,37 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, | |||
336 | return 0; | 346 | return 0; |
337 | } | 347 | } |
338 | 348 | ||
349 | static int rsnd_ssi_hw_params(struct rsnd_mod *mod, | ||
350 | struct rsnd_dai_stream *io, | ||
351 | struct snd_pcm_substream *substream, | ||
352 | struct snd_pcm_hw_params *params) | ||
353 | { | ||
354 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
355 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); | ||
356 | int chan = params_channels(params); | ||
357 | |||
358 | /* | ||
359 | * Already working. | ||
360 | * It will happen if SSI has parent/child connection. | ||
361 | */ | ||
362 | if (ssi->usrcnt) { | ||
363 | /* | ||
364 | * it is error if child <-> parent SSI uses | ||
365 | * different channels. | ||
366 | */ | ||
367 | if (ssi->chan != chan) | ||
368 | return -EIO; | ||
369 | } | ||
370 | |||
371 | /* It will be removed on rsnd_ssi_hw_stop */ | ||
372 | ssi->chan = chan; | ||
373 | if (ssi_parent) | ||
374 | return rsnd_ssi_hw_params(&ssi_parent->mod, io, | ||
375 | substream, params); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
339 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | 380 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) |
340 | { | 381 | { |
341 | /* under/over flow error */ | 382 | /* under/over flow error */ |
@@ -348,12 +389,12 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | |||
348 | } | 389 | } |
349 | 390 | ||
350 | static int rsnd_ssi_start(struct rsnd_mod *mod, | 391 | static int rsnd_ssi_start(struct rsnd_mod *mod, |
392 | struct rsnd_dai_stream *io, | ||
351 | struct rsnd_priv *priv) | 393 | struct rsnd_priv *priv) |
352 | { | 394 | { |
353 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 395 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
354 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
355 | 396 | ||
356 | rsnd_src_ssiu_start(mod, rsnd_ssi_use_busif(mod)); | 397 | rsnd_src_ssiu_start(mod, io, rsnd_ssi_use_busif(io, mod)); |
357 | 398 | ||
358 | rsnd_ssi_hw_start(ssi, io); | 399 | rsnd_ssi_hw_start(ssi, io); |
359 | 400 | ||
@@ -363,6 +404,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, | |||
363 | } | 404 | } |
364 | 405 | ||
365 | static int rsnd_ssi_stop(struct rsnd_mod *mod, | 406 | static int rsnd_ssi_stop(struct rsnd_mod *mod, |
407 | struct rsnd_dai_stream *io, | ||
366 | struct rsnd_priv *priv) | 408 | struct rsnd_priv *priv) |
367 | { | 409 | { |
368 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 410 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
@@ -371,24 +413,29 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod, | |||
371 | 413 | ||
372 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); | 414 | rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); |
373 | 415 | ||
374 | rsnd_ssi_hw_stop(ssi); | 416 | rsnd_ssi_hw_stop(io, ssi); |
375 | 417 | ||
376 | rsnd_src_ssiu_stop(mod); | 418 | rsnd_src_ssiu_stop(mod, io); |
377 | 419 | ||
378 | return 0; | 420 | return 0; |
379 | } | 421 | } |
380 | 422 | ||
381 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | 423 | static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, |
424 | struct rsnd_dai_stream *io) | ||
382 | { | 425 | { |
383 | struct rsnd_ssi *ssi = data; | 426 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
384 | struct rsnd_mod *mod = &ssi->mod; | ||
385 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 427 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
386 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
387 | int is_dma = rsnd_ssi_is_dma_mode(mod); | 428 | int is_dma = rsnd_ssi_is_dma_mode(mod); |
388 | u32 status = rsnd_mod_read(mod, SSISR); | 429 | u32 status; |
430 | bool elapsed = false; | ||
431 | |||
432 | spin_lock(&priv->lock); | ||
433 | |||
434 | /* ignore all cases if not working */ | ||
435 | if (!rsnd_io_is_working(io)) | ||
436 | goto rsnd_ssi_interrupt_out; | ||
389 | 437 | ||
390 | if (!io) | 438 | status = rsnd_mod_read(mod, SSISR); |
391 | return IRQ_NONE; | ||
392 | 439 | ||
393 | /* PIO only */ | 440 | /* PIO only */ |
394 | if (!is_dma && (status & DIRQ)) { | 441 | if (!is_dma && (status & DIRQ)) { |
@@ -406,11 +453,11 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
406 | else | 453 | else |
407 | *buf = rsnd_mod_read(mod, SSIRDR); | 454 | *buf = rsnd_mod_read(mod, SSIRDR); |
408 | 455 | ||
409 | rsnd_dai_pointer_update(io, sizeof(*buf)); | 456 | elapsed = rsnd_dai_pointer_update(io, sizeof(*buf)); |
410 | } | 457 | } |
411 | 458 | ||
412 | /* PIO / DMA */ | 459 | /* DMA only */ |
413 | if (status & (UIRQ | OIRQ)) { | 460 | if (is_dma && (status & (UIRQ | OIRQ))) { |
414 | struct device *dev = rsnd_priv_to_dev(priv); | 461 | struct device *dev = rsnd_priv_to_dev(priv); |
415 | 462 | ||
416 | /* | 463 | /* |
@@ -419,15 +466,28 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
419 | dev_dbg(dev, "%s[%d] restart\n", | 466 | dev_dbg(dev, "%s[%d] restart\n", |
420 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 467 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
421 | 468 | ||
422 | rsnd_ssi_stop(mod, priv); | 469 | rsnd_ssi_stop(mod, io, priv); |
423 | if (ssi->err < 1024) | 470 | if (ssi->err < 1024) |
424 | rsnd_ssi_start(mod, priv); | 471 | rsnd_ssi_start(mod, io, priv); |
425 | else | 472 | else |
426 | dev_warn(dev, "no more SSI restart\n"); | 473 | dev_warn(dev, "no more SSI restart\n"); |
427 | } | 474 | } |
428 | 475 | ||
429 | rsnd_ssi_record_error(ssi, status); | 476 | rsnd_ssi_record_error(ssi, status); |
430 | 477 | ||
478 | rsnd_ssi_interrupt_out: | ||
479 | spin_unlock(&priv->lock); | ||
480 | |||
481 | if (elapsed) | ||
482 | rsnd_dai_period_elapsed(io); | ||
483 | } | ||
484 | |||
485 | static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | ||
486 | { | ||
487 | struct rsnd_mod *mod = data; | ||
488 | |||
489 | rsnd_mod_interrupt(mod, __rsnd_ssi_interrupt); | ||
490 | |||
431 | return IRQ_HANDLED; | 491 | return IRQ_HANDLED; |
432 | } | 492 | } |
433 | 493 | ||
@@ -435,6 +495,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) | |||
435 | * SSI PIO | 495 | * SSI PIO |
436 | */ | 496 | */ |
437 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, | 497 | static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, |
498 | struct rsnd_dai_stream *io, | ||
438 | struct rsnd_priv *priv) | 499 | struct rsnd_priv *priv) |
439 | { | 500 | { |
440 | struct device *dev = rsnd_priv_to_dev(priv); | 501 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -444,7 +505,7 @@ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, | |||
444 | ret = devm_request_irq(dev, ssi->info->irq, | 505 | ret = devm_request_irq(dev, ssi->info->irq, |
445 | rsnd_ssi_interrupt, | 506 | rsnd_ssi_interrupt, |
446 | IRQF_SHARED, | 507 | IRQF_SHARED, |
447 | dev_name(dev), ssi); | 508 | dev_name(dev), mod); |
448 | 509 | ||
449 | return ret; | 510 | return ret; |
450 | } | 511 | } |
@@ -456,9 +517,11 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | |||
456 | .quit = rsnd_ssi_quit, | 517 | .quit = rsnd_ssi_quit, |
457 | .start = rsnd_ssi_start, | 518 | .start = rsnd_ssi_start, |
458 | .stop = rsnd_ssi_stop, | 519 | .stop = rsnd_ssi_stop, |
520 | .hw_params = rsnd_ssi_hw_params, | ||
459 | }; | 521 | }; |
460 | 522 | ||
461 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | 523 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, |
524 | struct rsnd_dai_stream *io, | ||
462 | struct rsnd_priv *priv) | 525 | struct rsnd_priv *priv) |
463 | { | 526 | { |
464 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 527 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
@@ -469,25 +532,26 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | |||
469 | ret = devm_request_irq(dev, ssi->info->irq, | 532 | ret = devm_request_irq(dev, ssi->info->irq, |
470 | rsnd_ssi_interrupt, | 533 | rsnd_ssi_interrupt, |
471 | IRQF_SHARED, | 534 | IRQF_SHARED, |
472 | dev_name(dev), ssi); | 535 | dev_name(dev), mod); |
473 | if (ret) | 536 | if (ret) |
474 | return ret; | 537 | return ret; |
475 | 538 | ||
476 | ret = rsnd_dma_init( | 539 | ret = rsnd_dma_init( |
477 | priv, rsnd_mod_to_dma(mod), | 540 | io, rsnd_mod_to_dma(mod), |
478 | dma_id); | 541 | dma_id); |
479 | 542 | ||
480 | return ret; | 543 | return ret; |
481 | } | 544 | } |
482 | 545 | ||
483 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | 546 | static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, |
547 | struct rsnd_dai_stream *io, | ||
484 | struct rsnd_priv *priv) | 548 | struct rsnd_priv *priv) |
485 | { | 549 | { |
486 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 550 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
487 | struct device *dev = rsnd_priv_to_dev(priv); | 551 | struct device *dev = rsnd_priv_to_dev(priv); |
488 | int irq = ssi->info->irq; | 552 | int irq = ssi->info->irq; |
489 | 553 | ||
490 | rsnd_dma_quit(rsnd_mod_to_dma(mod)); | 554 | rsnd_dma_quit(io, rsnd_mod_to_dma(mod)); |
491 | 555 | ||
492 | /* PIO will request IRQ again */ | 556 | /* PIO will request IRQ again */ |
493 | devm_free_irq(dev, irq, ssi); | 557 | devm_free_irq(dev, irq, ssi); |
@@ -496,6 +560,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, | |||
496 | } | 560 | } |
497 | 561 | ||
498 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, | 562 | static int rsnd_ssi_fallback(struct rsnd_mod *mod, |
563 | struct rsnd_dai_stream *io, | ||
499 | struct rsnd_priv *priv) | 564 | struct rsnd_priv *priv) |
500 | { | 565 | { |
501 | struct device *dev = rsnd_priv_to_dev(priv); | 566 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -516,37 +581,39 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod, | |||
516 | } | 581 | } |
517 | 582 | ||
518 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, | 583 | static int rsnd_ssi_dma_start(struct rsnd_mod *mod, |
584 | struct rsnd_dai_stream *io, | ||
519 | struct rsnd_priv *priv) | 585 | struct rsnd_priv *priv) |
520 | { | 586 | { |
521 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 587 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
522 | 588 | ||
523 | rsnd_dma_start(dma); | 589 | rsnd_dma_start(io, dma); |
524 | 590 | ||
525 | rsnd_ssi_start(mod, priv); | 591 | rsnd_ssi_start(mod, io, priv); |
526 | 592 | ||
527 | return 0; | 593 | return 0; |
528 | } | 594 | } |
529 | 595 | ||
530 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, | 596 | static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, |
597 | struct rsnd_dai_stream *io, | ||
531 | struct rsnd_priv *priv) | 598 | struct rsnd_priv *priv) |
532 | { | 599 | { |
533 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 600 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
534 | 601 | ||
535 | rsnd_ssi_stop(mod, priv); | 602 | rsnd_ssi_stop(mod, io, priv); |
536 | 603 | ||
537 | rsnd_dma_stop(dma); | 604 | rsnd_dma_stop(io, dma); |
538 | 605 | ||
539 | return 0; | 606 | return 0; |
540 | } | 607 | } |
541 | 608 | ||
542 | static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_mod *mod) | 609 | static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io, |
610 | struct rsnd_mod *mod) | ||
543 | { | 611 | { |
544 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 612 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
545 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
546 | int is_play = rsnd_io_is_play(io); | 613 | int is_play = rsnd_io_is_play(io); |
547 | char *name; | 614 | char *name; |
548 | 615 | ||
549 | if (rsnd_ssi_use_busif(mod)) | 616 | if (rsnd_ssi_use_busif(io, mod)) |
550 | name = is_play ? "rxu" : "txu"; | 617 | name = is_play ? "rxu" : "txu"; |
551 | else | 618 | else |
552 | name = is_play ? "rx" : "tx"; | 619 | name = is_play ? "rx" : "tx"; |
@@ -565,6 +632,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | |||
565 | .start = rsnd_ssi_dma_start, | 632 | .start = rsnd_ssi_dma_start, |
566 | .stop = rsnd_ssi_dma_stop, | 633 | .stop = rsnd_ssi_dma_stop, |
567 | .fallback = rsnd_ssi_fallback, | 634 | .fallback = rsnd_ssi_fallback, |
635 | .hw_params = rsnd_ssi_hw_params, | ||
568 | }; | 636 | }; |
569 | 637 | ||
570 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) | 638 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) |
@@ -598,7 +666,7 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) | |||
598 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); | 666 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); |
599 | } | 667 | } |
600 | 668 | ||
601 | static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) | 669 | static void rsnd_ssi_parent_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) |
602 | { | 670 | { |
603 | if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) | 671 | if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) |
604 | return; | 672 | return; |
@@ -728,11 +796,11 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
728 | else if (rsnd_ssi_pio_available(ssi)) | 796 | else if (rsnd_ssi_pio_available(ssi)) |
729 | ops = &rsnd_ssi_pio_ops; | 797 | ops = &rsnd_ssi_pio_ops; |
730 | 798 | ||
731 | ret = rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i); | 799 | ret = rsnd_mod_init(priv, &ssi->mod, ops, clk, RSND_MOD_SSI, i); |
732 | if (ret) | 800 | if (ret) |
733 | return ret; | 801 | return ret; |
734 | 802 | ||
735 | rsnd_ssi_parent_clk_setup(priv, ssi); | 803 | rsnd_ssi_parent_setup(priv, ssi); |
736 | } | 804 | } |
737 | 805 | ||
738 | return 0; | 806 | return 0; |