diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-12-21 22:56:10 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-12-21 22:56:10 -0500 |
commit | 7ccbefe07ea0a3570e44d1ec13a307552ee4dadd (patch) | |
tree | ba0299694a9f3940f289b6a29cadab853906e3d2 /arch/arm/mach-shmobile/board-ap4evb.c | |
parent | 623eb15647fc35c5a8cd38985d5958240eb072c1 (diff) | |
parent | 90a8a73c06cc32b609a880d48449d7083327e11a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
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 9add606021f4..a054f0d450d8 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -572,38 +572,127 @@ static struct platform_device *qhd_devices[] __initdata = { | |||
572 | 572 | ||
573 | /* FSI */ | 573 | /* FSI */ |
574 | #define IRQ_FSI evt2irq(0x1840) | 574 | #define IRQ_FSI evt2irq(0x1840) |
575 | static int __fsi_set_rate(struct clk *clk, long rate, int enable) | ||
576 | { | ||
577 | int ret = 0; | ||
578 | |||
579 | if (rate <= 0) | ||
580 | return ret; | ||
581 | |||
582 | if (enable) { | ||
583 | ret = clk_set_rate(clk, rate); | ||
584 | if (0 == ret) | ||
585 | ret = clk_enable(clk); | ||
586 | } else { | ||
587 | clk_disable(clk); | ||
588 | } | ||
589 | |||
590 | return ret; | ||
591 | } | ||
592 | |||
593 | static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) | ||
594 | { | ||
595 | return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable); | ||
596 | } | ||
575 | 597 | ||
576 | static int fsi_set_rate(int is_porta, int rate) | 598 | static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable) |
599 | { | ||
600 | struct clk *fsia_ick; | ||
601 | struct clk *fsiack; | ||
602 | int ret = -EIO; | ||
603 | |||
604 | fsia_ick = clk_get(dev, "icka"); | ||
605 | if (IS_ERR(fsia_ick)) | ||
606 | return PTR_ERR(fsia_ick); | ||
607 | |||
608 | /* | ||
609 | * FSIACK is connected to AK4642, | ||
610 | * and use external clock pin from it. | ||
611 | * it is parent of fsia_ick now. | ||
612 | */ | ||
613 | fsiack = clk_get_parent(fsia_ick); | ||
614 | if (!fsiack) | ||
615 | goto fsia_ick_out; | ||
616 | |||
617 | /* | ||
618 | * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick | ||
619 | * | ||
620 | ** FIXME ** | ||
621 | * Because the freq_table of external clk (fsiack) are all 0, | ||
622 | * the return value of clk_round_rate became 0. | ||
623 | * So, it use __fsi_set_rate here. | ||
624 | */ | ||
625 | ret = __fsi_set_rate(fsiack, rate, enable); | ||
626 | if (ret < 0) | ||
627 | goto fsiack_out; | ||
628 | |||
629 | ret = __fsi_set_round_rate(fsia_ick, rate, enable); | ||
630 | if ((ret < 0) && enable) | ||
631 | __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */ | ||
632 | |||
633 | fsiack_out: | ||
634 | clk_put(fsiack); | ||
635 | |||
636 | fsia_ick_out: | ||
637 | clk_put(fsia_ick); | ||
638 | |||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) | ||
577 | { | 643 | { |
578 | struct clk *fsib_clk; | 644 | struct clk *fsib_clk; |
579 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; | 645 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; |
646 | long fsib_rate = 0; | ||
647 | long fdiv_rate = 0; | ||
648 | int ackmd_bpfmd; | ||
580 | int ret; | 649 | int ret; |
581 | 650 | ||
582 | /* set_rate is not needed if port A */ | ||
583 | if (is_porta) | ||
584 | return 0; | ||
585 | |||
586 | fsib_clk = clk_get(NULL, "fsib_clk"); | ||
587 | if (IS_ERR(fsib_clk)) | ||
588 | return -EINVAL; | ||
589 | |||
590 | switch (rate) { | 651 | switch (rate) { |
591 | case 44100: | 652 | case 44100: |
592 | clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 11283000)); | 653 | fsib_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 | case 48000: | 656 | case 48000: |
596 | clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000)); | 657 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ |
597 | clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000)); | 658 | fdiv_rate = rate * 256; |
598 | ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | 659 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; |
599 | break; | 660 | break; |
600 | default: | 661 | default: |
601 | pr_err("unsupported rate in FSI2 port B\n"); | 662 | pr_err("unsupported rate in FSI2 port B\n"); |
602 | ret = -EINVAL; | 663 | return -EINVAL; |
603 | break; | ||
604 | } | 664 | } |
605 | 665 | ||
666 | /* FSI B setting */ | ||
667 | fsib_clk = clk_get(dev, "ickb"); | ||
668 | if (IS_ERR(fsib_clk)) | ||
669 | return -EIO; | ||
670 | |||
671 | ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable); | ||
606 | clk_put(fsib_clk); | 672 | clk_put(fsib_clk); |
673 | if (ret < 0) | ||
674 | return ret; | ||
675 | |||
676 | /* FSI DIV setting */ | ||
677 | ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable); | ||
678 | if (ret < 0) { | ||
679 | /* disable FSI B */ | ||
680 | if (enable) | ||
681 | __fsi_set_round_rate(fsib_clk, fsib_rate, 0); | ||
682 | return ret; | ||
683 | } | ||
684 | |||
685 | return ackmd_bpfmd; | ||
686 | } | ||
687 | |||
688 | static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) | ||
689 | { | ||
690 | int ret; | ||
691 | |||
692 | if (is_porta) | ||
693 | ret = fsi_ak4642_set_rate(dev, rate, enable); | ||
694 | else | ||
695 | ret = fsi_hdmi_set_rate(dev, rate, enable); | ||
607 | 696 | ||
608 | return ret; | 697 | return ret; |
609 | } | 698 | } |
@@ -909,6 +998,11 @@ static int __init hdmi_init_pm_clock(void) | |||
909 | goto out; | 998 | goto out; |
910 | } | 999 | } |
911 | 1000 | ||
1001 | ret = clk_enable(&sh7372_pllc2_clk); | ||
1002 | if (ret < 0) { | ||
1003 | pr_err("Cannot enable pllc2 clock\n"); | ||
1004 | goto out; | ||
1005 | } | ||
912 | pr_debug("PLLC2 set frequency %lu\n", rate); | 1006 | pr_debug("PLLC2 set frequency %lu\n", rate); |
913 | 1007 | ||
914 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); | 1008 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); |
@@ -925,23 +1019,11 @@ out: | |||
925 | 1019 | ||
926 | device_initcall(hdmi_init_pm_clock); | 1020 | device_initcall(hdmi_init_pm_clock); |
927 | 1021 | ||
928 | #define FSIACK_DUMMY_RATE 48000 | ||
929 | static int __init fsi_init_pm_clock(void) | 1022 | static int __init fsi_init_pm_clock(void) |
930 | { | 1023 | { |
931 | struct clk *fsia_ick; | 1024 | struct clk *fsia_ick; |
932 | int ret; | 1025 | int ret; |
933 | 1026 | ||
934 | /* | ||
935 | * FSIACK is connected to AK4642, | ||
936 | * and the rate is depend on playing sound rate. | ||
937 | * So, set dummy rate (= 48k) here | ||
938 | */ | ||
939 | ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE); | ||
940 | if (ret < 0) { | ||
941 | pr_err("Cannot set FSIACK dummy rate: %d\n", ret); | ||
942 | return ret; | ||
943 | } | ||
944 | |||
945 | fsia_ick = clk_get(&fsi_device.dev, "icka"); | 1027 | fsia_ick = clk_get(&fsi_device.dev, "icka"); |
946 | if (IS_ERR(fsia_ick)) { | 1028 | if (IS_ERR(fsia_ick)) { |
947 | ret = PTR_ERR(fsia_ick); | 1029 | ret = PTR_ERR(fsia_ick); |
@@ -950,16 +1032,9 @@ static int __init fsi_init_pm_clock(void) | |||
950 | } | 1032 | } |
951 | 1033 | ||
952 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); | 1034 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); |
953 | if (ret < 0) { | ||
954 | pr_err("Cannot set FSI-A parent: %d\n", ret); | ||
955 | goto out; | ||
956 | } | ||
957 | |||
958 | ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE); | ||
959 | if (ret < 0) | 1035 | if (ret < 0) |
960 | pr_err("Cannot set FSI-A rate: %d\n", ret); | 1036 | pr_err("Cannot set FSI-A parent: %d\n", ret); |
961 | 1037 | ||
962 | out: | ||
963 | clk_put(fsia_ick); | 1038 | clk_put(fsia_ick); |
964 | 1039 | ||
965 | return ret; | 1040 | return ret; |