diff options
| -rw-r--r-- | arch/arm/configs/marzen_defconfig | 14 | ||||
| -rw-r--r-- | arch/arm/mach-shmobile/Kconfig | 2 | ||||
| -rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 139 | ||||
| -rw-r--r-- | arch/arm/mach-shmobile/board-armadillo800eva.c | 38 | ||||
| -rw-r--r-- | arch/arm/mach-shmobile/board-mackerel.c | 80 | ||||
| -rw-r--r-- | arch/arm/mach-shmobile/board-marzen.c | 186 | ||||
| -rw-r--r-- | include/sound/sh_fsi.h | 6 | ||||
| -rw-r--r-- | sound/soc/sh/fsi.c | 441 |
8 files changed, 617 insertions, 289 deletions
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig index 5b8215f424c5..728a43c446f8 100644 --- a/arch/arm/configs/marzen_defconfig +++ b/arch/arm/configs/marzen_defconfig | |||
| @@ -47,6 +47,8 @@ CONFIG_DEVTMPFS_MOUNT=y | |||
| 47 | # CONFIG_STANDALONE is not set | 47 | # CONFIG_STANDALONE is not set |
| 48 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | 48 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set |
| 49 | # CONFIG_FW_LOADER is not set | 49 | # CONFIG_FW_LOADER is not set |
| 50 | CONFIG_SCSI=y | ||
| 51 | CONFIG_BLK_DEV_SD=y | ||
| 50 | CONFIG_NETDEVICES=y | 52 | CONFIG_NETDEVICES=y |
| 51 | # CONFIG_NET_VENDOR_BROADCOM is not set | 53 | # CONFIG_NET_VENDOR_BROADCOM is not set |
| 52 | # CONFIG_NET_VENDOR_FARADAY is not set | 54 | # CONFIG_NET_VENDOR_FARADAY is not set |
| @@ -59,9 +61,8 @@ CONFIG_SMSC911X=y | |||
| 59 | # CONFIG_NET_VENDOR_STMICRO is not set | 61 | # CONFIG_NET_VENDOR_STMICRO is not set |
| 60 | # CONFIG_WLAN is not set | 62 | # CONFIG_WLAN is not set |
| 61 | # CONFIG_INPUT_MOUSEDEV is not set | 63 | # CONFIG_INPUT_MOUSEDEV is not set |
| 62 | # CONFIG_INPUT_KEYBOARD is not set | 64 | CONFIG_INPUT_EVDEV=y |
| 63 | # CONFIG_INPUT_MOUSE is not set | 65 | # CONFIG_INPUT_MOUSE is not set |
| 64 | # CONFIG_SERIO is not set | ||
| 65 | # CONFIG_VT is not set | 66 | # CONFIG_VT is not set |
| 66 | # CONFIG_LEGACY_PTYS is not set | 67 | # CONFIG_LEGACY_PTYS is not set |
| 67 | # CONFIG_DEVKMEM is not set | 68 | # CONFIG_DEVKMEM is not set |
| @@ -78,9 +79,16 @@ CONFIG_GPIO_SYSFS=y | |||
| 78 | CONFIG_THERMAL=y | 79 | CONFIG_THERMAL=y |
| 79 | CONFIG_RCAR_THERMAL=y | 80 | CONFIG_RCAR_THERMAL=y |
| 80 | CONFIG_SSB=y | 81 | CONFIG_SSB=y |
| 81 | # CONFIG_USB_SUPPORT is not set | 82 | CONFIG_USB=y |
| 83 | CONFIG_USB_RCAR_PHY=y | ||
| 82 | CONFIG_MMC=y | 84 | CONFIG_MMC=y |
| 83 | CONFIG_MMC_SDHI=y | 85 | CONFIG_MMC_SDHI=y |
| 86 | CONFIG_USB=y | ||
| 87 | CONFIG_USB_EHCI_HCD=y | ||
| 88 | CONFIG_USB_OHCI_HCD=y | ||
| 89 | CONFIG_USB_OHCI_HCD_PLATFORM=y | ||
| 90 | CONFIG_USB_EHCI_HCD_PLATFORM=y | ||
| 91 | CONFIG_USB_STORAGE=y | ||
| 84 | CONFIG_UIO=y | 92 | CONFIG_UIO=y |
| 85 | CONFIG_UIO_PDRV_GENIRQ=y | 93 | CONFIG_UIO_PDRV_GENIRQ=y |
| 86 | # CONFIG_IOMMU_SUPPORT is not set | 94 | # CONFIG_IOMMU_SUPPORT is not set |
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 4eddca14ae07..9255546e7bf6 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
| @@ -29,6 +29,8 @@ config ARCH_R8A7779 | |||
| 29 | select ARM_GIC | 29 | select ARM_GIC |
| 30 | select CPU_V7 | 30 | select CPU_V7 |
| 31 | select SH_CLK_CPG | 31 | select SH_CLK_CPG |
| 32 | select USB_ARCH_HAS_EHCI | ||
| 33 | select USB_ARCH_HAS_OHCI | ||
| 32 | 34 | ||
| 33 | config ARCH_EMEV2 | 35 | config ARCH_EMEV2 |
| 34 | bool "Emma Mobile EV2" | 36 | bool "Emma Mobile EV2" |
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index cefdd030361d..40657854e3ad 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
| @@ -658,133 +658,16 @@ static struct platform_device lcdc_device = { | |||
| 658 | 658 | ||
| 659 | /* FSI */ | 659 | /* FSI */ |
| 660 | #define IRQ_FSI evt2irq(0x1840) | 660 | #define IRQ_FSI evt2irq(0x1840) |
| 661 | static int __fsi_set_rate(struct clk *clk, long rate, int enable) | ||
| 662 | { | ||
| 663 | int ret = 0; | ||
| 664 | |||
| 665 | if (rate <= 0) | ||
| 666 | return ret; | ||
| 667 | |||
| 668 | if (enable) { | ||
| 669 | ret = clk_set_rate(clk, rate); | ||
| 670 | if (0 == ret) | ||
| 671 | ret = clk_enable(clk); | ||
| 672 | } else { | ||
| 673 | clk_disable(clk); | ||
| 674 | } | ||
| 675 | |||
| 676 | return ret; | ||
| 677 | } | ||
| 678 | |||
| 679 | static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) | ||
| 680 | { | ||
| 681 | return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable); | ||
| 682 | } | ||
| 683 | |||
| 684 | static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable) | ||
| 685 | { | ||
| 686 | struct clk *fsia_ick; | ||
| 687 | struct clk *fsiack; | ||
| 688 | int ret = -EIO; | ||
| 689 | |||
| 690 | fsia_ick = clk_get(dev, "icka"); | ||
| 691 | if (IS_ERR(fsia_ick)) | ||
| 692 | return PTR_ERR(fsia_ick); | ||
| 693 | |||
| 694 | /* | ||
| 695 | * FSIACK is connected to AK4642, | ||
| 696 | * and use external clock pin from it. | ||
| 697 | * it is parent of fsia_ick now. | ||
| 698 | */ | ||
| 699 | fsiack = clk_get_parent(fsia_ick); | ||
| 700 | if (!fsiack) | ||
| 701 | goto fsia_ick_out; | ||
| 702 | |||
| 703 | /* | ||
| 704 | * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick | ||
| 705 | * | ||
| 706 | ** FIXME ** | ||
| 707 | * Because the freq_table of external clk (fsiack) are all 0, | ||
| 708 | * the return value of clk_round_rate became 0. | ||
| 709 | * So, it use __fsi_set_rate here. | ||
| 710 | */ | ||
| 711 | ret = __fsi_set_rate(fsiack, rate, enable); | ||
| 712 | if (ret < 0) | ||
| 713 | goto fsiack_out; | ||
| 714 | |||
| 715 | ret = __fsi_set_round_rate(fsia_ick, rate, enable); | ||
| 716 | if ((ret < 0) && enable) | ||
| 717 | __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */ | ||
| 718 | |||
| 719 | fsiack_out: | ||
| 720 | clk_put(fsiack); | ||
| 721 | |||
| 722 | fsia_ick_out: | ||
| 723 | clk_put(fsia_ick); | ||
| 724 | |||
| 725 | return 0; | ||
| 726 | } | ||
| 727 | |||
| 728 | static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) | ||
| 729 | { | ||
| 730 | struct clk *fsib_clk; | ||
| 731 | struct clk *fdiv_clk = clk_get(NULL, "fsidivb"); | ||
| 732 | long fsib_rate = 0; | ||
| 733 | long fdiv_rate = 0; | ||
| 734 | int ackmd_bpfmd; | ||
| 735 | int ret; | ||
| 736 | |||
| 737 | switch (rate) { | ||
| 738 | case 44100: | ||
| 739 | fsib_rate = rate * 256; | ||
| 740 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 741 | break; | ||
| 742 | case 48000: | ||
| 743 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ | ||
| 744 | fdiv_rate = rate * 256; | ||
| 745 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 746 | break; | ||
| 747 | default: | ||
| 748 | pr_err("unsupported rate in FSI2 port B\n"); | ||
| 749 | return -EINVAL; | ||
| 750 | } | ||
| 751 | |||
| 752 | /* FSI B setting */ | ||
| 753 | fsib_clk = clk_get(dev, "ickb"); | ||
| 754 | if (IS_ERR(fsib_clk)) | ||
| 755 | return -EIO; | ||
| 756 | |||
| 757 | ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable); | ||
| 758 | if (ret < 0) | ||
| 759 | goto fsi_set_rate_end; | ||
| 760 | |||
| 761 | /* FSI DIV setting */ | ||
| 762 | ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable); | ||
| 763 | if (ret < 0) { | ||
| 764 | /* disable FSI B */ | ||
| 765 | if (enable) | ||
| 766 | __fsi_set_round_rate(fsib_clk, fsib_rate, 0); | ||
| 767 | goto fsi_set_rate_end; | ||
| 768 | } | ||
| 769 | |||
| 770 | ret = ackmd_bpfmd; | ||
| 771 | |||
| 772 | fsi_set_rate_end: | ||
| 773 | clk_put(fsib_clk); | ||
| 774 | return ret; | ||
| 775 | } | ||
| 776 | |||
| 777 | static struct sh_fsi_platform_info fsi_info = { | 661 | static struct sh_fsi_platform_info fsi_info = { |
| 778 | .port_a = { | 662 | .port_a = { |
| 779 | .flags = SH_FSI_BRS_INV, | 663 | .flags = SH_FSI_BRS_INV, |
| 780 | .set_rate = fsi_ak4642_set_rate, | ||
| 781 | }, | 664 | }, |
| 782 | .port_b = { | 665 | .port_b = { |
| 783 | .flags = SH_FSI_BRS_INV | | 666 | .flags = SH_FSI_BRS_INV | |
| 784 | SH_FSI_BRM_INV | | 667 | SH_FSI_BRM_INV | |
| 785 | SH_FSI_LRS_INV | | 668 | SH_FSI_LRS_INV | |
| 669 | SH_FSI_CLK_CPG | | ||
| 786 | SH_FSI_FMT_SPDIF, | 670 | SH_FSI_FMT_SPDIF, |
| 787 | .set_rate = fsi_hdmi_set_rate, | ||
| 788 | }, | 671 | }, |
| 789 | }; | 672 | }; |
| 790 | 673 | ||
| @@ -1144,25 +1027,6 @@ out: | |||
| 1144 | clk_put(hdmi_ick); | 1027 | clk_put(hdmi_ick); |
| 1145 | } | 1028 | } |
| 1146 | 1029 | ||
| 1147 | static void __init fsi_init_pm_clock(void) | ||
| 1148 | { | ||
| 1149 | struct clk *fsia_ick; | ||
| 1150 | int ret; | ||
| 1151 | |||
| 1152 | fsia_ick = clk_get(&fsi_device.dev, "icka"); | ||
| 1153 | if (IS_ERR(fsia_ick)) { | ||
| 1154 | ret = PTR_ERR(fsia_ick); | ||
| 1155 | pr_err("Cannot get FSI ICK: %d\n", ret); | ||
| 1156 | return; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); | ||
| 1160 | if (ret < 0) | ||
| 1161 | pr_err("Cannot set FSI-A parent: %d\n", ret); | ||
| 1162 | |||
| 1163 | clk_put(fsia_ick); | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | /* TouchScreen */ | 1030 | /* TouchScreen */ |
| 1167 | #ifdef CONFIG_AP4EVB_QHD | 1031 | #ifdef CONFIG_AP4EVB_QHD |
| 1168 | # define GPIO_TSC_IRQ GPIO_FN_IRQ28_123 | 1032 | # define GPIO_TSC_IRQ GPIO_FN_IRQ28_123 |
| @@ -1476,7 +1340,6 @@ static void __init ap4evb_init(void) | |||
| 1476 | ARRAY_SIZE(domain_devices)); | 1340 | ARRAY_SIZE(domain_devices)); |
| 1477 | 1341 | ||
| 1478 | hdmi_init_pm_clock(); | 1342 | hdmi_init_pm_clock(); |
| 1479 | fsi_init_pm_clock(); | ||
| 1480 | sh7372_pm_init(); | 1343 | sh7372_pm_init(); |
| 1481 | pm_clk_add(&fsi_device.dev, "spu2"); | 1344 | pm_clk_add(&fsi_device.dev, "spu2"); |
| 1482 | pm_clk_add(&lcdc1_device.dev, "hdmi"); | 1345 | pm_clk_add(&lcdc1_device.dev, "hdmi"); |
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 499e6e376666..5353adf6b828 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c | |||
| @@ -768,32 +768,6 @@ static struct platform_device ceu0_device = { | |||
| 768 | }; | 768 | }; |
| 769 | 769 | ||
| 770 | /* FSI */ | 770 | /* FSI */ |
| 771 | static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) | ||
| 772 | { | ||
| 773 | struct clk *fsib; | ||
| 774 | int ret; | ||
| 775 | |||
| 776 | /* it support 48KHz only */ | ||
| 777 | if (48000 != rate) | ||
| 778 | return -EINVAL; | ||
| 779 | |||
| 780 | fsib = clk_get(dev, "ickb"); | ||
| 781 | if (IS_ERR(fsib)) | ||
| 782 | return -EINVAL; | ||
| 783 | |||
| 784 | if (enable) { | ||
| 785 | ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 786 | clk_enable(fsib); | ||
| 787 | } else { | ||
| 788 | ret = 0; | ||
| 789 | clk_disable(fsib); | ||
| 790 | } | ||
| 791 | |||
| 792 | clk_put(fsib); | ||
| 793 | |||
| 794 | return ret; | ||
| 795 | } | ||
| 796 | |||
| 797 | static struct sh_fsi_platform_info fsi_info = { | 771 | static struct sh_fsi_platform_info fsi_info = { |
| 798 | /* FSI-WM8978 */ | 772 | /* FSI-WM8978 */ |
| 799 | .port_a = { | 773 | .port_a = { |
| @@ -802,8 +776,8 @@ static struct sh_fsi_platform_info fsi_info = { | |||
| 802 | /* FSI-HDMI */ | 776 | /* FSI-HDMI */ |
| 803 | .port_b = { | 777 | .port_b = { |
| 804 | .flags = SH_FSI_FMT_SPDIF | | 778 | .flags = SH_FSI_FMT_SPDIF | |
| 805 | SH_FSI_ENABLE_STREAM_MODE, | 779 | SH_FSI_ENABLE_STREAM_MODE | |
| 806 | .set_rate = fsi_hdmi_set_rate, | 780 | SH_FSI_CLK_CPG, |
| 807 | .tx_id = SHDMA_SLAVE_FSIB_TX, | 781 | .tx_id = SHDMA_SLAVE_FSIB_TX, |
| 808 | } | 782 | } |
| 809 | }; | 783 | }; |
| @@ -938,13 +912,11 @@ static void __init eva_clock_init(void) | |||
| 938 | struct clk *xtal1 = clk_get(NULL, "extal1"); | 912 | struct clk *xtal1 = clk_get(NULL, "extal1"); |
| 939 | struct clk *usb24s = clk_get(NULL, "usb24s"); | 913 | struct clk *usb24s = clk_get(NULL, "usb24s"); |
| 940 | struct clk *fsibck = clk_get(NULL, "fsibck"); | 914 | struct clk *fsibck = clk_get(NULL, "fsibck"); |
| 941 | struct clk *fsib = clk_get(&fsi_device.dev, "ickb"); | ||
| 942 | 915 | ||
| 943 | if (IS_ERR(system) || | 916 | if (IS_ERR(system) || |
| 944 | IS_ERR(xtal1) || | 917 | IS_ERR(xtal1) || |
| 945 | IS_ERR(usb24s) || | 918 | IS_ERR(usb24s) || |
| 946 | IS_ERR(fsibck) || | 919 | IS_ERR(fsibck)) { |
| 947 | IS_ERR(fsib)) { | ||
| 948 | pr_err("armadillo800eva board clock init failed\n"); | 920 | pr_err("armadillo800eva board clock init failed\n"); |
| 949 | goto clock_error; | 921 | goto clock_error; |
| 950 | } | 922 | } |
| @@ -956,9 +928,7 @@ static void __init eva_clock_init(void) | |||
| 956 | clk_set_parent(usb24s, system); | 928 | clk_set_parent(usb24s, system); |
| 957 | 929 | ||
| 958 | /* FSIBCK is 12.288MHz, and it is parent of FSI-B */ | 930 | /* FSIBCK is 12.288MHz, and it is parent of FSI-B */ |
| 959 | clk_set_parent(fsib, fsibck); | ||
| 960 | clk_set_rate(fsibck, 12288000); | 931 | clk_set_rate(fsibck, 12288000); |
| 961 | clk_set_rate(fsib, 12288000); | ||
| 962 | 932 | ||
| 963 | clock_error: | 933 | clock_error: |
| 964 | if (!IS_ERR(system)) | 934 | if (!IS_ERR(system)) |
| @@ -969,8 +939,6 @@ clock_error: | |||
| 969 | clk_put(usb24s); | 939 | clk_put(usb24s); |
| 970 | if (!IS_ERR(fsibck)) | 940 | if (!IS_ERR(fsibck)) |
| 971 | clk_put(fsibck); | 941 | clk_put(fsibck); |
| 972 | if (!IS_ERR(fsib)) | ||
| 973 | clk_put(fsib); | ||
| 974 | } | 942 | } |
| 975 | 943 | ||
| 976 | /* | 944 | /* |
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index f274252e4705..3f56e70795b7 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
| @@ -816,6 +816,8 @@ static struct platform_device usbhs1_device = { | |||
| 816 | .id = 1, | 816 | .id = 1, |
| 817 | .dev = { | 817 | .dev = { |
| 818 | .platform_data = &usbhs1_private.info, | 818 | .platform_data = &usbhs1_private.info, |
| 819 | .dma_mask = &usbhs1_device.dev.coherent_dma_mask, | ||
| 820 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 819 | }, | 821 | }, |
| 820 | .num_resources = ARRAY_SIZE(usbhs1_resources), | 822 | .num_resources = ARRAY_SIZE(usbhs1_resources), |
| 821 | .resource = usbhs1_resources, | 823 | .resource = usbhs1_resources, |
| @@ -860,76 +862,6 @@ static struct platform_device leds_device = { | |||
| 860 | 862 | ||
| 861 | /* FSI */ | 863 | /* FSI */ |
| 862 | #define IRQ_FSI evt2irq(0x1840) | 864 | #define IRQ_FSI evt2irq(0x1840) |
| 863 | static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) | ||
| 864 | { | ||
| 865 | int ret; | ||
| 866 | |||
| 867 | if (rate <= 0) | ||
| 868 | return 0; | ||
| 869 | |||
| 870 | if (!enable) { | ||
| 871 | clk_disable(clk); | ||
| 872 | return 0; | ||
| 873 | } | ||
| 874 | |||
| 875 | ret = clk_set_rate(clk, clk_round_rate(clk, rate)); | ||
| 876 | if (ret < 0) | ||
| 877 | return ret; | ||
| 878 | |||
| 879 | return clk_enable(clk); | ||
| 880 | } | ||
| 881 | |||
| 882 | static int fsi_b_set_rate(struct device *dev, int rate, int enable) | ||
| 883 | { | ||
| 884 | struct clk *fsib_clk; | ||
| 885 | struct clk *fdiv_clk = clk_get(NULL, "fsidivb"); | ||
| 886 | long fsib_rate = 0; | ||
| 887 | long fdiv_rate = 0; | ||
| 888 | int ackmd_bpfmd; | ||
| 889 | int ret; | ||
| 890 | |||
| 891 | /* clock start */ | ||
| 892 | switch (rate) { | ||
| 893 | case 44100: | ||
| 894 | fsib_rate = rate * 256; | ||
| 895 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 896 | break; | ||
| 897 | case 48000: | ||
| 898 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ | ||
| 899 | fdiv_rate = rate * 256; | ||
| 900 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 901 | break; | ||
| 902 | default: | ||
| 903 | pr_err("unsupported rate in FSI2 port B\n"); | ||
| 904 | return -EINVAL; | ||
| 905 | } | ||
| 906 | |||
| 907 | /* FSI B setting */ | ||
| 908 | fsib_clk = clk_get(dev, "ickb"); | ||
| 909 | if (IS_ERR(fsib_clk)) | ||
| 910 | return -EIO; | ||
| 911 | |||
| 912 | /* fsib */ | ||
| 913 | ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable); | ||
| 914 | if (ret < 0) | ||
| 915 | goto fsi_set_rate_end; | ||
| 916 | |||
| 917 | /* FSI DIV */ | ||
| 918 | ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable); | ||
| 919 | if (ret < 0) { | ||
| 920 | /* disable FSI B */ | ||
| 921 | if (enable) | ||
| 922 | __fsi_set_round_rate(fsib_clk, fsib_rate, 0); | ||
| 923 | goto fsi_set_rate_end; | ||
| 924 | } | ||
| 925 | |||
| 926 | ret = ackmd_bpfmd; | ||
| 927 | |||
| 928 | fsi_set_rate_end: | ||
| 929 | clk_put(fsib_clk); | ||
| 930 | return ret; | ||
| 931 | } | ||
| 932 | |||
| 933 | static struct sh_fsi_platform_info fsi_info = { | 865 | static struct sh_fsi_platform_info fsi_info = { |
| 934 | .port_a = { | 866 | .port_a = { |
| 935 | .flags = SH_FSI_BRS_INV, | 867 | .flags = SH_FSI_BRS_INV, |
| @@ -940,8 +872,8 @@ static struct sh_fsi_platform_info fsi_info = { | |||
| 940 | .flags = SH_FSI_BRS_INV | | 872 | .flags = SH_FSI_BRS_INV | |
| 941 | SH_FSI_BRM_INV | | 873 | SH_FSI_BRM_INV | |
| 942 | SH_FSI_LRS_INV | | 874 | SH_FSI_LRS_INV | |
| 875 | SH_FSI_CLK_CPG | | ||
| 943 | SH_FSI_FMT_SPDIF, | 876 | SH_FSI_FMT_SPDIF, |
| 944 | .set_rate = fsi_b_set_rate, | ||
| 945 | } | 877 | } |
| 946 | }; | 878 | }; |
| 947 | 879 | ||
| @@ -1018,7 +950,11 @@ static struct resource nand_flash_resources[] = { | |||
| 1018 | .start = 0xe6a30000, | 950 | .start = 0xe6a30000, |
| 1019 | .end = 0xe6a3009b, | 951 | .end = 0xe6a3009b, |
| 1020 | .flags = IORESOURCE_MEM, | 952 | .flags = IORESOURCE_MEM, |
| 1021 | } | 953 | }, |
| 954 | [1] = { | ||
| 955 | .start = evt2irq(0x0d80), /* flstei: status error irq */ | ||
| 956 | .flags = IORESOURCE_IRQ, | ||
| 957 | }, | ||
| 1022 | }; | 958 | }; |
| 1023 | 959 | ||
| 1024 | static struct sh_flctl_platform_data nand_flash_data = { | 960 | static struct sh_flctl_platform_data nand_flash_data = { |
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index 69f7f464eff8..449f9289567d 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c | |||
| @@ -34,6 +34,10 @@ | |||
| 34 | #include <linux/spi/sh_hspi.h> | 34 | #include <linux/spi/sh_hspi.h> |
| 35 | #include <linux/mmc/sh_mobile_sdhi.h> | 35 | #include <linux/mmc/sh_mobile_sdhi.h> |
| 36 | #include <linux/mfd/tmio.h> | 36 | #include <linux/mfd/tmio.h> |
| 37 | #include <linux/usb/otg.h> | ||
| 38 | #include <linux/usb/ehci_pdriver.h> | ||
| 39 | #include <linux/usb/ohci_pdriver.h> | ||
| 40 | #include <linux/pm_runtime.h> | ||
| 37 | #include <mach/hardware.h> | 41 | #include <mach/hardware.h> |
| 38 | #include <mach/r8a7779.h> | 42 | #include <mach/r8a7779.h> |
| 39 | #include <mach/common.h> | 43 | #include <mach/common.h> |
| @@ -144,13 +148,185 @@ static struct platform_device hspi_device = { | |||
| 144 | .num_resources = ARRAY_SIZE(hspi_resources), | 148 | .num_resources = ARRAY_SIZE(hspi_resources), |
| 145 | }; | 149 | }; |
| 146 | 150 | ||
| 151 | /* USB PHY */ | ||
| 152 | static struct resource usb_phy_resources[] = { | ||
| 153 | [0] = { | ||
| 154 | .start = 0xffe70000, | ||
| 155 | .end = 0xffe70900 - 1, | ||
| 156 | .flags = IORESOURCE_MEM, | ||
| 157 | }, | ||
| 158 | [1] = { | ||
| 159 | .start = 0xfff70000, | ||
| 160 | .end = 0xfff70900 - 1, | ||
| 161 | .flags = IORESOURCE_MEM, | ||
| 162 | }, | ||
| 163 | }; | ||
| 164 | |||
| 165 | static struct platform_device usb_phy_device = { | ||
| 166 | .name = "rcar_usb_phy", | ||
| 167 | .resource = usb_phy_resources, | ||
| 168 | .num_resources = ARRAY_SIZE(usb_phy_resources), | ||
| 169 | }; | ||
| 170 | |||
| 147 | static struct platform_device *marzen_devices[] __initdata = { | 171 | static struct platform_device *marzen_devices[] __initdata = { |
| 148 | ð_device, | 172 | ð_device, |
| 149 | &sdhi0_device, | 173 | &sdhi0_device, |
| 150 | &thermal_device, | 174 | &thermal_device, |
| 151 | &hspi_device, | 175 | &hspi_device, |
| 176 | &usb_phy_device, | ||
| 177 | }; | ||
| 178 | |||
| 179 | /* USB */ | ||
| 180 | static struct usb_phy *phy; | ||
| 181 | static int usb_power_on(struct platform_device *pdev) | ||
| 182 | { | ||
| 183 | if (!phy) | ||
| 184 | return -EIO; | ||
| 185 | |||
| 186 | pm_runtime_enable(&pdev->dev); | ||
| 187 | pm_runtime_get_sync(&pdev->dev); | ||
| 188 | |||
| 189 | usb_phy_init(phy); | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static void usb_power_off(struct platform_device *pdev) | ||
| 195 | { | ||
| 196 | if (!phy) | ||
| 197 | return; | ||
| 198 | |||
| 199 | usb_phy_shutdown(phy); | ||
| 200 | |||
| 201 | pm_runtime_put_sync(&pdev->dev); | ||
| 202 | pm_runtime_disable(&pdev->dev); | ||
| 203 | } | ||
| 204 | |||
| 205 | static struct usb_ehci_pdata ehcix_pdata = { | ||
| 206 | .power_on = usb_power_on, | ||
| 207 | .power_off = usb_power_off, | ||
| 208 | .power_suspend = usb_power_off, | ||
| 209 | }; | ||
| 210 | |||
| 211 | static struct resource ehci0_resources[] = { | ||
| 212 | [0] = { | ||
| 213 | .start = 0xffe70000, | ||
| 214 | .end = 0xffe70400 - 1, | ||
| 215 | .flags = IORESOURCE_MEM, | ||
| 216 | }, | ||
| 217 | [1] = { | ||
| 218 | .start = gic_spi(44), | ||
| 219 | .flags = IORESOURCE_IRQ, | ||
| 220 | }, | ||
| 221 | }; | ||
| 222 | |||
| 223 | static struct platform_device ehci0_device = { | ||
| 224 | .name = "ehci-platform", | ||
| 225 | .id = 0, | ||
| 226 | .dev = { | ||
| 227 | .dma_mask = &ehci0_device.dev.coherent_dma_mask, | ||
| 228 | .coherent_dma_mask = 0xffffffff, | ||
| 229 | .platform_data = &ehcix_pdata, | ||
| 230 | }, | ||
| 231 | .num_resources = ARRAY_SIZE(ehci0_resources), | ||
| 232 | .resource = ehci0_resources, | ||
| 152 | }; | 233 | }; |
| 153 | 234 | ||
| 235 | static struct resource ehci1_resources[] = { | ||
| 236 | [0] = { | ||
| 237 | .start = 0xfff70000, | ||
| 238 | .end = 0xfff70400 - 1, | ||
| 239 | .flags = IORESOURCE_MEM, | ||
| 240 | }, | ||
| 241 | [1] = { | ||
| 242 | .start = gic_spi(45), | ||
| 243 | .flags = IORESOURCE_IRQ, | ||
| 244 | }, | ||
| 245 | }; | ||
| 246 | |||
| 247 | static struct platform_device ehci1_device = { | ||
| 248 | .name = "ehci-platform", | ||
| 249 | .id = 1, | ||
| 250 | .dev = { | ||
| 251 | .dma_mask = &ehci1_device.dev.coherent_dma_mask, | ||
| 252 | .coherent_dma_mask = 0xffffffff, | ||
| 253 | .platform_data = &ehcix_pdata, | ||
| 254 | }, | ||
| 255 | .num_resources = ARRAY_SIZE(ehci1_resources), | ||
| 256 | .resource = ehci1_resources, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static struct usb_ohci_pdata ohcix_pdata = { | ||
| 260 | .power_on = usb_power_on, | ||
| 261 | .power_off = usb_power_off, | ||
| 262 | .power_suspend = usb_power_off, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static struct resource ohci0_resources[] = { | ||
| 266 | [0] = { | ||
| 267 | .start = 0xffe70400, | ||
| 268 | .end = 0xffe70800 - 1, | ||
| 269 | .flags = IORESOURCE_MEM, | ||
| 270 | }, | ||
| 271 | [1] = { | ||
| 272 | .start = gic_spi(44), | ||
| 273 | .flags = IORESOURCE_IRQ, | ||
| 274 | }, | ||
| 275 | }; | ||
| 276 | |||
| 277 | static struct platform_device ohci0_device = { | ||
| 278 | .name = "ohci-platform", | ||
| 279 | .id = 0, | ||
| 280 | .dev = { | ||
| 281 | .dma_mask = &ohci0_device.dev.coherent_dma_mask, | ||
| 282 | .coherent_dma_mask = 0xffffffff, | ||
| 283 | .platform_data = &ohcix_pdata, | ||
| 284 | }, | ||
| 285 | .num_resources = ARRAY_SIZE(ohci0_resources), | ||
| 286 | .resource = ohci0_resources, | ||
| 287 | }; | ||
| 288 | |||
| 289 | static struct resource ohci1_resources[] = { | ||
| 290 | [0] = { | ||
| 291 | .start = 0xfff70400, | ||
| 292 | .end = 0xfff70800 - 1, | ||
| 293 | .flags = IORESOURCE_MEM, | ||
| 294 | }, | ||
| 295 | [1] = { | ||
| 296 | .start = gic_spi(45), | ||
| 297 | .flags = IORESOURCE_IRQ, | ||
| 298 | }, | ||
| 299 | }; | ||
| 300 | |||
| 301 | static struct platform_device ohci1_device = { | ||
| 302 | .name = "ohci-platform", | ||
| 303 | .id = 1, | ||
| 304 | .dev = { | ||
| 305 | .dma_mask = &ohci1_device.dev.coherent_dma_mask, | ||
| 306 | .coherent_dma_mask = 0xffffffff, | ||
| 307 | .platform_data = &ohcix_pdata, | ||
| 308 | }, | ||
| 309 | .num_resources = ARRAY_SIZE(ohci1_resources), | ||
| 310 | .resource = ohci1_resources, | ||
| 311 | }; | ||
| 312 | |||
| 313 | static struct platform_device *marzen_late_devices[] __initdata = { | ||
| 314 | &ehci0_device, | ||
| 315 | &ehci1_device, | ||
| 316 | &ohci0_device, | ||
| 317 | &ohci1_device, | ||
| 318 | }; | ||
| 319 | |||
| 320 | void __init marzen_init_late(void) | ||
| 321 | { | ||
| 322 | /* get usb phy */ | ||
| 323 | phy = usb_get_phy(USB_PHY_TYPE_USB2); | ||
| 324 | |||
| 325 | shmobile_init_late(); | ||
| 326 | platform_add_devices(marzen_late_devices, | ||
| 327 | ARRAY_SIZE(marzen_late_devices)); | ||
| 328 | } | ||
| 329 | |||
| 154 | static void __init marzen_init(void) | 330 | static void __init marzen_init(void) |
| 155 | { | 331 | { |
| 156 | regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, | 332 | regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, |
| @@ -188,6 +364,14 @@ static void __init marzen_init(void) | |||
| 188 | gpio_request(GPIO_FN_HSPI_TX0, NULL); | 364 | gpio_request(GPIO_FN_HSPI_TX0, NULL); |
| 189 | gpio_request(GPIO_FN_HSPI_RX0, NULL); | 365 | gpio_request(GPIO_FN_HSPI_RX0, NULL); |
| 190 | 366 | ||
| 367 | /* USB (CN21) */ | ||
| 368 | gpio_request(GPIO_FN_USB_OVC0, NULL); | ||
| 369 | gpio_request(GPIO_FN_USB_OVC1, NULL); | ||
| 370 | gpio_request(GPIO_FN_USB_OVC2, NULL); | ||
| 371 | |||
| 372 | /* USB (CN22) */ | ||
| 373 | gpio_request(GPIO_FN_USB_PENC2, NULL); | ||
| 374 | |||
| 191 | r8a7779_add_standard_devices(); | 375 | r8a7779_add_standard_devices(); |
| 192 | platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); | 376 | platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices)); |
| 193 | } | 377 | } |
| @@ -200,6 +384,6 @@ MACHINE_START(MARZEN, "marzen") | |||
| 200 | .init_irq = r8a7779_init_irq, | 384 | .init_irq = r8a7779_init_irq, |
| 201 | .handle_irq = gic_handle_irq, | 385 | .handle_irq = gic_handle_irq, |
| 202 | .init_machine = marzen_init, | 386 | .init_machine = marzen_init, |
| 203 | .init_late = shmobile_init_late, | 387 | .init_late = marzen_init_late, |
| 204 | .timer = &shmobile_timer, | 388 | .timer = &shmobile_timer, |
| 205 | MACHINE_END | 389 | MACHINE_END |
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 906010344dd7..27ee1dcc3e2e 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | * A: inversion | 26 | * A: inversion |
| 27 | * B: format mode | 27 | * B: format mode |
| 28 | * C: chip specific | 28 | * C: chip specific |
| 29 | * D: clock selecter if master mode | ||
| 29 | */ | 30 | */ |
| 30 | 31 | ||
| 31 | /* A: clock inversion */ | 32 | /* A: clock inversion */ |
| @@ -44,6 +45,11 @@ | |||
| 44 | #define SH_FSI_OPTION_MASK 0x00000F00 | 45 | #define SH_FSI_OPTION_MASK 0x00000F00 |
| 45 | #define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */ | 46 | #define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */ |
| 46 | 47 | ||
| 48 | /* D: clock selecter if master mode */ | ||
| 49 | #define SH_FSI_CLK_MASK 0x0000F000 | ||
| 50 | #define SH_FSI_CLK_EXTERNAL (1 << 12) | ||
| 51 | #define SH_FSI_CLK_CPG (2 << 12) /* FSIxCK + FSI-DIV */ | ||
| 52 | |||
| 47 | /* | 53 | /* |
| 48 | * set_rate return value | 54 | * set_rate return value |
| 49 | * | 55 | * |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 9d7f30774a44..4a10e4d1bd43 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
| 24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
| 25 | #include <sound/pcm_params.h> | ||
| 25 | #include <sound/sh_fsi.h> | 26 | #include <sound/sh_fsi.h> |
| 26 | 27 | ||
| 27 | /* PortA/PortB register */ | 28 | /* PortA/PortB register */ |
| @@ -189,6 +190,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable); | |||
| 189 | */ | 190 | */ |
| 190 | 191 | ||
| 191 | /* | 192 | /* |
| 193 | * FSI clock | ||
| 194 | * | ||
| 195 | * FSIxCLK [CPG] (ick) -------> | | ||
| 196 | * |-> FSI_DIV (div)-> FSI2 | ||
| 197 | * FSIxCK [external] (xck) ---> | | ||
| 198 | */ | ||
| 199 | |||
| 200 | /* | ||
| 192 | * struct | 201 | * struct |
| 193 | */ | 202 | */ |
| 194 | 203 | ||
| @@ -228,6 +237,20 @@ struct fsi_stream { | |||
| 228 | dma_addr_t dma; | 237 | dma_addr_t dma; |
| 229 | }; | 238 | }; |
| 230 | 239 | ||
| 240 | struct fsi_clk { | ||
| 241 | /* see [FSI clock] */ | ||
| 242 | struct clk *own; | ||
| 243 | struct clk *xck; | ||
| 244 | struct clk *ick; | ||
| 245 | struct clk *div; | ||
| 246 | int (*set_rate)(struct device *dev, | ||
| 247 | struct fsi_priv *fsi, | ||
| 248 | unsigned long rate); | ||
| 249 | |||
| 250 | unsigned long rate; | ||
| 251 | unsigned int count; | ||
| 252 | }; | ||
| 253 | |||
| 231 | struct fsi_priv { | 254 | struct fsi_priv { |
| 232 | void __iomem *base; | 255 | void __iomem *base; |
| 233 | struct fsi_master *master; | 256 | struct fsi_master *master; |
| @@ -236,6 +259,8 @@ struct fsi_priv { | |||
| 236 | struct fsi_stream playback; | 259 | struct fsi_stream playback; |
| 237 | struct fsi_stream capture; | 260 | struct fsi_stream capture; |
| 238 | 261 | ||
| 262 | struct fsi_clk clock; | ||
| 263 | |||
| 239 | u32 fmt; | 264 | u32 fmt; |
| 240 | 265 | ||
| 241 | int chan_num:16; | 266 | int chan_num:16; |
| @@ -717,14 +742,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) | |||
| 717 | /* | 742 | /* |
| 718 | * clock function | 743 | * clock function |
| 719 | */ | 744 | */ |
| 745 | static int fsi_clk_init(struct device *dev, | ||
| 746 | struct fsi_priv *fsi, | ||
| 747 | int xck, | ||
| 748 | int ick, | ||
| 749 | int div, | ||
| 750 | int (*set_rate)(struct device *dev, | ||
| 751 | struct fsi_priv *fsi, | ||
| 752 | unsigned long rate)) | ||
| 753 | { | ||
| 754 | struct fsi_clk *clock = &fsi->clock; | ||
| 755 | int is_porta = fsi_is_port_a(fsi); | ||
| 756 | |||
| 757 | clock->xck = NULL; | ||
| 758 | clock->ick = NULL; | ||
| 759 | clock->div = NULL; | ||
| 760 | clock->rate = 0; | ||
| 761 | clock->count = 0; | ||
| 762 | clock->set_rate = set_rate; | ||
| 763 | |||
| 764 | clock->own = devm_clk_get(dev, NULL); | ||
| 765 | if (IS_ERR(clock->own)) | ||
| 766 | return -EINVAL; | ||
| 767 | |||
| 768 | /* external clock */ | ||
| 769 | if (xck) { | ||
| 770 | clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb"); | ||
| 771 | if (IS_ERR(clock->xck)) { | ||
| 772 | dev_err(dev, "can't get xck clock\n"); | ||
| 773 | return -EINVAL; | ||
| 774 | } | ||
| 775 | if (clock->xck == clock->own) { | ||
| 776 | dev_err(dev, "cpu doesn't support xck clock\n"); | ||
| 777 | return -EINVAL; | ||
| 778 | } | ||
| 779 | } | ||
| 780 | |||
| 781 | /* FSIACLK/FSIBCLK */ | ||
| 782 | if (ick) { | ||
| 783 | clock->ick = devm_clk_get(dev, is_porta ? "icka" : "ickb"); | ||
| 784 | if (IS_ERR(clock->ick)) { | ||
| 785 | dev_err(dev, "can't get ick clock\n"); | ||
| 786 | return -EINVAL; | ||
| 787 | } | ||
| 788 | if (clock->ick == clock->own) { | ||
| 789 | dev_err(dev, "cpu doesn't support ick clock\n"); | ||
| 790 | return -EINVAL; | ||
| 791 | } | ||
| 792 | } | ||
| 793 | |||
| 794 | /* FSI-DIV */ | ||
| 795 | if (div) { | ||
| 796 | clock->div = devm_clk_get(dev, is_porta ? "diva" : "divb"); | ||
| 797 | if (IS_ERR(clock->div)) { | ||
| 798 | dev_err(dev, "can't get div clock\n"); | ||
| 799 | return -EINVAL; | ||
| 800 | } | ||
| 801 | if (clock->div == clock->own) { | ||
| 802 | dev_err(dev, "cpu doens't support div clock\n"); | ||
| 803 | return -EINVAL; | ||
| 804 | } | ||
| 805 | } | ||
| 806 | |||
| 807 | return 0; | ||
| 808 | } | ||
| 809 | |||
| 810 | #define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0) | ||
| 811 | static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate) | ||
| 812 | { | ||
| 813 | fsi->clock.rate = rate; | ||
| 814 | } | ||
| 815 | |||
| 816 | static int fsi_clk_is_valid(struct fsi_priv *fsi) | ||
| 817 | { | ||
| 818 | return fsi->clock.set_rate && | ||
| 819 | fsi->clock.rate; | ||
| 820 | } | ||
| 821 | |||
| 822 | static int fsi_clk_enable(struct device *dev, | ||
| 823 | struct fsi_priv *fsi, | ||
| 824 | unsigned long rate) | ||
| 825 | { | ||
| 826 | struct fsi_clk *clock = &fsi->clock; | ||
| 827 | int ret = -EINVAL; | ||
| 828 | |||
| 829 | if (!fsi_clk_is_valid(fsi)) | ||
| 830 | return ret; | ||
| 831 | |||
| 832 | if (0 == clock->count) { | ||
| 833 | ret = clock->set_rate(dev, fsi, rate); | ||
| 834 | if (ret < 0) { | ||
| 835 | fsi_clk_invalid(fsi); | ||
| 836 | return ret; | ||
| 837 | } | ||
| 838 | |||
| 839 | if (clock->xck) | ||
| 840 | clk_enable(clock->xck); | ||
| 841 | if (clock->ick) | ||
| 842 | clk_enable(clock->ick); | ||
| 843 | if (clock->div) | ||
| 844 | clk_enable(clock->div); | ||
| 845 | |||
| 846 | clock->count++; | ||
| 847 | } | ||
| 848 | |||
| 849 | return ret; | ||
| 850 | } | ||
| 851 | |||
| 852 | static int fsi_clk_disable(struct device *dev, | ||
| 853 | struct fsi_priv *fsi) | ||
| 854 | { | ||
| 855 | struct fsi_clk *clock = &fsi->clock; | ||
| 856 | |||
| 857 | if (!fsi_clk_is_valid(fsi)) | ||
| 858 | return -EINVAL; | ||
| 859 | |||
| 860 | if (1 == clock->count--) { | ||
| 861 | if (clock->xck) | ||
| 862 | clk_disable(clock->xck); | ||
| 863 | if (clock->ick) | ||
| 864 | clk_disable(clock->ick); | ||
| 865 | if (clock->div) | ||
| 866 | clk_disable(clock->div); | ||
| 867 | } | ||
| 868 | |||
| 869 | return 0; | ||
| 870 | } | ||
| 871 | |||
| 872 | static int fsi_clk_set_ackbpf(struct device *dev, | ||
| 873 | struct fsi_priv *fsi, | ||
| 874 | int ackmd, int bpfmd) | ||
| 875 | { | ||
| 876 | u32 data = 0; | ||
| 877 | |||
| 878 | /* check ackmd/bpfmd relationship */ | ||
| 879 | if (bpfmd > ackmd) { | ||
| 880 | dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd); | ||
| 881 | return -EINVAL; | ||
| 882 | } | ||
| 883 | |||
| 884 | /* ACKMD */ | ||
| 885 | switch (ackmd) { | ||
| 886 | case 512: | ||
| 887 | data |= (0x0 << 12); | ||
| 888 | break; | ||
| 889 | case 256: | ||
| 890 | data |= (0x1 << 12); | ||
| 891 | break; | ||
| 892 | case 128: | ||
| 893 | data |= (0x2 << 12); | ||
| 894 | break; | ||
| 895 | case 64: | ||
| 896 | data |= (0x3 << 12); | ||
| 897 | break; | ||
| 898 | case 32: | ||
| 899 | data |= (0x4 << 12); | ||
| 900 | break; | ||
| 901 | default: | ||
| 902 | dev_err(dev, "unsupported ackmd (%d)\n", ackmd); | ||
| 903 | return -EINVAL; | ||
| 904 | } | ||
| 905 | |||
| 906 | /* BPFMD */ | ||
| 907 | switch (bpfmd) { | ||
| 908 | case 32: | ||
| 909 | data |= (0x0 << 8); | ||
| 910 | break; | ||
| 911 | case 64: | ||
| 912 | data |= (0x1 << 8); | ||
| 913 | break; | ||
| 914 | case 128: | ||
| 915 | data |= (0x2 << 8); | ||
| 916 | break; | ||
| 917 | case 256: | ||
| 918 | data |= (0x3 << 8); | ||
| 919 | break; | ||
| 920 | case 512: | ||
| 921 | data |= (0x4 << 8); | ||
| 922 | break; | ||
| 923 | case 16: | ||
| 924 | data |= (0x7 << 8); | ||
| 925 | break; | ||
| 926 | default: | ||
| 927 | dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd); | ||
| 928 | return -EINVAL; | ||
| 929 | } | ||
| 930 | |||
| 931 | dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd); | ||
| 932 | |||
| 933 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | ||
| 934 | udelay(10); | ||
| 935 | |||
| 936 | return 0; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int fsi_clk_set_rate_external(struct device *dev, | ||
| 940 | struct fsi_priv *fsi, | ||
| 941 | unsigned long rate) | ||
| 942 | { | ||
| 943 | struct clk *xck = fsi->clock.xck; | ||
| 944 | struct clk *ick = fsi->clock.ick; | ||
| 945 | unsigned long xrate; | ||
| 946 | int ackmd, bpfmd; | ||
| 947 | int ret = 0; | ||
| 948 | |||
| 949 | /* check clock rate */ | ||
| 950 | xrate = clk_get_rate(xck); | ||
| 951 | if (xrate % rate) { | ||
| 952 | dev_err(dev, "unsupported clock rate\n"); | ||
| 953 | return -EINVAL; | ||
| 954 | } | ||
| 955 | |||
| 956 | clk_set_parent(ick, xck); | ||
| 957 | clk_set_rate(ick, xrate); | ||
| 958 | |||
| 959 | bpfmd = fsi->chan_num * 32; | ||
| 960 | ackmd = xrate / rate; | ||
| 961 | |||
| 962 | dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate); | ||
| 963 | |||
| 964 | ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd); | ||
| 965 | if (ret < 0) | ||
| 966 | dev_err(dev, "%s failed", __func__); | ||
| 967 | |||
| 968 | return ret; | ||
| 969 | } | ||
| 970 | |||
| 971 | static int fsi_clk_set_rate_cpg(struct device *dev, | ||
| 972 | struct fsi_priv *fsi, | ||
| 973 | unsigned long rate) | ||
| 974 | { | ||
| 975 | struct clk *ick = fsi->clock.ick; | ||
| 976 | struct clk *div = fsi->clock.div; | ||
| 977 | unsigned long target = 0; /* 12288000 or 11289600 */ | ||
| 978 | unsigned long actual, cout; | ||
| 979 | unsigned long diff, min; | ||
| 980 | unsigned long best_cout, best_act; | ||
| 981 | int adj; | ||
| 982 | int ackmd, bpfmd; | ||
| 983 | int ret = -EINVAL; | ||
| 984 | |||
| 985 | if (!(12288000 % rate)) | ||
| 986 | target = 12288000; | ||
| 987 | if (!(11289600 % rate)) | ||
| 988 | target = 11289600; | ||
| 989 | if (!target) { | ||
| 990 | dev_err(dev, "unsupported rate\n"); | ||
| 991 | return ret; | ||
| 992 | } | ||
| 993 | |||
| 994 | bpfmd = fsi->chan_num * 32; | ||
| 995 | ackmd = target / rate; | ||
| 996 | ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd); | ||
| 997 | if (ret < 0) { | ||
| 998 | dev_err(dev, "%s failed", __func__); | ||
| 999 | return ret; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /* | ||
| 1003 | * The clock flow is | ||
| 1004 | * | ||
| 1005 | * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec] | ||
| 1006 | * | ||
| 1007 | * But, it needs to find best match of CPG and FSI_DIV | ||
| 1008 | * combination, since it is difficult to generate correct | ||
| 1009 | * frequency of audio clock from ick clock only. | ||
| 1010 | * Because ick is created from its parent clock. | ||
| 1011 | * | ||
| 1012 | * target = rate x [512/256/128/64]fs | ||
| 1013 | * cout = round(target x adjustment) | ||
| 1014 | * actual = cout / adjustment (by FSI-DIV) ~= target | ||
| 1015 | * audio = actual | ||
| 1016 | */ | ||
| 1017 | min = ~0; | ||
| 1018 | best_cout = 0; | ||
| 1019 | best_act = 0; | ||
| 1020 | for (adj = 1; adj < 0xffff; adj++) { | ||
| 1021 | |||
| 1022 | cout = target * adj; | ||
| 1023 | if (cout > 100000000) /* max clock = 100MHz */ | ||
| 1024 | break; | ||
| 1025 | |||
| 1026 | /* cout/actual audio clock */ | ||
| 1027 | cout = clk_round_rate(ick, cout); | ||
| 1028 | actual = cout / adj; | ||
| 1029 | |||
| 1030 | /* find best frequency */ | ||
| 1031 | diff = abs(actual - target); | ||
| 1032 | if (diff < min) { | ||
| 1033 | min = diff; | ||
| 1034 | best_cout = cout; | ||
| 1035 | best_act = actual; | ||
| 1036 | } | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | ret = clk_set_rate(ick, best_cout); | ||
| 1040 | if (ret < 0) { | ||
| 1041 | dev_err(dev, "ick clock failed\n"); | ||
| 1042 | return -EIO; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | ret = clk_set_rate(div, clk_round_rate(div, best_act)); | ||
| 1046 | if (ret < 0) { | ||
| 1047 | dev_err(dev, "div clock failed\n"); | ||
| 1048 | return -EIO; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | dev_dbg(dev, "ick/div = %ld/%ld\n", | ||
| 1052 | clk_get_rate(ick), clk_get_rate(div)); | ||
| 1053 | |||
| 1054 | return ret; | ||
| 1055 | } | ||
| 1056 | |||
| 720 | static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, | 1057 | static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, |
| 721 | long rate, int enable) | 1058 | long rate, int enable) |
| 722 | { | 1059 | { |
| 723 | set_rate_func set_rate = fsi_get_info_set_rate(fsi); | 1060 | set_rate_func set_rate = fsi_get_info_set_rate(fsi); |
| 724 | int ret; | 1061 | int ret; |
| 725 | 1062 | ||
| 726 | if (!set_rate) | 1063 | /* |
| 727 | return 0; | 1064 | * CAUTION |
| 1065 | * | ||
| 1066 | * set_rate will be deleted | ||
| 1067 | */ | ||
| 1068 | if (!set_rate) { | ||
| 1069 | if (enable) | ||
| 1070 | return fsi_clk_enable(dev, fsi, rate); | ||
| 1071 | else | ||
| 1072 | return fsi_clk_disable(dev, fsi); | ||
| 1073 | } | ||
| 728 | 1074 | ||
| 729 | ret = set_rate(dev, rate, enable); | 1075 | ret = set_rate(dev, rate, enable); |
| 730 | if (ret < 0) /* error */ | 1076 | if (ret < 0) /* error */ |
| @@ -1334,14 +1680,21 @@ static int fsi_hw_startup(struct fsi_priv *fsi, | |||
| 1334 | /* fifo init */ | 1680 | /* fifo init */ |
| 1335 | fsi_fifo_init(fsi, io, dev); | 1681 | fsi_fifo_init(fsi, io, dev); |
| 1336 | 1682 | ||
| 1683 | /* start master clock */ | ||
| 1684 | if (fsi_is_clk_master(fsi)) | ||
| 1685 | return fsi_set_master_clk(dev, fsi, fsi->rate, 1); | ||
| 1686 | |||
| 1337 | return 0; | 1687 | return 0; |
| 1338 | } | 1688 | } |
| 1339 | 1689 | ||
| 1340 | static void fsi_hw_shutdown(struct fsi_priv *fsi, | 1690 | static int fsi_hw_shutdown(struct fsi_priv *fsi, |
| 1341 | struct device *dev) | 1691 | struct device *dev) |
| 1342 | { | 1692 | { |
| 1693 | /* stop master clock */ | ||
| 1343 | if (fsi_is_clk_master(fsi)) | 1694 | if (fsi_is_clk_master(fsi)) |
| 1344 | fsi_set_master_clk(dev, fsi, fsi->rate, 0); | 1695 | return fsi_set_master_clk(dev, fsi, fsi->rate, 0); |
| 1696 | |||
| 1697 | return 0; | ||
| 1345 | } | 1698 | } |
| 1346 | 1699 | ||
| 1347 | static int fsi_dai_startup(struct snd_pcm_substream *substream, | 1700 | static int fsi_dai_startup(struct snd_pcm_substream *substream, |
| @@ -1349,6 +1702,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
| 1349 | { | 1702 | { |
| 1350 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1703 | struct fsi_priv *fsi = fsi_get_priv(substream); |
| 1351 | 1704 | ||
| 1705 | fsi_clk_invalid(fsi); | ||
| 1352 | fsi->rate = 0; | 1706 | fsi->rate = 0; |
| 1353 | 1707 | ||
| 1354 | return 0; | 1708 | return 0; |
| @@ -1359,6 +1713,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
| 1359 | { | 1713 | { |
| 1360 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1714 | struct fsi_priv *fsi = fsi_get_priv(substream); |
| 1361 | 1715 | ||
| 1716 | fsi_clk_invalid(fsi); | ||
| 1362 | fsi->rate = 0; | 1717 | fsi->rate = 0; |
| 1363 | } | 1718 | } |
| 1364 | 1719 | ||
| @@ -1372,13 +1727,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
| 1372 | switch (cmd) { | 1727 | switch (cmd) { |
| 1373 | case SNDRV_PCM_TRIGGER_START: | 1728 | case SNDRV_PCM_TRIGGER_START: |
| 1374 | fsi_stream_init(fsi, io, substream); | 1729 | fsi_stream_init(fsi, io, substream); |
| 1375 | fsi_hw_startup(fsi, io, dai->dev); | 1730 | if (!ret) |
| 1376 | ret = fsi_stream_transfer(io); | 1731 | ret = fsi_hw_startup(fsi, io, dai->dev); |
| 1377 | if (0 == ret) | 1732 | if (!ret) |
| 1733 | ret = fsi_stream_transfer(io); | ||
| 1734 | if (!ret) | ||
| 1378 | fsi_stream_start(fsi, io); | 1735 | fsi_stream_start(fsi, io); |
| 1379 | break; | 1736 | break; |
| 1380 | case SNDRV_PCM_TRIGGER_STOP: | 1737 | case SNDRV_PCM_TRIGGER_STOP: |
| 1381 | fsi_hw_shutdown(fsi, dai->dev); | 1738 | if (!ret) |
| 1739 | ret = fsi_hw_shutdown(fsi, dai->dev); | ||
| 1382 | fsi_stream_stop(fsi, io); | 1740 | fsi_stream_stop(fsi, io); |
| 1383 | fsi_stream_quit(fsi, io); | 1741 | fsi_stream_quit(fsi, io); |
| 1384 | break; | 1742 | break; |
| @@ -1437,9 +1795,25 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
| 1437 | return -EINVAL; | 1795 | return -EINVAL; |
| 1438 | } | 1796 | } |
| 1439 | 1797 | ||
| 1440 | if (fsi_is_clk_master(fsi) && !set_rate) { | 1798 | if (fsi_is_clk_master(fsi)) { |
| 1441 | dev_err(dai->dev, "platform doesn't have set_rate\n"); | 1799 | /* |
| 1442 | return -EINVAL; | 1800 | * CAUTION |
| 1801 | * | ||
| 1802 | * set_rate will be deleted | ||
| 1803 | */ | ||
| 1804 | if (set_rate) | ||
| 1805 | dev_warn(dai->dev, "set_rate will be removed soon\n"); | ||
| 1806 | |||
| 1807 | switch (flags & SH_FSI_CLK_MASK) { | ||
| 1808 | case SH_FSI_CLK_EXTERNAL: | ||
| 1809 | fsi_clk_init(dai->dev, fsi, 1, 1, 0, | ||
| 1810 | fsi_clk_set_rate_external); | ||
| 1811 | break; | ||
| 1812 | case SH_FSI_CLK_CPG: | ||
| 1813 | fsi_clk_init(dai->dev, fsi, 0, 1, 1, | ||
| 1814 | fsi_clk_set_rate_cpg); | ||
| 1815 | break; | ||
| 1816 | } | ||
| 1443 | } | 1817 | } |
| 1444 | 1818 | ||
| 1445 | /* set format */ | 1819 | /* set format */ |
| @@ -1462,19 +1836,13 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 1462 | struct snd_soc_dai *dai) | 1836 | struct snd_soc_dai *dai) |
| 1463 | { | 1837 | { |
| 1464 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1838 | struct fsi_priv *fsi = fsi_get_priv(substream); |
| 1465 | long rate = params_rate(params); | ||
| 1466 | int ret; | ||
| 1467 | |||
| 1468 | if (!fsi_is_clk_master(fsi)) | ||
| 1469 | return 0; | ||
| 1470 | 1839 | ||
| 1471 | ret = fsi_set_master_clk(dai->dev, fsi, rate, 1); | 1840 | if (fsi_is_clk_master(fsi)) { |
| 1472 | if (ret < 0) | 1841 | fsi->rate = params_rate(params); |
| 1473 | return ret; | 1842 | fsi_clk_valid(fsi, fsi->rate); |
| 1474 | 1843 | } | |
| 1475 | fsi->rate = rate; | ||
| 1476 | 1844 | ||
| 1477 | return ret; | 1845 | return 0; |
| 1478 | } | 1846 | } |
| 1479 | 1847 | ||
| 1480 | static const struct snd_soc_dai_ops fsi_dai_ops = { | 1848 | static const struct snd_soc_dai_ops fsi_dai_ops = { |
| @@ -1498,7 +1866,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = { | |||
| 1498 | .rates = FSI_RATES, | 1866 | .rates = FSI_RATES, |
| 1499 | .rate_min = 8000, | 1867 | .rate_min = 8000, |
| 1500 | .rate_max = 192000, | 1868 | .rate_max = 192000, |
| 1501 | .channels_min = 1, | 1869 | .channels_min = 2, |
| 1502 | .channels_max = 2, | 1870 | .channels_max = 2, |
| 1503 | .buffer_bytes_max = 64 * 1024, | 1871 | .buffer_bytes_max = 64 * 1024, |
| 1504 | .period_bytes_min = 32, | 1872 | .period_bytes_min = 32, |
| @@ -1586,14 +1954,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = { | |||
| 1586 | .playback = { | 1954 | .playback = { |
| 1587 | .rates = FSI_RATES, | 1955 | .rates = FSI_RATES, |
| 1588 | .formats = FSI_FMTS, | 1956 | .formats = FSI_FMTS, |
| 1589 | .channels_min = 1, | 1957 | .channels_min = 2, |
| 1590 | .channels_max = 8, | 1958 | .channels_max = 2, |
| 1591 | }, | 1959 | }, |
| 1592 | .capture = { | 1960 | .capture = { |
| 1593 | .rates = FSI_RATES, | 1961 | .rates = FSI_RATES, |
| 1594 | .formats = FSI_FMTS, | 1962 | .formats = FSI_FMTS, |
| 1595 | .channels_min = 1, | 1963 | .channels_min = 2, |
| 1596 | .channels_max = 8, | 1964 | .channels_max = 2, |
| 1597 | }, | 1965 | }, |
| 1598 | .ops = &fsi_dai_ops, | 1966 | .ops = &fsi_dai_ops, |
| 1599 | }, | 1967 | }, |
| @@ -1602,14 +1970,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = { | |||
| 1602 | .playback = { | 1970 | .playback = { |
| 1603 | .rates = FSI_RATES, | 1971 | .rates = FSI_RATES, |
| 1604 | .formats = FSI_FMTS, | 1972 | .formats = FSI_FMTS, |
| 1605 | .channels_min = 1, | 1973 | .channels_min = 2, |
| 1606 | .channels_max = 8, | 1974 | .channels_max = 2, |
| 1607 | }, | 1975 | }, |
| 1608 | .capture = { | 1976 | .capture = { |
| 1609 | .rates = FSI_RATES, | 1977 | .rates = FSI_RATES, |
| 1610 | .formats = FSI_FMTS, | 1978 | .formats = FSI_FMTS, |
| 1611 | .channels_min = 1, | 1979 | .channels_min = 2, |
| 1612 | .channels_max = 8, | 1980 | .channels_max = 2, |
| 1613 | }, | 1981 | }, |
| 1614 | .ops = &fsi_dai_ops, | 1982 | .ops = &fsi_dai_ops, |
| 1615 | }, | 1983 | }, |
| @@ -1702,7 +2070,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 1702 | pm_runtime_enable(&pdev->dev); | 2070 | pm_runtime_enable(&pdev->dev); |
| 1703 | dev_set_drvdata(&pdev->dev, master); | 2071 | dev_set_drvdata(&pdev->dev, master); |
| 1704 | 2072 | ||
| 1705 | ret = request_irq(irq, &fsi_interrupt, 0, | 2073 | ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0, |
| 1706 | id_entry->name, master); | 2074 | id_entry->name, master); |
| 1707 | if (ret) { | 2075 | if (ret) { |
| 1708 | dev_err(&pdev->dev, "irq request err\n"); | 2076 | dev_err(&pdev->dev, "irq request err\n"); |
| @@ -1712,7 +2080,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 1712 | ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform); | 2080 | ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform); |
| 1713 | if (ret < 0) { | 2081 | if (ret < 0) { |
| 1714 | dev_err(&pdev->dev, "cannot snd soc register\n"); | 2082 | dev_err(&pdev->dev, "cannot snd soc register\n"); |
| 1715 | goto exit_free_irq; | 2083 | goto exit_fsib; |
| 1716 | } | 2084 | } |
| 1717 | 2085 | ||
| 1718 | ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai, | 2086 | ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai, |
| @@ -1726,8 +2094,6 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 1726 | 2094 | ||
| 1727 | exit_snd_soc: | 2095 | exit_snd_soc: |
| 1728 | snd_soc_unregister_platform(&pdev->dev); | 2096 | snd_soc_unregister_platform(&pdev->dev); |
| 1729 | exit_free_irq: | ||
| 1730 | free_irq(irq, master); | ||
| 1731 | exit_fsib: | 2097 | exit_fsib: |
| 1732 | pm_runtime_disable(&pdev->dev); | 2098 | pm_runtime_disable(&pdev->dev); |
| 1733 | fsi_stream_remove(&master->fsib); | 2099 | fsi_stream_remove(&master->fsib); |
| @@ -1743,7 +2109,6 @@ static int fsi_remove(struct platform_device *pdev) | |||
| 1743 | 2109 | ||
| 1744 | master = dev_get_drvdata(&pdev->dev); | 2110 | master = dev_get_drvdata(&pdev->dev); |
| 1745 | 2111 | ||
| 1746 | free_irq(master->irq, master); | ||
| 1747 | pm_runtime_disable(&pdev->dev); | 2112 | pm_runtime_disable(&pdev->dev); |
| 1748 | 2113 | ||
| 1749 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); | 2114 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai)); |
| @@ -1774,10 +2139,6 @@ static void __fsi_resume(struct fsi_priv *fsi, | |||
| 1774 | return; | 2139 | return; |
| 1775 | 2140 | ||
| 1776 | fsi_hw_startup(fsi, io, dev); | 2141 | fsi_hw_startup(fsi, io, dev); |
| 1777 | |||
| 1778 | if (fsi_is_clk_master(fsi) && fsi->rate) | ||
| 1779 | fsi_set_master_clk(dev, fsi, fsi->rate, 1); | ||
| 1780 | |||
| 1781 | fsi_stream_start(fsi, io); | 2142 | fsi_stream_start(fsi, io); |
| 1782 | } | 2143 | } |
| 1783 | 2144 | ||
