diff options
author | Scott Ling <sl@opensource.wolfsonmicro.com> | 2012-11-07 11:53:18 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-11-09 06:44:31 -0500 |
commit | 3f5475df378cfcac51e9384153aef122555a60cb (patch) | |
tree | 442e5c1c19bd70cec8a93815804c3f3afe1563bd /sound/soc/codecs/wm0010.c | |
parent | 8f7d52affeb8341cbc602209b6f35eedb410d3ee (diff) |
ASoC: wm0010: Split out the stage2 load from the boot function
Signed-off-by: Scott Ling <sl@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm0010.c')
-rw-r--r-- | sound/soc/codecs/wm0010.c | 129 |
1 files changed, 79 insertions, 50 deletions
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 7576330044ba..4b68ea86d7cb 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -477,6 +477,82 @@ abort: | |||
477 | return ret; | 477 | return ret; |
478 | } | 478 | } |
479 | 479 | ||
480 | static int wm0010_stage2_load(struct snd_soc_codec *codec) | ||
481 | { | ||
482 | struct spi_device *spi = to_spi_device(codec->dev); | ||
483 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
484 | const struct firmware *fw; | ||
485 | struct spi_message m; | ||
486 | struct spi_transfer t; | ||
487 | u32 *img; | ||
488 | u8 *out; | ||
489 | int i; | ||
490 | int ret = 0; | ||
491 | |||
492 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); | ||
493 | if (ret != 0) { | ||
494 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", | ||
495 | ret); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); | ||
500 | |||
501 | /* Copy to local buffer first as vmalloc causes problems for dma */ | ||
502 | img = kzalloc(fw->size, GFP_KERNEL); | ||
503 | if (!img) { | ||
504 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
505 | ret = -ENOMEM; | ||
506 | goto abort2; | ||
507 | } | ||
508 | |||
509 | out = kzalloc(fw->size, GFP_KERNEL); | ||
510 | if (!out) { | ||
511 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
512 | ret = -ENOMEM; | ||
513 | goto abort1; | ||
514 | } | ||
515 | |||
516 | memcpy(img, &fw->data[0], fw->size); | ||
517 | |||
518 | spi_message_init(&m); | ||
519 | memset(&t, 0, sizeof(t)); | ||
520 | t.rx_buf = out; | ||
521 | t.tx_buf = img; | ||
522 | t.len = fw->size; | ||
523 | t.bits_per_word = 8; | ||
524 | t.speed_hz = wm0010->sysclk / 10; | ||
525 | spi_message_add_tail(&t, &m); | ||
526 | |||
527 | dev_dbg(codec->dev, "Starting initial download at %dHz\n", | ||
528 | t.speed_hz); | ||
529 | |||
530 | ret = spi_sync(spi, &m); | ||
531 | if (ret != 0) { | ||
532 | dev_err(codec->dev, "Initial download failed: %d\n", ret); | ||
533 | goto abort; | ||
534 | } | ||
535 | |||
536 | /* Look for errors from the boot ROM */ | ||
537 | for (i = 0; i < fw->size; i++) { | ||
538 | if (out[i] != 0x55) { | ||
539 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", | ||
540 | out[i], i); | ||
541 | wm0010_mark_boot_failure(wm0010); | ||
542 | ret = -EBUSY; | ||
543 | goto abort; | ||
544 | } | ||
545 | } | ||
546 | abort: | ||
547 | kfree(out); | ||
548 | abort1: | ||
549 | kfree(img); | ||
550 | abort2: | ||
551 | release_firmware(fw); | ||
552 | |||
553 | return ret; | ||
554 | } | ||
555 | |||
480 | static int wm0010_boot(struct snd_soc_codec *codec) | 556 | static int wm0010_boot(struct snd_soc_codec *codec) |
481 | { | 557 | { |
482 | struct spi_device *spi = to_spi_device(codec->dev); | 558 | struct spi_device *spi = to_spi_device(codec->dev); |
@@ -487,10 +563,9 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
487 | struct spi_message m; | 563 | struct spi_message m; |
488 | struct spi_transfer t; | 564 | struct spi_transfer t; |
489 | struct dfw_pllrec pll_rec; | 565 | struct dfw_pllrec pll_rec; |
490 | u32 *img, *p; | 566 | u32 *p, len; |
491 | u64 *img_swap; | 567 | u64 *img_swap; |
492 | u8 *out; | 568 | u8 *out; |
493 | u32 len; | ||
494 | int i; | 569 | int i; |
495 | 570 | ||
496 | spin_lock_irqsave(&wm0010->irq_lock, flags); | 571 | spin_lock_irqsave(&wm0010->irq_lock, flags); |
@@ -546,55 +621,9 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
546 | wm0010->state = WM0010_BOOTROM; | 621 | wm0010->state = WM0010_BOOTROM; |
547 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | 622 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); |
548 | 623 | ||
549 | dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); | 624 | ret = wm0010_stage2_load(codec); |
550 | 625 | if (ret) | |
551 | /* Copy to local buffer first as vmalloc causes problems for dma */ | ||
552 | img = kzalloc(fw->size, GFP_KERNEL); | ||
553 | if (!img) { | ||
554 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
555 | goto abort; | ||
556 | } | ||
557 | |||
558 | out = kzalloc(fw->size, GFP_KERNEL); | ||
559 | if (!out) { | ||
560 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
561 | goto abort; | ||
562 | } | ||
563 | |||
564 | memcpy(img, &fw->data[0], fw->size); | ||
565 | |||
566 | spi_message_init(&m); | ||
567 | memset(&t, 0, sizeof(t)); | ||
568 | t.rx_buf = out; | ||
569 | t.tx_buf = img; | ||
570 | t.len = fw->size; | ||
571 | t.bits_per_word = 8; | ||
572 | t.speed_hz = wm0010->sysclk / 10; | ||
573 | spi_message_add_tail(&t, &m); | ||
574 | |||
575 | dev_dbg(codec->dev, "Starting initial download at %dHz\n", | ||
576 | t.speed_hz); | ||
577 | |||
578 | ret = spi_sync(spi, &m); | ||
579 | if (ret != 0) { | ||
580 | dev_err(codec->dev, "Initial download failed: %d\n", ret); | ||
581 | goto abort; | 626 | goto abort; |
582 | } | ||
583 | |||
584 | /* Look for errors from the boot ROM */ | ||
585 | for (i = 0; i < fw->size; i++) { | ||
586 | if (out[i] != 0x55) { | ||
587 | ret = -EBUSY; | ||
588 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", | ||
589 | out[i], i); | ||
590 | wm0010_mark_boot_failure(wm0010); | ||
591 | goto abort; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | release_firmware(fw); | ||
596 | kfree(img); | ||
597 | kfree(out); | ||
598 | 627 | ||
599 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | 628 | if (!wait_for_completion_timeout(&wm0010->boot_completion, |
600 | msecs_to_jiffies(10))) | 629 | msecs_to_jiffies(10))) |