diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-12-13 03:28:43 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-12-13 03:28:43 -0500 |
commit | 20aeeb356ba2e8daa99b5942c528ae2b3ea28433 (patch) | |
tree | d2cebc7039954851998d592123899f5627def7a9 /arch/arm/mach-shmobile/board-ap4evb.c | |
parent | 07a9e2b2fbdda631eeff54e4b8ebcaaea71be538 (diff) | |
parent | 5b84ba26a9672e615897234fa5efd3eea2d6b295 (diff) |
Merge branch 'topic/workq-update' into topic/asoc
Conflicts:
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8753.c
sound/soc/sh/fsi.c
sound/soc/soc-core.c
Diffstat (limited to 'arch/arm/mach-shmobile/board-ap4evb.c')
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 147 |
1 files changed, 111 insertions, 36 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 82c3204af899..e6bf1e114b10 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -567,38 +567,127 @@ static struct platform_device *qhd_devices[] __initdata = { | |||
567 | 567 | ||
568 | /* FSI */ | 568 | /* FSI */ |
569 | #define IRQ_FSI evt2irq(0x1840) | 569 | #define IRQ_FSI evt2irq(0x1840) |
570 | static int __fsi_set_rate(struct clk *clk, long rate, int enable) | ||
571 | { | ||
572 | int ret = 0; | ||
573 | |||
574 | if (rate <= 0) | ||
575 | return ret; | ||
576 | |||
577 | if (enable) { | ||
578 | ret = clk_set_rate(clk, rate); | ||
579 | if (0 == ret) | ||
580 | ret = clk_enable(clk); | ||
581 | } else { | ||
582 | clk_disable(clk); | ||
583 | } | ||
584 | |||
585 | return ret; | ||
586 | } | ||
587 | |||
588 | static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) | ||
589 | { | ||
590 | return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable); | ||
591 | } | ||
570 | 592 | ||
571 | static int fsi_set_rate(int is_porta, int rate) | 593 | static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable) |
594 | { | ||
595 | struct clk *fsia_ick; | ||
596 | struct clk *fsiack; | ||
597 | int ret = -EIO; | ||
598 | |||
599 | fsia_ick = clk_get(dev, "icka"); | ||
600 | if (IS_ERR(fsia_ick)) | ||
601 | return PTR_ERR(fsia_ick); | ||
602 | |||
603 | /* | ||
604 | * FSIACK is connected to AK4642, | ||
605 | * and use external clock pin from it. | ||
606 | * it is parent of fsia_ick now. | ||
607 | */ | ||
608 | fsiack = clk_get_parent(fsia_ick); | ||
609 | if (!fsiack) | ||
610 | goto fsia_ick_out; | ||
611 | |||
612 | /* | ||
613 | * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick | ||
614 | * | ||
615 | ** FIXME ** | ||
616 | * Because the freq_table of external clk (fsiack) are all 0, | ||
617 | * the return value of clk_round_rate became 0. | ||
618 | * So, it use __fsi_set_rate here. | ||
619 | */ | ||
620 | ret = __fsi_set_rate(fsiack, rate, enable); | ||
621 | if (ret < 0) | ||
622 | goto fsiack_out; | ||
623 | |||
624 | ret = __fsi_set_round_rate(fsia_ick, rate, enable); | ||
625 | if ((ret < 0) && enable) | ||
626 | __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */ | ||
627 | |||
628 | fsiack_out: | ||
629 | clk_put(fsiack); | ||
630 | |||
631 | fsia_ick_out: | ||
632 | clk_put(fsia_ick); | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) | ||
572 | { | 638 | { |
573 | struct clk *fsib_clk; | 639 | struct clk *fsib_clk; |
574 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; | 640 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; |
641 | long fsib_rate = 0; | ||
642 | long fdiv_rate = 0; | ||
643 | int ackmd_bpfmd; | ||
575 | int ret; | 644 | int ret; |
576 | 645 | ||
577 | /* set_rate is not needed if port A */ | ||
578 | if (is_porta) | ||
579 | return 0; | ||
580 | |||
581 | fsib_clk = clk_get(NULL, "fsib_clk"); | ||
582 | if (IS_ERR(fsib_clk)) | ||
583 | return -EINVAL; | ||
584 | |||
585 | switch (rate) { | 646 | switch (rate) { |
586 | case 44100: | 647 | case 44100: |
587 | clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 11283000)); | 648 | fsib_rate = rate * 256; |
588 | ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | 649 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; |
589 | break; | 650 | break; |
590 | case 48000: | 651 | case 48000: |
591 | clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000)); | 652 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ |
592 | clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000)); | 653 | fdiv_rate = rate * 256; |
593 | ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | 654 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; |
594 | break; | 655 | break; |
595 | default: | 656 | default: |
596 | pr_err("unsupported rate in FSI2 port B\n"); | 657 | pr_err("unsupported rate in FSI2 port B\n"); |
597 | ret = -EINVAL; | 658 | return -EINVAL; |
598 | break; | ||
599 | } | 659 | } |
600 | 660 | ||
661 | /* FSI B setting */ | ||
662 | fsib_clk = clk_get(dev, "ickb"); | ||
663 | if (IS_ERR(fsib_clk)) | ||
664 | return -EIO; | ||
665 | |||
666 | ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable); | ||
601 | clk_put(fsib_clk); | 667 | clk_put(fsib_clk); |
668 | if (ret < 0) | ||
669 | return ret; | ||
670 | |||
671 | /* FSI DIV setting */ | ||
672 | ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable); | ||
673 | if (ret < 0) { | ||
674 | /* disable FSI B */ | ||
675 | if (enable) | ||
676 | __fsi_set_round_rate(fsib_clk, fsib_rate, 0); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | return ackmd_bpfmd; | ||
681 | } | ||
682 | |||
683 | static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) | ||
684 | { | ||
685 | int ret; | ||
686 | |||
687 | if (is_porta) | ||
688 | ret = fsi_ak4642_set_rate(dev, rate, enable); | ||
689 | else | ||
690 | ret = fsi_hdmi_set_rate(dev, rate, enable); | ||
602 | 691 | ||
603 | return ret; | 692 | return ret; |
604 | } | 693 | } |
@@ -885,6 +974,11 @@ static int __init hdmi_init_pm_clock(void) | |||
885 | goto out; | 974 | goto out; |
886 | } | 975 | } |
887 | 976 | ||
977 | ret = clk_enable(&sh7372_pllc2_clk); | ||
978 | if (ret < 0) { | ||
979 | pr_err("Cannot enable pllc2 clock\n"); | ||
980 | goto out; | ||
981 | } | ||
888 | pr_debug("PLLC2 set frequency %lu\n", rate); | 982 | pr_debug("PLLC2 set frequency %lu\n", rate); |
889 | 983 | ||
890 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); | 984 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); |
@@ -901,23 +995,11 @@ out: | |||
901 | 995 | ||
902 | device_initcall(hdmi_init_pm_clock); | 996 | device_initcall(hdmi_init_pm_clock); |
903 | 997 | ||
904 | #define FSIACK_DUMMY_RATE 48000 | ||
905 | static int __init fsi_init_pm_clock(void) | 998 | static int __init fsi_init_pm_clock(void) |
906 | { | 999 | { |
907 | struct clk *fsia_ick; | 1000 | struct clk *fsia_ick; |
908 | int ret; | 1001 | int ret; |
909 | 1002 | ||
910 | /* | ||
911 | * FSIACK is connected to AK4642, | ||
912 | * and the rate is depend on playing sound rate. | ||
913 | * So, set dummy rate (= 48k) here | ||
914 | */ | ||
915 | ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE); | ||
916 | if (ret < 0) { | ||
917 | pr_err("Cannot set FSIACK dummy rate: %d\n", ret); | ||
918 | return ret; | ||
919 | } | ||
920 | |||
921 | fsia_ick = clk_get(&fsi_device.dev, "icka"); | 1003 | fsia_ick = clk_get(&fsi_device.dev, "icka"); |
922 | if (IS_ERR(fsia_ick)) { | 1004 | if (IS_ERR(fsia_ick)) { |
923 | ret = PTR_ERR(fsia_ick); | 1005 | ret = PTR_ERR(fsia_ick); |
@@ -926,16 +1008,9 @@ static int __init fsi_init_pm_clock(void) | |||
926 | } | 1008 | } |
927 | 1009 | ||
928 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); | 1010 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); |
929 | if (ret < 0) { | ||
930 | pr_err("Cannot set FSI-A parent: %d\n", ret); | ||
931 | goto out; | ||
932 | } | ||
933 | |||
934 | ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE); | ||
935 | if (ret < 0) | 1011 | if (ret < 0) |
936 | pr_err("Cannot set FSI-A rate: %d\n", ret); | 1012 | pr_err("Cannot set FSI-A parent: %d\n", ret); |
937 | 1013 | ||
938 | out: | ||
939 | clk_put(fsia_ick); | 1014 | clk_put(fsia_ick); |
940 | 1015 | ||
941 | return ret; | 1016 | return ret; |