diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts index d621e6eea63832..9c5cb7ec048c58 100644 --- a/arch/arm/boot/dts/exynos5410-odroidxu.dts +++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts @@ -540,7 +540,7 @@ i2s@03830000 { - status = "okay"; + status = "okay"; }; sound { @@ -549,8 +549,8 @@ samsung,i2s-controller = <&i2s0>; samsung,audio-codec = <&max98090>; card-name = "ODROID-I2S-98090"; - clocks = <&clock CLK_FOUT_EPLL>, <&clock CLK_SCLK_EPLL>, <&clock CLK_MOUT_AUDIO0>, - <&clock CLK_SCLK_MAUDIO0>, <&clock_audss EXYNOS_MOUT_AUDSS>, + clocks = <&clock CLK_FOUT_EPLL>, <&clock CLK_MOUT_EPLL>, <&clock CLK_MOUT_MAU_AUDIO0>, + <&clock CLK_SCLK_MAU_AUDIO0>, <&clock_audss EXYNOS_MOUT_AUDSS>, <&clock_audss EXYNOS_MOUT_I2S>; clock-names = "fout_epll", "sclk_epll", "mout_audio0", "sclk_audio0", "mout_audss", "mout_i2s"; diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi index 2ea3d6174e6a36..f9b3c0c8b5c12a 100644 --- a/arch/arm/boot/dts/exynos5410.dtsi +++ b/arch/arm/boot/dts/exynos5410.dtsi @@ -322,6 +322,10 @@ clock-names = "hdmi", "sclk_hdmi", "div_hdmi_pixel", "sclk_hdmiphy", "mout_hdmi"; phy = <&hdmiphy>; + + hdmi-audio { + compatible = "samsung,exynos-hdmi-audio"; + }; }; hdmiphy: hdmiphy@145D0000 { @@ -386,7 +390,7 @@ reg = <0x12110000 0x100>; interrupts = <0 71 0>; - clocks = <&clock CLK_USBH20>; + clocks = <&clock CLK_USB2>; clock-names = "usbhost"; }; @@ -395,14 +399,14 @@ reg = <0x12120000 0x100>; interrupts = <0 71 0>; - clocks = <&clock CLK_USBH20>; + clocks = <&clock CLK_USB2>; clock-names = "usbhost"; }; usb2_phy: usbphy@12130000 { compatible = "samsung,exynos5250-usb2phy"; reg = <0x12130000 0x100>; - clocks = <&clock CLK_FIN_PLL>, <&clock CLK_USBH20>; + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_USB2>; clock-names = "ext_xtal", "usbhost"; #address-cells = <1>; #size-cells = <1>; @@ -417,7 +421,7 @@ usb3_phy0: usbphy@12100000 { compatible = "samsung,exynos5250-usb3phy"; reg = <0x12100000 0x100>; - clocks = <&clock CLK_FIN_PLL>, <&clock CLK_USBD300>; + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_USBPHY300>; clock-names = "ext_xtal", "usbdrd30"; #address-cells = <1>; #size-cells = <1>; @@ -432,7 +436,7 @@ usb3_phy1: usbphy@12500000 { compatible = "samsung,exynos5250-usb3phy"; reg = <0x12500000 0x100>; - clocks = <&clock CLK_FIN_PLL>, <&clock CLK_USBD301>; + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_USBPHY301>; clock-names = "ext_xtal", "usbdrd30"; #address-cells = <1>; #size-cells = <1>; @@ -446,7 +450,7 @@ usb@12000000 { compatible = "samsung,exynos5250-dwusb3"; - clocks = <&clock CLK_USBD300>; + clocks = <&clock CLK_USBPHY300>; clock-names = "usbdrd30"; #address-cells = <1>; #size-cells = <1>; @@ -462,7 +466,7 @@ usb@12400000 { compatible = "samsung,exynos5250-dwusb3"; - clocks = <&clock CLK_USBD301>; + clocks = <&clock CLK_USBPHY301>; clock-names = "usbdrd30"; #address-cells = <1>; #size-cells = <1>; @@ -573,10 +577,10 @@ }; clock_audss: audss-clock-controller@3810000 { - compatible = "samsung,exynos5250-audss-clock"; /* Is it compatible with exynos5420 or exynos5250? */ + compatible = "samsung,exynos5250-audss-clock"; reg = <0x03810000 0x0C>; #clock-cells = <1>; - clocks = <&clock CLK_FIN_PLL>, <&clock CLK_FOUT_EPLL>, <&clock CLK_SCLK_MAUDIO0>, <&clock CLK_SCLK_MAUPCM0>; + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_FOUT_EPLL>, <&clock CLK_SCLK_MAU_AUDIO0>, <&clock CLK_SCLK_MAU_PCM0>; clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in"; }; @@ -611,6 +615,7 @@ #dma-channels = <8>; #dma-requests = <32>; }; + */ mdma0: mdma@10800000 { compatible = "arm,pl330", "arm,primecell"; @@ -623,6 +628,7 @@ #dma-requests = <1>; }; + /* mdma1: mdma@11C10000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x11C10000 0x1000>; @@ -647,9 +653,6 @@ <&clock_audss EXYNOS_I2S_BUS>, <&clock_audss EXYNOS_SCLK_I2S>; clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; - samsung,supports-6ch; - samsung,supports-rstclr; - samsung,supports-secdai; samsung,idma-addr = <0x03000000>; pinctrl-names = "default"; pinctrl-0 = <&i2s0_bus>; @@ -669,6 +672,7 @@ pinctrl-0 = <&i2s1_bus>; status = "disabled"; }; + */ i2s2: i2s@12D70000 { compatible = "samsung,s5pv210-i2s"; @@ -681,5 +685,5 @@ pinctrl-names = "default"; pinctrl-0 = <&i2s2_bus>; status = "disabled"; - };*/ + }; }; diff --git a/arch/arm/configs/odroidxu_defconfig b/arch/arm/configs/odroidxu_defconfig index 9197bad7585d56..a651d33c736351 100644 --- a/arch/arm/configs/odroidxu_defconfig +++ b/arch/arm/configs/odroidxu_defconfig @@ -109,6 +109,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_EXTRA_FIRMWARE="edid/1024x768.fw edid/1280x1024.fw edid/1280x720.fw edid/1920x1080.fw" +# CONFIG_FW_LOADER_USER_HELPER is not set CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=128 CONFIG_CONNECTOR=y @@ -117,6 +118,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_NETDEVICES=y @@ -203,6 +205,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MAX77XXX=y CONFIG_REGULATOR_S2MPS11=y CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y CONFIG_MEDIA_RC_SUPPORT=y CONFIG_RC_DEVICES=y @@ -247,6 +250,11 @@ CONFIG_DVB_USB_IT913X=m CONFIG_DVB_USB_LME2510=m CONFIG_DVB_USB_MXL111SF=m CONFIG_DVB_USB_RTL28XXU=m +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_SAMSUNG_S5P_G2D=m +CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m +CONFIG_VIDEO_SAMSUNG_S5P_MFC=m +CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m CONFIG_DRM=y CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_EXYNOS=y @@ -267,9 +275,12 @@ CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y CONFIG_SOUND=y CONFIG_SND=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y CONFIG_SND_SOC=y CONFIG_SND_SOC_SAMSUNG=y -CONFIG_SND_SOC_SAMSUNG_HDMI_AUDIO=m +CONFIG_SND_SOC_SAMSUNG_HDMI_AUDIO=y CONFIG_SND_SOC_SMDK_I2S_STUB=y CONFIG_SND_SOC_EXYNOS_MAX98095=y CONFIG_HIDRAW=y @@ -361,6 +372,7 @@ CONFIG_STAGING=y CONFIG_R8188EU=m CONFIG_88EU_AP_MODE=y CONFIG_COMMON_CLK_DEBUG=y +CONFIG_COMMON_CLK_DEBUG_EXTRA=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 675749f811bae2..a4125f364bb996 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -33,6 +33,14 @@ config COMMON_CLK_DEBUG clk_flags, clk_prepare_count, clk_enable_count & clk_notifier_count. +config COMMON_CLK_DEBUG_EXTRA + bool "Extra features for the clock tree DebugFS" + depends on COMMON_CLK_DEBUG + ---help--- + Adds one write-one file named change_rate to each + directory, allowing the function clk_set_rate to + be called. + config COMMON_CLK_WM831X tristate "Clock driver for WM831x/2x PMICs" depends on MFD_WM831X diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 77fcd069c64ae1..3808d87f37b813 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -226,6 +226,16 @@ static const struct file_operations clk_dump_fops = { .release = single_release, }; +#if CONFIG_COMMON_CLK_DEBUG_EXTRA +static int debugfs_clk_set_rate(void *data, u64 val) +{ + struct clk *clk = (struct clk *) data; + return clk_set_rate(clk, (u32) val); +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_clk_rate_wo, NULL, debugfs_clk_set_rate, "%llu\n"); +#endif /* CONFIG_COMMON_CLK_DEBUG_EXTRA */ + /* caller must hold prepare_lock */ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) { @@ -248,6 +258,12 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) if (!d) goto err_out; +#if CONFIG_COMMON_CLK_DEBUG_EXTRA + d = debugfs_create_file("change_rate", S_IWUGO, clk->dentry, clk, &fops_clk_rate_wo); + if (!d) + goto err_out; +#endif + d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry, (u32 *)&clk->flags); if (!d) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 1a7c1b929c690b..8e292d7e708c13 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1100,11 +1100,13 @@ static void __init exynos4_clk_init(struct device_node *np, if (exynos4_soc == EXYNOS4210) samsung_clk_init(np, reg_base, nr_clks, exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), - exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save)); + exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save), + NULL, NULL, NULL); else samsung_clk_init(np, reg_base, nr_clks, exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), - exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save)); + exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save), + NULL, NULL, NULL); samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index f048fd2a349dab..e3f4eacc98aa78 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -563,7 +563,7 @@ static void __init exynos5250_clk_init(struct device_node *np) samsung_clk_init(np, reg_base, nr_clks, exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs), - NULL, 0); + NULL, 0, NULL, NULL, NULL); samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index d57a375b5c6784..69c6f900a4adfd 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -21,81 +21,147 @@ #include #include "clk.h" +#include "clk-pll.h" #define APLL_LOCK 0x0 #define APLL_CON0 0x100 -#define CPLL_LOCK 0x10020 -#define CPLL_CON0 0x10120 +#define SRC_CPU 0x200 +#define DIV_CPU0 0x500 +#define DIV_CPU1 0x504 +#define GATE_BUS_CPU 0x700 +#define GATE_SCLK_CPU 0x800 + #define MPLL_LOCK 0x4000 #define MPLL_CON0 0x4100 -#define BPLL_LOCK 0x20010 -#define BPLL_CON0 0x20110 -#define KPLL_LOCK 0x28000 -#define KPLL_CON0 0x28100 -#define VPLL_LOCK 0x10050 -#define VPLL_CON0 0x10140 +#define SRC_CPERI0 0x4200 +#define SRC_CPERI1 0x4204 +#define DIV_CPERI0 0x4500 +#define DIV_CPERI1 0x4504 +#define GATE_IP_CORE 0x4900 + +#define DIV_G2D 0x8500 +#define DIV_ACP 0x8500 /* The same? */ +#define GATE_IP_G2D 0x8800 +#define GATE_IP_ACP 0x8800 /* Again? */ + +#define CPLL_LOCK 0x10020 #define DPLL_LOCK 0x10030 -#define DPLL_CON0 0x10128 #define EPLL_LOCK 0x10040 -#define EPLL_CON0 0x10130 +#define VPLL_LOCK 0x10050 #define IPLL_LOCK 0x10060 + +#define CPLL_CON0 0x10120 +#define CPLL_CON1 0x10124 +#define DPLL_CON0 0x10128 +#define DPLL_CON1 0x1012C +#define EPLL_CON0 0x10130 +#define EPLL_CON1 0x10134 +#define EPLL_CON2 0x10138 +#define VPLL_CON0 0x10140 +#define VPLL_CON1 0x10144 +#define VPLL_CON2 0x10148 #define IPLL_CON0 0x10150 -#define GATE_IP_ACP 0x8800 +#define IPLL_CON1 0x10154 + +#define SRC_TOP0 0x10210 +#define SRC_TOP1 0x10214 +#define SRC_TOP2 0x10218 +#define SRC_TOP3 0x1021C +#define SRC_GSCL 0x10220 +#define SRC_DISP0_0 0x10224 +#define SRC_DISP0_1 0x10228 +#define SRC_DISP1_0 0x1022C +#define SRC_DISP1_1 0x10230 +#define SRC_MAU 0x10240 +#define SRC_FSYS 0x10244 +#define SRC_GEN 0x10248 +#define SRC_PERIC0 0x10250 +#define SRC_PERIC1 0x10254 + +#define SRC_MASK_TOP 0x10310 +#define SRC_MASK_GSCL 0x10320 +#define SRC_MASK_DISP0_0 0x10324 +#define SRC_MASK_DISP0_1 0x10328 +#define SRC_MASK_DISP1_0 0x1032C +#define SRC_MASK_DISP1_1 0x10330 +#define SRC_MASK_MAU 0x10334 +#define SRC_MASK_FSYS 0x10340 +#define SRC_MASK_GEN 0x10344 +#define SRC_MASK_PERIC0 0x10350 +#define SRC_MASK_PERIC1 0x10354 -#define SRC_CPU 0x200 -#define DIV_CPU0 0x500 -#define SRC_CPERI1 0x4204 #define DIV_TOP0 0x10510 #define DIV_TOP1 0x10514 #define DIV_TOP2 0x10518 -#define DIV_FSYS1 0x1054c +#define DIV_TOP3 0x1051C +#define DIV_GSCL 0x10520 +#define DIV_DISP0_0 0x10524 +#define DIV_DISP0_1 0x10528 +#define DIV_DISP1_0 0x1052C +#define DIV_DISP1_1 0x10530 +#define DIV_GEN 0x1053C +#define DIV_MAU 0x10544 +#define DIV_FSYS0 0x10548 +#define DIV_FSYS1 0x1054C #define DIV_FSYS2 0x10550 +#define DIV_FSYS3 0x10554 #define DIV_PERIC0 0x10558 -#define DIV_PERIC1 0x1055c +#define DIV_PERIC1 0x1055C #define DIV_PERIC2 0x10560 #define DIV_PERIC3 0x10564 #define DIV_PERIC4 0x10568 #define DIV_PERIC5 0x1056C -#define DIV_DISP1_0 0x1052c -#define DIV_MAU 0x10544 -#define DIV_FSYS0 0x10548 -#define SRC_TOP0 0x10210 -#define SRC_TOP1 0x10214 -#define SRC_TOP2 0x10218 -#define SRC_TOP3 0x1021c -#define SRC_FSYS 0x10244 -#define SRC_DISP1_0 0x1022c -#define SRC_MAU 0x10240 -#define SRC_PERIC0 0x10250 -#define SRC_PERIC1 0x10254 -#define SRC_MASK_DISP1_0 0x1032c -#define SRC_MASK_MAU 0x10334 -#define SRC_MASK_FSYS 0x10340 -#define SRC_MASK_PERIC0 0x10350 + +#define GATE_BUS_GSCL0 0x10710 +#define GATE_BUS_GSCL1 0x10720 +#define GATE_BUS_DISP0 0x10724 +#define GATE_BUS_DISP1 0x10728 +#define GATE_BUS_MFC 0x10734 +#define GATE_BUS_G3D 0x10738 +#define GATE_BUS_GEN 0x1073C #define GATE_BUS_FSYS0 0x10740 +#define GATE_BUS_FSYS1 0x10744 + #define GATE_TOP_SCLK_GSCL 0x10820 +#define GATE_TOP_SCLK_DISP0 0x10824 #define GATE_TOP_SCLK_DISP1 0x10828 -#define GATE_TOP_SCLK_MAU 0x1083c +#define GATE_TOP_SCLK_GEN 0x1082C +#define GATE_TOP_SCLK_MAU 0x1083C #define GATE_TOP_SCLK_FSYS 0x10840 #define GATE_TOP_SCLK_PERIC 0x10850 -#define GATE_IP_FSYS 0x10944 -#define GATE_IP_PERIC 0x10950 -#define GATE_IP_PERIS 0x10960 -#define GATE_IP_DISP1 0x10928 + #define GATE_IP_GSCL0 0x10910 #define GATE_IP_GSCL1 0x10920 -#define GATE_IP_MFC 0x1092c +#define GATE_IP_DISP0 0x10924 +#define GATE_IP_DISP1 0x10928 +#define GATE_IP_MFC 0x1092C +#define GATE_IP_G3D 0x10930 #define GATE_IP_GEN 0x10934 +#define GATE_IP_FSYS 0x10944 +#define GATE_IP_PERIC 0x10950 +#define GATE_IP_PERIS 0x10960 + + +#define BPLL_LOCK 0x20010 +#define BPLL_CON0 0x20110 #define SRC_CDREX 0x20200 +#define DIV_CDREX 0x20500 +#define DIV_CDREX2 0x20504 +#define GATE_BUS_CDREX 0x20700 +#define GATE_IP_CDREX 0x20900 + +#define KPLL_LOCK 0x28000 +#define KPLL_CON0 0x28100 #define SRC_KFC 0x28200 #define DIV_KFC0 0x28500 + /* list of PLLs */ enum exynos5410_plls { - apll, cpll, mpll, - bpll, kpll, vpll, + apll, bpll, cpll, dpll, epll, ipll, + kpll, mpll, vpll, nr_plls /* number of PLLs */ }; @@ -105,47 +171,96 @@ enum exynos5410_plls { */ static unsigned long exynos5410_clk_regs[] __initdata = { SRC_CPU, - DIV_CPU0, + SRC_CPERI0, SRC_CPERI1, SRC_TOP0, SRC_TOP1, SRC_TOP2, SRC_TOP3, SRC_MAU, - SRC_FSYS, + SRC_CDREX, + SRC_DISP0_0, + SRC_DISP0_1, + SRC_DISP1_0, + SRC_DISP1_1, + SRC_KFC, SRC_PERIC0, SRC_PERIC1, + SRC_GSCL, + SRC_FSYS, + + DIV_GEN, + DIV_CDREX, + DIV_CDREX2, + DIV_ACP, DIV_TOP0, DIV_TOP1, DIV_TOP2, - DIV_MAU, + DIV_TOP3, DIV_FSYS0, DIV_FSYS1, DIV_FSYS2, + DIV_GSCL, + DIV_DISP0_0, + DIV_DISP0_1, + DIV_DISP1_0, + DIV_DISP1_1, DIV_PERIC0, DIV_PERIC1, DIV_PERIC2, DIV_PERIC3, DIV_PERIC4, - SRC_MASK_FSYS, - SRC_MASK_PERIC0, + DIV_PERIC5, + DIV_CPERI1, + DIV_G2D, + DIV_MAU, + DIV_CPU0, + DIV_KFC0, + GATE_BUS_FSYS0, - GATE_IP_FSYS, + GATE_BUS_DISP1, GATE_IP_PERIC, GATE_IP_PERIS, + GATE_IP_FSYS, GATE_IP_GSCL0, GATE_IP_GSCL1, - GATE_IP_MFC, GATE_IP_GEN, + GATE_IP_G2D, + GATE_IP_DISP0, + GATE_IP_DISP1, + GATE_IP_MFC, + GATE_IP_G3D, + GATE_IP_CDREX, + GATE_IP_CORE, GATE_IP_ACP, GATE_TOP_SCLK_GSCL, GATE_TOP_SCLK_DISP1, GATE_TOP_SCLK_MAU, GATE_TOP_SCLK_FSYS, GATE_TOP_SCLK_PERIC, - SRC_CDREX, - SRC_KFC, - DIV_KFC0, + GATE_BUS_DISP1, + GATE_BUS_FSYS0, + GATE_SCLK_CPU, + + SRC_MASK_FSYS, + SRC_MASK_DISP0_0, + SRC_MASK_DISP1_0, + SRC_MASK_PERIC0, + SRC_MASK_PERIC1, + SRC_MASK_MAU, + + CPLL_LOCK, + CPLL_CON0, + DPLL_LOCK, + DPLL_CON0, + IPLL_LOCK, + IPLL_CON0, + EPLL_LOCK, + EPLL_CON0, + EPLL_CON1, + VPLL_LOCK, + VPLL_CON0, + VPLL_CON1, }; /* list of all parent clocks */ @@ -158,42 +273,48 @@ PNAME(dpll_p) = { "fin_pll", "fout_dpll", }; PNAME(epll_p) = { "fin_pll", "fout_epll", }; PNAME(ipll_p) = { "fin_pll", "fout_ipll", }; -PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", }; -PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", }; +PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", }; +PNAME(mout_kfc_p) = { "mout_kpll", "mout_mpll", }; PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" }; PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" }; PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" }; -PNAME(mout_usbd3_p) = { "sclk_mpll_bpll", "fin_pll" }; - -PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", }; -PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", }; -PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", }; -PNAME(cpll_mpll_p) = { "sclk_cpll", "sclk_mpll_muxed", }; -PNAME(aclk200_disp1_p) = { "fin_pll", "div_aclk200", }; -PNAME(aclk300_disp0_p) = { "fin_pll", "div_aclk300_disp0", }; -PNAME(aclk300_disp1_p) = { "fin_pll", "div_aclk300_disp1", }; -PNAME(aclk300_gscl_p) = { "fin_pll", "div_aclk300_gscl", }; -PNAME(aclk300_jpeg_p) = { "fin_pll", "div_aclk300_jpeg", }; -PNAME(aclk333_sub_p) = { "fin_pll", "div_aclk333", }; +PNAME(mout_usbd3_p) = { "mout_mpll_bpll", "fin_pll" }; + +PNAME(mpll_user_p) = { "fin_pll", "mout_mpll", }; +PNAME(bpll_user_p) = { "fin_pll", "mout_bpll", }; +PNAME(mpll_bpll_p) = { "mout_mpll_user", "mout_bpll_user", }; +PNAME(cpll_mpll_p) = { "mout_cpll", "mout_mpll_user", }; +PNAME(cpll_vpll_p) = { "mout_cpll", "mout_vpll", }; +PNAME(aclk200_disp_p) = { "fin_pll", "div_aclk200", }; +PNAME(aclk266_gscl_p) = { "fin_pll", "div_aclk266_gscl_pre", }; +PNAME(aclk300_disp0_p) = { "fin_pll", "div_aclk300_disp0", }; +PNAME(aclk300_disp1_p) = { "fin_pll", "div_aclk300_disp1", }; +PNAME(aclk300_gscl_p) = { "fin_pll", "div_aclk300_gscl", }; +PNAME(aclk300_jpeg_p) = { "fin_pll", "div_aclk300_jpeg", }; +PNAME(aclk333_sub_p) = { "fin_pll", "div_aclk333", }; +PNAME(aclk333_432_gscl_p) = { "fin_pll", "div_aclk333_432_gscl", }; +PNAME(g3d_core_sub_p) = { "fin_pll", "div_g3d_core", }; +PNAME(g3d_hydra_sub_p) = { "fin_pll", "div_g3d_hydra", }; + PNAME(group2_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy", - "sclk_uhostphy", "sclk_hdmiphy", "sclk_mpll_bpll", - "sclk_dpll", "sclk_vpll", "sclk_cpll" }; + "sclk_uhostphy", "sclk_hdmiphy", "mout_mpll_bpll", + "mout_dpll", "mout_vpll", "mout_cpll" }; PNAME(audio0_p) = { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy", - "sclk_mpll_bpll", "sclk_epll", "sclk_vpll", "sclk_cpll" }; + "mout_mpll_bpll", "mout_epll", "mout_vpll", "mout_cpll" }; PNAME(audio1_p) = { "cdclk1", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy", - "sclk_mpll_bpll", "sclk_epll", "sclk_vpll", "sclk_cpll" }; + "mout_mpll_bpll", "mout_epll", "mout_vpll", "mout_cpll" }; PNAME(audio2_p) = { "cdclk2", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy", - "sclk_mpll_bpll", "sclk_epll", "sclk_vpll", "sclk_cpll" }; -PNAME(spdif_p) = { "dout_audio0", "dout_audio1", "dout_audio2", - "spdif_extclk" }; -PNAME(maudio0_p) = { "cdclk0", "fin_pll", "sclk_hdmi27m", + "mout_mpll_bpll", "mout_epll", "mout_vpll", "mout_cpll" }; +PNAME(spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2", + "spdifcdclk" }; +PNAME(mau_audio0_p) = { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy", - "sclk_mpll_bpll", "sclk_epll", "sclk_vpll", "sclk_cpll" }; + "mout_mpll_bpll", "mout_epll", "mout_vpll", "mout_cpll" }; static const struct samsung_pll_rate_table apll_tbl[] = { @@ -219,6 +340,7 @@ static const struct samsung_pll_rate_table apll_tbl[] = { PLL_35XX_RATE(400000000, 200, 3, 2), PLL_35XX_RATE(300000000, 100, 2, 2), PLL_35XX_RATE(200000000, 200, 3, 3), + PLL_35XX_RATE(0, 0, 0, 0), }; /* The next 2 tables for CPLL and DPLL were copies from @@ -229,17 +351,49 @@ static const struct samsung_pll_rate_table cpll_tbl[] = { /* PLL_35XX_RATE(rate, m, p, s) */ PLL_35XX_RATE(666000000, 222, 4, 1), PLL_35XX_RATE(640000000, 160, 3, 1), - PLL_35XX_RATE(320000000, 160, 3, 2) + PLL_35XX_RATE(320000000, 160, 3, 2), + PLL_35XX_RATE(0, 0, 0, 0), }; static const struct samsung_pll_rate_table dpll_tbl[] = { /* sorted in descending order */ /* PLL_35XX_RATE(rate, m, p, s) */ - PLL_35XX_RATE(600000000, 200, 4, 1) + PLL_35XX_RATE(600000000, 200, 4, 1), + PLL_35XX_RATE(0, 0, 0, 0), +}; + + +/* + * The Exynos 5410 EPLL Clock is actually an PLL_2650, + * which is very similar to the PLL_36XX, except for the size + * of MDIV field. This field should have 10 bits and not 9. + * However, since the parameter MDIV for the table below + * is never above 2^9 - 1 = 511, we are in good shape. + */ +static const struct samsung_pll_rate_table epll_tbl[] = { + /* sorted in descending order */ + /* PLL_36XX_RATE(rate, m, p, s, k) */ + PLL_36XX_RATE(600000000, 100, 2, 1, 0), + PLL_36XX_RATE(400000000, 200, 3, 2, 0), + PLL_36XX_RATE(200000000, 200, 3, 3, 0), + PLL_36XX_RATE(180633600, 301, 5, 3, -3670), + PLL_36XX_RATE( 67737600, 452, 5, 5, -27263), + PLL_36XX_RATE( 49152000, 197, 3, 5, -25690), + PLL_36XX_RATE( 45158401, 181, 3, 5, -24012), + PLL_36XX_RATE(0, 0, 0, 0, 0), }; +static const struct samsung_pll_rate_table ipll_tbl[] = { + /* sorted in descending order */ + /* PLL_35XX_RATE(rate, m, p, s, k) */ + PLL_35XX_RATE(864000000, 288, 4, 1), + PLL_35XX_RATE(666000000, 222, 4, 1), + PLL_35XX_RATE(432000000, 288, 4, 2), + PLL_35XX_RATE(0, 0, 0, 0), +}; + static const struct samsung_pll_rate_table kpll_tbl[] = { /* sorted in descending order */ @@ -258,16 +412,10 @@ static const struct samsung_pll_rate_table kpll_tbl[] = { PLL_35XX_RATE(400000000, 200, 3, 2), PLL_35XX_RATE(300000000, 100, 2, 2), PLL_35XX_RATE(200000000, 200, 3, 3), + PLL_35XX_RATE(0, 0, 0, 0), }; -/* - * The Exynos 5410 VPLL Clock is actually an PLL_2650, - * which is very similar to the PLL_36XX, except for the size - * of MDIV field. This field should have 10 bits and not 9. - * However, since the parameter MDIV for the table below - * is never above 2^9 - 1 = 511, we are in good shape. - */ static const struct samsung_pll_rate_table vpll_tbl[] = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ @@ -281,31 +429,12 @@ static const struct samsung_pll_rate_table vpll_tbl[] = { PLL_36XX_RATE(266000000, 133, 3, 2, 0), PLL_36XX_RATE(177000000, 118, 2, 3, 0), PLL_36XX_RATE(123500000, 330, 4, 4, 0), - PLL_36XX_RATE( 89000000, 178, 3, 4, 0) + PLL_36XX_RATE( 89000000, 178, 3, 4, 0), + PLL_36XX_RATE(0, 0, 0, 0, 0), }; -static const struct samsung_pll_rate_table epll_tbl[] = { - /* sorted in descending order */ - /* PLL_36XX_RATE(rate, m, p, s, k) */ - PLL_36XX_RATE(600000000, 100, 2, 1, 0), - PLL_36XX_RATE(400000000, 200, 3, 2, 0), - PLL_36XX_RATE(200000000, 200, 3, 3, 0), - PLL_36XX_RATE(180633600, 301, 5, 3, 3670), - PLL_36XX_RATE( 67737600, 452, 5, 5, 27263), - PLL_36XX_RATE( 49152000, 197, 3, 5, 25690), - PLL_36XX_RATE( 45158400, 181, 3, 5, 24012), -}; - - -static const struct samsung_pll_rate_table ipll_tbl[] = { - /* sorted in descending order */ - /* PLL_35XX_RATE(rate, m, p, s, k) */ - PLL_35XX_RATE(864000000, 288, 4, 1), - PLL_35XX_RATE(666000000, 222, 4, 1), - PLL_35XX_RATE(432000000, 288, 4, 2), -}; /* fixed rate clocks generated outside the soc */ @@ -316,9 +445,15 @@ static struct samsung_fixed_rate_clock exynos5410_fixed_rate_ext_clks[] __initda /* fixed rate clocks generated inside the soc */ static struct samsung_fixed_rate_clock exynos5410_fixed_rate_clks[] __initdata = { FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), + FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000), + FRATE(0, "cdclk0", NULL, CLK_IS_ROOT, 16934400), + /* Do not trust the value of the frequencies below */ + FRATE(0, "cdclk1", NULL, CLK_IS_ROOT, 16934400), + FRATE(0, "cdclk2", NULL, CLK_IS_ROOT, 16934400), + FRATE(0, "spdifcdclk", NULL, CLK_IS_ROOT, 16934400), }; static struct samsung_mux_clock exynos5410_pll_pmux_clks[] __initdata = { @@ -332,23 +467,23 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = { MUX_A(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1, "mout_kpll"), MUX_A(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1, "mout_kfc"), - MUX_A(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1, "mout_mpll"), - MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1), + MUX_A(0, "mout_mpll", mpll_p, SRC_CPERI1, 8, 1, "mout_mpll"), + MUX(0, "mout_mpll_user", mpll_user_p, SRC_TOP2, 20, 1), - MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1), - MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1), - MUX_A(0, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1, "sclk_vpll"), + MUX(0, "mout_bpll", bpll_p, SRC_CDREX, 0, 1), + MUX(0, "mout_bpll_user", bpll_user_p, SRC_TOP2, 24, 1), + MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1), - MUX(CLK_SCLK_EPLL, "sclk_epll", epll_p, SRC_TOP2, 12, 1), - MUX(0, "sclk_ipll", ipll_p, SRC_TOP2, 14, 1), + MUX(0, "mout_ipll", ipll_p, SRC_TOP2, 14, 1), - MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1), - MUX_A(0, "sclk_dpll", dpll_p, SRC_TOP2, 10, 1, "sclk_dpll"), + MUX(0, "mout_cpll", cpll_p, SRC_TOP2, 8, 1), + MUX_A(CLK_MOUT_EPLL, "mout_epll", epll_p, SRC_TOP2, 12, 1, "mout_epll"), + MUX(0, "mout_dpll", dpll_p, SRC_TOP2, 10, 1), - MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1), + MUX(0, "mout_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1), /* MAU Block */ - MUX(0, "mout_maudio0", maudio0_p, SRC_MAU, 0, 4), + MUX(CLK_MOUT_MAU_AUDIO0, "mout_mau_audio0", mau_audio0_p, SRC_MAU, 0, 4), MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4), MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4), @@ -363,7 +498,7 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = { MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4), - MUX(0, "mout_spdif", spdif_p, SRC_PERIC0, 8, 2), + MUX(0, "mout_spdif", spdif_p, SRC_PERIC1, 8, 2), MUX(CLK_MOUT_AUDIO0, "mout_audio0", audio0_p, SRC_PERIC1, 12, 4), MUX(0, "mout_audio1", audio1_p, SRC_PERIC1, 0, 4), MUX(0, "mout_audio2", audio2_p, SRC_PERIC1, 4, 4), @@ -372,19 +507,23 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = { MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1), MUX(0, "mout_aclk333", cpll_mpll_p, SRC_TOP0, 16, 1), MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1), - MUX(0, "mout_aclk266_gscl", mpll_bpll_p, SRC_TOP1, 28, 1), + MUX(0, "mout_g3d", cpll_vpll_p, SRC_TOP0, 24, 1), + MUX(0, "mout_aclk266_gscl_pre", mpll_bpll_p, SRC_TOP1, 28, 1), - MUX_A(0, "mout_aclk200_disp1", aclk200_disp1_p, - SRC_TOP3, 4, 1, "aclk200_disp1"), + MUX(0, "mout_aclk200_disp0", aclk200_disp_p, SRC_TOP3, 0, 1), + MUX(0, "mout_aclk200_disp1", aclk200_disp_p, SRC_TOP3, 4, 1), MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1), MUX(0, "mout_fimd1", group2_p, SRC_DISP1_0, 0, 4), + MUX(0, "mout_acl266_gscl", aclk266_gscl_p, SRC_TOP3, 8, 1), MUX(0, "mout_aclk300_gscl", aclk300_gscl_p, SRC_TOP3, 17, 1), MUX(0, "mout_aclk300_disp0", aclk300_disp0_p, SRC_TOP3, 18, 1), - MUX_A(0, "mout_aclk300_disp1", aclk300_disp1_p, SRC_TOP3, 19, 1, - "aclk300_disp1"), + MUX(0, "mout_aclk300_disp1", aclk300_disp1_p, SRC_TOP3, 19, 1), MUX(0, "mout_aclk400_isp", mpll_bpll_p, SRC_TOP3, 20, 1), MUX(0, "mout_aclk333_sub", aclk333_sub_p, SRC_TOP3, 24, 1), - MUX(0, "mout_aclk300_jpeg", aclk300_jpeg_p, SRC_TOP3, 28, 1), + MUX(0, "mout_aclk333_432_gscl", aclk333_432_gscl_p, SRC_TOP3, 26, 1), + MUX(0, "mout_aclk300_jpeg", aclk300_jpeg_p, SRC_TOP3, 27, 1), + MUX(0, "mout_g3d_core_sub", g3d_core_sub_p, SRC_TOP3, 28, 1), + MUX(0, "mout_g3d_hydra_sub", g3d_hydra_sub_p, SRC_TOP3, 29, 1), }; static struct samsung_div_clock exynos5410_div_clks[] __initdata = { @@ -401,17 +540,17 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = { DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3), DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), - DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3), + DIV(0, "aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3), DIV(0, "div_aclk66", "aclk66_pre", DIV_TOP0, 0, 3), /* Audio Block */ - DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 0, 4), - DIV(0, "dout_maupcm0", "dout_maudio0", DIV_MAU, 4, 8), + DIV(0, "div_mau_audio0", "mout_mau_audio0", DIV_MAU, 0, 4), + DIV(0, "div_mau_pcm0", "sclk_mau_audio0", DIV_MAU, 4, 8), - DIV(CLK_SCLK_USBPHY300, "sclk_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4), - DIV(CLK_SCLK_USBPHY301, "sclk_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4), DIV(0, "div_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4), DIV(0, "div_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4), + DIV(CLK_DIV_USBPHY300, "div_usbphy300", "div_usbd300", DIV_FSYS0, 16, 4), + DIV(CLK_DIV_USBPHY301, "div_usbphy301", "div_usbd301", DIV_FSYS0, 20, 4), DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4), @@ -430,49 +569,49 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = { DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4), /* PCM */ - DIV(0, "dout_pcm", "dout_audio0", DIV_MAU, 4, 8), - DIV(0, "dout_pcm0", "dout_audio2", DIV_PERIC4, 20, 8), - DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC4, 4, 8), - DIV(0, "dout_pcm2", "dout_audio2", DIV_PERIC4, 12, 8), - /* this seems to overlap with "dout_audio2", which is strange */ + DIV(0, "div_pcm1", "div_audio1", DIV_PERIC4, 4, 8), + DIV(0, "div_pcm2", "div_audio2", DIV_PERIC4, 20, 8), /* Audio - I2S */ - DIV(0, "dout_i2s1", "dout_audio1", DIV_PERIC5, 0, 6), - DIV(0, "dout_i2s2", "dout_audio2", DIV_PERIC5, 8, 6), - DIV(0, "dout_audio0", "mout_audio0", DIV_PERIC5, 24, 4), - DIV(0, "dout_audio1", "mout_audio1", DIV_PERIC4, 0, 4), - DIV(0, "dout_audio2", "mout_audio2", DIV_PERIC4, 16, 4), + DIV(0, "div_i2s1", "div_audio1", DIV_PERIC5, 0, 6), + DIV(0, "div_i2s2", "div_audio2", DIV_PERIC5, 8, 6), + DIV(0, "div_audio0", "mout_audio0", DIV_PERIC5, 24, 4), + DIV(0, "div_audio1", "mout_audio1", DIV_PERIC4, 0, 4), + DIV(0, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4), DIV(0, "div_aclk166", "mout_aclk166", DIV_TOP0, 8, 3), - DIV_A(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3, "aclk200"), - DIV(0, "div_aclk266", "sclk_mpll_muxed", DIV_TOP0, 16, 3), + DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3), + DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3), DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3), DIV(0, "div_aclk400", "mout_aclk400", DIV_TOP0, 24, 3), - DIV(0, "div_aclk300_gscl", "sclk_dpll", DIV_TOP2, 8, 3), - DIV(0, "div_aclk300_disp0", "sclk_dpll", DIV_TOP2, 12, 3), - DIV_A(0, "div_aclk300_disp1", "sclk_dpll", DIV_TOP2, 16, 3, - "daclk300disp1"), - DIV(0, "div_aclk300_jpeg", "sclk_dpll", DIV_TOP2, 17, 3), - DIV(CLK_DIV_HDMI_PIXEL, "div_hdmi_pixel", "sclk_vpll", + DIV(0, "div_aclk266_gscl_pre", "mout_aclk266_gscl_pre", DIV_TOP2, 4, 3), + DIV(0, "div_aclk300_gscl", "mout_dpll", DIV_TOP2, 8, 3), + DIV(0, "div_aclk300_disp0", "mout_dpll", DIV_TOP2, 12, 3), + DIV(0, "div_aclk300_disp1", "mout_dpll", DIV_TOP2, 16, 3), + DIV(0, "div_aclk300_jpeg", "mout_dpll", DIV_TOP2, 28, 3), + DIV(0, "div_aclk333_432_gscl", "mout_ipll", DIV_TOP2, 24, 3), + DIV(0, "div_g3d_core", "mout_g3d", DIV_TOP3, 0, 3), + DIV(0, "div_g3d_hydra", "mout_g3d", DIV_TOP3, 3, 3), + DIV(CLK_DIV_HDMI_PIXEL, "div_hdmi_pixel", "mout_vpll", DIV_DISP1_0, 28, 4), DIV(0, "div_fimd1", "mout_fimd1", DIV_DISP1_0, 0, 4), + DIV(0, "div_sclk_jpeg", "mout_cpll", DIV_GEN, 4, 4), + DIV(0, "div_sclk_cdrex", "mout_bpll", DIV_CDREX, 24, 3), + DIV(0, "div_clk2x_phy", "div_sclk_cdrex", DIV_CDREX, 3, 5), + DIV(0, "div_cclk_cdrex", "div_clk2x_phy", DIV_CDREX, 8, 3), + DIV(0, "div_pclk_cdrex", "div_cclk_cdrex", DIV_CDREX, 28, 3), + + DIV(0, "div_aclk_acp", "mout_mpll", DIV_ACP, 0, 3), + DIV(0, "div_pclk_acp", "div_aclk_acp", DIV_ACP, 4, 3), }; static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { - GATE(CLK_MCT, "mct", "div_aclk66", GATE_IP_PERIS, 18, 0, 0), - GATE(CLK_TMU_APBIF, "tmu_apbif", "div_aclk66", - GATE_IP_PERIS, 21, CLK_IGNORE_UNUSED, 0), - GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1", SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2", SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_USBD300, "sclk_usbd300", "div_usbd300", - GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_USBD301, "sclk_usbd301", "div_usbd301", - GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "div_fimd1", GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", @@ -482,15 +621,23 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { GATE(CLK_SCLK_DP1, "sclk_dp1", "mout_aclk300_disp0", GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0), - GATE(CLK_PDMA0, "pdma0", "div_aclk200", GATE_IP_FSYS, 1, 0, 0), - GATE(CLK_PDMA1, "pdma1", "div_aclk200", GATE_IP_FSYS, 2, 0, 0), + GATE(CLK_PDMA0, "pdma0", "div_aclk200", GATE_BUS_FSYS0, 1, 0, 0), + GATE(CLK_PDMA1, "pdma1", "div_aclk200", GATE_BUS_FSYS0, 2, 0, 0), GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0), GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0), - - GATE(CLK_MMC0, "sdmmc0", "div_aclk200", GATE_BUS_FSYS0, 12, 0, 0), - GATE(CLK_MMC1, "sdmmc1", "div_aclk200", GATE_BUS_FSYS0, 13, 0, 0), - GATE(CLK_MMC2, "sdmmc2", "div_aclk200", GATE_BUS_FSYS0, 14, 0, 0), + GATE(CLK_SATA, "sata", "div_aclk200", GATE_IP_FSYS, 6, 0, 0), + GATE(CLK_USBOTG, "usbotg", "div_aclk200", GATE_IP_FSYS, 7, 0, 0), + GATE(CLK_MIPI_HSI, "mipi_hsi", "div_aclk200", GATE_IP_FSYS, 8, 0, 0), + GATE(CLK_MMC0, "sdmmc0", "div_aclk200", GATE_IP_FSYS, 12, 0, 0), + GATE(CLK_MMC1, "sdmmc1", "div_aclk200", GATE_IP_FSYS, 13, 0, 0), + GATE(CLK_MMC2, "sdmmc2", "div_aclk200", GATE_IP_FSYS, 14, 0, 0), + GATE(CLK_SROMC, "sromc", "div_aclk200", GATE_IP_FSYS, 17, 0, 0), + GATE(CLK_USB2, "usb2", "div_aclk200", GATE_IP_FSYS, 18, 0, 0), + GATE(CLK_USBPHY300, "usbphy300", "div_usbphy300", GATE_IP_FSYS, + 19, CLK_SET_RATE_PARENT, 0), + GATE(CLK_USBPHY301, "usbphy301", "div_usbphy301", GATE_IP_FSYS, + 20, CLK_SET_RATE_PARENT, 0), GATE(CLK_UART0, "uart0", "div_aclk66", GATE_IP_PERIC, 0, 0, 0), GATE(CLK_UART1, "uart1", "div_aclk66", GATE_IP_PERIC, 1, 0, 0), @@ -506,33 +653,66 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { GATE(CLK_I2C6, "i2c6", "div_aclk66", GATE_IP_PERIC, 12, 0, 0), GATE(CLK_I2C7, "i2c7", "div_aclk66", GATE_IP_PERIC, 13, 0, 0), GATE(CLK_I2C_HDMI, "i2c_hdmi", "div_aclk66", GATE_IP_PERIC, 14, 0, 0), - - /* Maudio Block */ - /* Not even sure if this is correct for exynos5410. */ - GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0", - GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0", - GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0), - + GATE(CLK_ADC, "adc", "div_aclk66", GATE_IP_PERIC, 15, 0, 0), + GATE(CLK_SPI0, "spi0", "div_aclk66", GATE_IP_PERIC, 16, 0, 0), + GATE(CLK_SPI1, "spi1", "div_aclk66", GATE_IP_PERIC, 17, 0, 0), + GATE(CLK_SPI2, "spi2", "div_aclk66", GATE_IP_PERIC, 18, 0, 0), + GATE(CLK_I2S0, "i2s0", "div_aclk66", GATE_IP_PERIC, 19, 0, 0), GATE(CLK_I2S1, "i2s1", "div_aclk66", GATE_IP_PERIC, 20, 0, 0), GATE(CLK_I2S2, "i2s2", "div_aclk66", GATE_IP_PERIC, 21, 0, 0), + GATE(CLK_PCM1, "pcm1", "div_aclk66", GATE_IP_PERIC, 22, 0, 0), + GATE(CLK_PCM2, "pcm2", "div_aclk66", GATE_IP_PERIC, 23, 0, 0), + GATE(CLK_PWM, "pwm", "div_aclk66", GATE_IP_PERIC, 24, 0, 0), + GATE(CLK_PCM0, "pcm0", "div_aclk66", GATE_IP_PERIC, 25, 0, 0), + GATE(CLK_SPDIF, "spdif", "div_aclk66", GATE_IP_PERIC, 26, 0, 0), + GATE(CLK_AC97, "ac97", "div_aclk66", GATE_IP_PERIC, 27, 0, 0), + GATE(CLK_KEYIF, "keyif", "div_aclk66", GATE_IP_PERIC, 28, 0, 0), + + GATE_A(CLK_CHIPID, "chipid", "div_aclk66", + GATE_IP_PERIS, 0, 0, 0, "chipid"), + GATE(CLK_SYSREG, "sysreg", "div_aclk66", + GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PMU_APBIF, "pmu_apbif", "div_aclk66", + GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_TOPPART, "cmu_toppart", "div_aclk66", + GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_CORE, "cmu_core", "div_aclk66", + GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_MEM, "cmu_mem", "div_aclk66", + GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC0, "tzpc0", "div_aclk66", GATE_IP_PERIS, 6, 0, 0), + GATE(CLK_TZPC1, "tzpc1", "div_aclk66", GATE_IP_PERIS, 7, 0, 0), + GATE(CLK_TZPC2, "tzpc2", "div_aclk66", GATE_IP_PERIS, 8, 0, 0), + GATE(CLK_TZPC3, "tzpc3", "div_aclk66", GATE_IP_PERIS, 9, 0, 0), + GATE(CLK_TZPC4, "tzpc4", "div_aclk66", GATE_IP_PERIS, 10, 0, 0), + GATE(CLK_TZPC5, "tzpc5", "div_aclk66", GATE_IP_PERIS, 11, 0, 0), + GATE(CLK_TZPC6, "tzpc6", "div_aclk66", GATE_IP_PERIS, 12, 0, 0), + GATE(CLK_TZPC7, "tzpc7", "div_aclk66", GATE_IP_PERIS, 13, 0, 0), + GATE(CLK_TZPC8, "tzpc8", "div_aclk66", GATE_IP_PERIS, 14, 0, 0), + GATE(CLK_TZPC9, "tzpc9", "div_aclk66", GATE_IP_PERIS, 15, 0, 0), + GATE(CLK_HDMI_CEC, "hdmi_cec", "div_aclk66", GATE_IP_PERIS, 16, 0, 0), + GATE(CLK_SECKEY_APBIF, "seckey_apbif", "div_aclk66", + GATE_IP_PERIS, 17, CLK_IGNORE_UNUSED, 0), + GATE(CLK_MCT, "mct", "div_aclk66", GATE_IP_PERIS, 18, 0, 0), + GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0), + GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0), + GATE(CLK_TMU_APBIF, "tmu_apbif", "div_aclk66", GATE_IP_PERIS, 21, 0, 0), - GATE_A(CLK_CHIPID, "chipid", "div_aclk66", GATE_IP_PERIS, 0, 0, 0, - "chipid"), - /* Copied from exynos5420, but again this might also - * be wrong. - */ + /* MAU audio Block */ + /* Not even sure if this is correct for exynos5410. */ + GATE(CLK_SCLK_MAU_AUDIO0, "sclk_mau_audio0", "div_mau_audio0", + SRC_MASK_MAU, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MAU_PCM0, "sclk_mau_pcm0", "div_mau_pcm0", + SRC_MASK_MAU, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_AUDIO0, "sclk_audio0", "div_audio0", + SRC_MASK_PERIC1, 12, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_AUDIO1, "sclk_audio1", "div_audio1", + SRC_MASK_PERIC1, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_AUDIO2, "sclk_audio2", "div_audio2", + SRC_MASK_PERIC1, 4, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", - GATE_TOP_SCLK_PERIC, 9, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_pcm1", - GATE_TOP_SCLK_PERIC, 15, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_PCM2, "sclk_pcm2", "dout_pcm2", - GATE_TOP_SCLK_PERIC, 16, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_I2S1, "sclk_i2s1", "dout_i2s1", - GATE_TOP_SCLK_PERIC, 17, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_I2S2, "sclk_i2s2", "dout_i2s2", - GATE_TOP_SCLK_PERIC, 18, CLK_SET_RATE_PARENT, 0), + SRC_MASK_PERIC1, 8, 0, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0), @@ -556,110 +736,92 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0), GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 1, 0, 0), GATE(CLK_SMMU_MFCR, "smmu_mfcr", "mout_aclk333_sub", GATE_IP_MFC, 2, 0, 0), - GATE(CLK_PWM, "pwm", "div_aclk66", GATE_IP_PERIC, 24, 0, 0), }; static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = { [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, apll_tbl), - [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, - CPLL_CON0, cpll_tbl), - [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, - MPLL_CON0, NULL), [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, BPLL_CON0, NULL), - [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK, - KPLL_CON0, kpll_tbl), - [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc", - VPLL_LOCK, VPLL_CON0, vpll_tbl), + [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, + CPLL_CON0, cpll_tbl), [dpll] = PLL(pll_35xx, CLK_FOUT_DPLL, "fout_dpll", "fin_pll", DPLL_LOCK, DPLL_CON0, dpll_tbl), [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK, EPLL_CON0, epll_tbl), [ipll] = PLL(pll_35xx, CLK_FOUT_IPLL, "fout_ipll", "fin_pll", IPLL_LOCK, IPLL_CON0, ipll_tbl), + [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK, + KPLL_CON0, kpll_tbl), + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0, NULL), + [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc", + VPLL_LOCK, VPLL_CON0, vpll_tbl), }; - - /* Auxiliary function to set the parent of a clock */ -static __init int set_parent_by_name(const char *cname, const char *pname) +static __init int _set_parent(const char *child_name, const char *parent_name) { - struct clk *child_p = NULL; - struct clk *parent_p = NULL; + struct clk *child = NULL; + struct clk *parent = NULL; int ret = -1; - child_p = clk_get(NULL, cname); - parent_p = clk_get(NULL, pname); - - if (!IS_ERR(child_p) && !IS_ERR(parent_p)) { - ret = clk_prepare(child_p); - if (ret == 0) { - pr_debug ("setting parent of `%s' to `%s'\n", - cname, pname); - - ret = clk_set_parent(child_p, parent_p); - if (ret < 0) { - pr_err("could not set parent `%s' -> `%s'\n", - cname, pname); - } - clk_unprepare(child_p); - } else { - pr_err("could not prepare child `%s': %d\n", - cname, ret); + child = __clk_lookup(child_name); + parent = __clk_lookup(parent_name); + + if (child && parent) { + pr_debug ("setting parent of `%s' to `%s'\n", + child_name, parent_name); + + ret = clk_set_parent(child, parent); + if (ret < 0) { + pr_err("could not set parent `%s' -> `%s'\n", + child_name, parent_name); } - clk_put(child_p); - clk_put(parent_p); } else { - if (IS_ERR(child_p)) { - pr_err("child lookup `%s' failed: %d\n", - cname, (int) child_p); - } else { - clk_put(child_p); + if (!child) { + pr_err("child lookup `%s' failed\n", child_name); } - if (IS_ERR(parent_p)) { - pr_err("parent lookup `%s' failed: %d\n", - pname, (int) parent_p); - } else { - clk_put(parent_p); + if (!parent) { + pr_err("parent lookup `%s' failed\n", parent_name); } } return ret; } /* Auxiliary function to set the clock rate */ -static __init int set_rate_by_name(const char *name, unsigned long rate) +static __init int _set_rate(const char *clk_name, unsigned long rate) { - struct clk *clock_p = NULL; + struct clk *clk; int ret = -1; - clock_p = clk_get(NULL, name); - - if (!IS_ERR(clock_p)) { - ret = clk_prepare(clock_p); - if (ret == 0) { - pr_debug ("setting rate of `%s' to %lu\n", - name, rate); - - ret = clk_set_rate(clock_p, rate); - if (ret < 0) { - pr_err("could not set rate `%s' to %lu\n", - name, rate); - } - clk_unprepare(clock_p); - } else { - pr_err("could not prepare clock `%s': %d\n", - name, ret); + clk = __clk_lookup(clk_name); + + if (clk) { + pr_debug ("setting rate of `%s' to %lu\n", clk_name, rate); + ret = clk_set_rate(clk, rate); + if (ret < 0) { + pr_err("could not set rate `%s' to %lu\n", + clk_name, rate); } - clk_put(clock_p); } else { - pr_err("clock lookup `%s' failed: %d\n", - name, (int) clock_p); + pr_err("clock lookup `%s' failed\n", clk_name); } return ret; } +/* Callback for PM Resume. */ +static void exynos5410_clk_pm_resume_callback(void *data) +{ + samsung_clk_pll_wait_locktime(__clk_lookup("fout_cpll")); + samsung_clk_pll_wait_locktime(__clk_lookup("fout_dpll")); + samsung_clk_pll_wait_locktime(__clk_lookup("fout_epll")); + samsung_clk_pll_wait_locktime(__clk_lookup("fout_ipll")); + samsung_clk_pll_wait_locktime(__clk_lookup("fout_vpll")); +} + + static struct of_device_id ext_clk_match[] __initdata = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { }, @@ -676,14 +838,15 @@ static void __init exynos5410_clk_init(struct device_node *np) samsung_clk_init(np, reg_base, CLK_NR_CLKS, exynos5410_clk_regs, ARRAY_SIZE(exynos5410_clk_regs), - NULL, 0); + NULL, 0, NULL, &exynos5410_clk_pm_resume_callback, + NULL); samsung_clk_of_register_fixed_ext(exynos5410_fixed_rate_ext_clks, ARRAY_SIZE(exynos5410_fixed_rate_ext_clks), ext_clk_match); samsung_clk_register_mux(exynos5410_pll_pmux_clks, ARRAY_SIZE(exynos5410_pll_pmux_clks)); samsung_clk_register_pll(exynos5410_plls, ARRAY_SIZE(exynos5410_plls), - reg_base); + reg_base); samsung_clk_register_fixed_rate(exynos5410_fixed_rate_clks, ARRAY_SIZE(exynos5410_fixed_rate_clks)); @@ -699,15 +862,32 @@ static void __init exynos5410_clk_init(struct device_node *np) * I've added this initialization code here because I do not * know where else to put it. */ - set_parent_by_name("sclk_vpll", "mout_vpllsrc"); - set_rate_by_name("fout_vpll", 350000000); - set_parent_by_name("sclk_vpll", "fout_vpll"); + _set_parent("mout_vpll", "mout_vpllsrc"); + _set_rate("fout_vpll", 350000000); + _set_parent("mout_vpll", "fout_vpll"); + + _set_rate("fout_cpll", 640000000); + _set_parent("mout_cpll", "fout_cpll"); + + _set_rate("fout_dpll", 600000000); + _set_parent("mout_dpll", "fout_dpll"); + + _set_rate("fout_ipll", 432000000); + _set_parent("mout_ipll", "fout_ipll"); + + _set_rate("fout_epll", 200000000); + _set_parent("mout_epll", "fout_epll"); + + _set_rate("div_aclk200", 200000000); + _set_parent("mout_aclk200_disp1", "div_aclk200"); + _set_parent("mout_aclk300_disp1", "div_aclk300_disp1"); - set_rate_by_name("fout_dpll", 600000000); - set_parent_by_name("aclk200_disp1", "aclk200"); - set_parent_by_name("sclk_dpll", "fout_dpll"); - set_parent_by_name("aclk300_disp1", "daclk300disp1"); + _set_rate("div_pcm0", 4000000); + _set_rate("div_pcm1", 4000000); + _set_rate("div_pcm2", 4000000); + _set_rate("div_aclk_acp", 267000000); + _set_rate("div_pclk_acp", 134000000); pr_debug("Exynos5410: clock setup completed.\n"); } diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 7ea884ad554d17..fdd9798dacc88b 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -779,7 +779,7 @@ static void __init exynos5420_clk_init(struct device_node *np) samsung_clk_init(np, reg_base, nr_clks, exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs), - NULL, 0); + NULL, 0, NULL, NULL, NULL); samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index f8658945bfd2a7..d72192768d40ec 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -114,7 +114,8 @@ static void __init exynos5440_clk_init(struct device_node *np) return; } - samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0); + samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0, + NULL, NULL, NULL); samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 6f631c9bdb4727..c773616f144365 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -64,13 +64,13 @@ static long samsung_pll_round_rate(struct clk_hw *hw, /* Maximum lock time can be 270 * PDIV cycles */ #define PLL35XX_LOCK_FACTOR (270) -#define PLL35XX_MDIV_MASK (0x3FF) -#define PLL35XX_PDIV_MASK (0x3F) -#define PLL35XX_SDIV_MASK (0x7) +#define PLL35XX_MDIV_MASK (0x3FF) +#define PLL35XX_PDIV_MASK (0x3F) +#define PLL35XX_SDIV_MASK (0x7) #define PLL35XX_LOCK_STAT_MASK (0x1) -#define PLL35XX_MDIV_SHIFT (16) -#define PLL35XX_PDIV_SHIFT (8) -#define PLL35XX_SDIV_SHIFT (0) +#define PLL35XX_MDIV_SHIFT (16) +#define PLL35XX_PDIV_SHIFT (8) +#define PLL35XX_SDIV_SHIFT (0) #define PLL35XX_LOCK_STAT_SHIFT (29) #define PLL35XX_ENABLE_SHIFT (31) @@ -103,6 +103,23 @@ static inline bool samsung_pll35xx_mp_change( return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv); } + +static int samsung_pll35xx_wait_locktime(struct clk_hw *hw) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp; + + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = readl_relaxed(pll->con_reg); + } while ((tmp & (1 << PLL35XX_ENABLE_SHIFT)) && + !(tmp & (1 << PLL35XX_LOCK_STAT_SHIFT))); + return 0; +} + + static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate) { @@ -145,14 +162,11 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(tmp, pll->con_reg); /* wait_lock_time */ - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & (PLL35XX_LOCK_STAT_MASK - << PLL35XX_LOCK_STAT_SHIFT))); - return 0; + return samsung_pll35xx_wait_locktime(hw); } + + static const struct clk_ops samsung_pll35xx_clk_ops = { .recalc_rate = samsung_pll35xx_recalc_rate, .round_rate = samsung_pll_round_rate, @@ -215,11 +229,26 @@ static inline bool samsung_pll36xx_mpk_change( rate->kdiv != old_kdiv); } +static int samsung_pll36xx_wait_locktime(struct clk_hw *hw) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp; + + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = readl_relaxed(pll->con_reg); + } while ((tmp & (1 << PLL36XX_ENABLE_SHIFT)) && + !(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT))); + return 0; +} + static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long parent_rate) { struct samsung_clk_pll *pll = to_clk_pll(hw); - u32 tmp, pll_con0, pll_con1; + u32 pll_con0, pll_con1; const struct samsung_pll_rate_table *rate; rate = samsung_get_pll_settings(pll, drate); @@ -260,12 +289,7 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(pll_con1, pll->con_reg + 4); /* wait_lock_time */ - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT))); - - return 0; + return samsung_pll36xx_wait_locktime(hw); } static const struct clk_ops samsung_pll36xx_clk_ops = { @@ -330,13 +354,35 @@ static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1, || old_afc != rate->afc); } +static int samsung_pll45xx_wait_locktime(struct clk_hw *hw) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + ktime_t start; + + + /* wait_lock_time */ + start = ktime_get(); + while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) { + ktime_t delta = ktime_sub(ktime_get(), start); + + if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { + pr_err("%s: could not lock PLL %s\n", + __func__, __clk_get_name(hw->clk)); + return -EFAULT; + } + + cpu_relax(); + } + return 0; +} + + static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate) { struct samsung_clk_pll *pll = to_clk_pll(hw); const struct samsung_pll_rate_table *rate; u32 con0, con1; - ktime_t start; /* Get required rate settings from table */ rate = samsung_get_pll_settings(pll, drate); @@ -388,20 +434,7 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(con0, pll->con_reg); /* Wait for locking. */ - start = ktime_get(); - while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) { - ktime_t delta = ktime_sub(ktime_get(), start); - - if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { - pr_err("%s: could not lock PLL %s\n", - __func__, __clk_get_name(hw->clk)); - return -EFAULT; - } - - cpu_relax(); - } - - return 0; + return samsung_pll45xx_wait_locktime(hw); } static const struct clk_ops samsung_pll45xx_clk_ops = { @@ -477,13 +510,35 @@ static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1, || old_kdiv != rate->kdiv); } +static int samsung_pll46xx_wait_locktime(struct clk_hw *hw) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + ktime_t start; + + + /* wait_lock_time */ + start = ktime_get(); + while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) { + ktime_t delta = ktime_sub(ktime_get(), start); + + if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { + pr_err("%s: could not lock PLL %s\n", + __func__, __clk_get_name(hw->clk)); + return -EFAULT; + } + + cpu_relax(); + } + return 0; +} + + static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate) { struct samsung_clk_pll *pll = to_clk_pll(hw); const struct samsung_pll_rate_table *rate; u32 con0, con1, lock; - ktime_t start; /* Get required rate settings from table */ rate = samsung_get_pll_settings(pll, drate); @@ -536,20 +591,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(con1, pll->con_reg + 0x4); /* Wait for locking. */ - start = ktime_get(); - while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) { - ktime_t delta = ktime_sub(ktime_get(), start); - - if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { - pr_err("%s: could not lock PLL %s\n", - __func__, __clk_get_name(hw->clk)); - return -EFAULT; - } - - cpu_relax(); - } - - return 0; + return samsung_pll46xx_wait_locktime(hw); } static const struct clk_ops samsung_pll46xx_clk_ops = { @@ -829,3 +871,35 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, for (cnt = 0; cnt < nr_pll; cnt++) _samsung_clk_register_pll(&pll_list[cnt], base); } + +int samsung_clk_pll_wait_locktime(struct clk *clk) +{ + struct clk_hw *hw = __clk_get_hw(clk); + struct samsung_clk_pll *pll; + if (!hw) return -EINVAL; + + pll = to_clk_pll(hw); + switch (pll->type) { + /* clk_ops for 35xx and 2550 are similar */ + case pll_35xx: + case pll_2550: + return samsung_pll35xx_wait_locktime(hw); + case pll_4500: + case pll_4502: + case pll_4508: + return samsung_pll45xx_wait_locktime(hw); + /* clk_ops for 36xx and 2650 are similar */ + case pll_36xx: + case pll_2650: + return samsung_pll36xx_wait_locktime(hw); + case pll_6552: + case pll_6553: + return 0; + case pll_4600: + case pll_4650: + case pll_4650c: + return samsung_pll46xx_wait_locktime(hw); + default: + return -EINVAL; + } +} diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 6c39030080fbed..89ff1702fc291d 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -93,4 +93,6 @@ extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset); +extern int samsung_clk_pll_wait_locktime(struct clk *clk); + #endif /* __SAMSUNG_CLK_PLL_H */ diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index afad1c80f36845..b7a6b4dc6032d5 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -24,6 +24,9 @@ static struct clk_onecell_data clk_data; #ifdef CONFIG_PM_SLEEP static struct samsung_clk_reg_dump *reg_dump; static unsigned long nr_reg_dump; +static clk_pm_suspend_callback suspend_cb; +static clk_pm_resume_callback resume_cb; +static void *cb_data; static int samsung_clk_suspend(void) { @@ -33,6 +36,10 @@ static int samsung_clk_suspend(void) for (i = 0; i < nr_reg_dump; i++, rd++) rd->value = readl_relaxed(reg_base + rd->offset); + if (suspend_cb != NULL) { + return (*suspend_cb)(cb_data); + } + return 0; } @@ -43,6 +50,10 @@ static void samsung_clk_resume(void) for (i = 0; i < nr_reg_dump; i++, rd++) writel_relaxed(rd->value, reg_base + rd->offset); + + if (resume_cb != NULL) { + (*resume_cb)(cb_data); + } } static struct syscore_ops samsung_clk_syscore_ops = { @@ -55,11 +66,15 @@ static struct syscore_ops samsung_clk_syscore_ops = { void __init samsung_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks, unsigned long *rdump, unsigned long nr_rdump, unsigned long *soc_rdump, - unsigned long nr_soc_rdump) + unsigned long nr_soc_rdump, clk_pm_suspend_callback suspend, + clk_pm_resume_callback resume, void *callback_data) { reg_base = base; #ifdef CONFIG_PM_SLEEP + suspend_cb = suspend; + resume_cb = resume; + cb_data = callback_data; if (rdump && nr_rdump) { unsigned int idx; reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump) diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 31b4174e7a5bfa..b86f910dc94a09 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -264,6 +264,16 @@ struct samsung_clk_reg_dump { u32 value; }; +/** + * Callbacks for PM suspend and resume. + * These functions should be registered using + * "samsung_clk_init" + * @data: callback parameter to be passed to the callbacks. + */ +typedef int (*clk_pm_suspend_callback)(void *data); +typedef void (*clk_pm_resume_callback)(void *data); + + /** * struct samsung_pll_clock: information about pll clock * @id: platform specific id of the clock. @@ -286,7 +296,7 @@ struct samsung_pll_clock { int lock_offset; enum samsung_pll_type type; const struct samsung_pll_rate_table *rate_table; - const char *alias; + const char *alias; }; #define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \ @@ -315,7 +325,8 @@ struct samsung_pll_clock { extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks, unsigned long *rdump, unsigned long nr_rdump, unsigned long *soc_rdump, - unsigned long nr_soc_rdump); + unsigned long nr_soc_rdump, clk_pm_suspend_callback suspend, + clk_pm_resume_callback resume, void *callback_data); extern void __init samsung_clk_of_register_fixed_ext( struct samsung_fixed_rate_clock *fixed_rate_clk, unsigned int nr_fixed_rate_clk, diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 2a671f38192455..97ee39a19907bb 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -186,6 +186,7 @@ struct hdmi_context { struct device *dev; struct drm_device *drm_dev; bool hpd; + bool is_soc_exynos5; bool powered; bool dvi_mode; struct mutex hdmi_mutex; @@ -1172,12 +1173,13 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) hdmi_conf_reset(hdata); hdmi_conf_init(hdata); mutex_unlock(&hdata->hdmi_mutex); - - hdmi_audio_init(hdata); + if (!hdata->is_soc_exynos5) + hdmi_audio_init(hdata); /* setting core registers */ hdmi_mode_apply(hdata); - hdmi_audio_control(hdata, true); + if (!hdata->is_soc_exynos5) + hdmi_audio_control(hdata, true); hdmi_regs_dump(hdata, "start"); } @@ -1773,6 +1775,54 @@ static struct of_device_id hdmi_match_types[] = { } }; +struct platform_device *hdmi_audio_device; + +int hdmi_register_audio_device(struct platform_device *pdev) +{ + struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); + struct hdmi_context *hdata = ctx->ctx; + struct platform_device *audio_dev; + int ret; + + audio_dev = platform_device_alloc("exynos-hdmi-audio", -1); + if (!audio_dev) { + DRM_ERROR("hdmi audio device allocation failed.\n"); + ret = -ENOMEM; + goto err; + } + + ret = platform_device_add_resources(audio_dev, pdev->resource, + pdev->num_resources); + if (ret) { + ret = -ENOMEM; + goto err_device; + } + + audio_dev->dev.of_node = of_get_next_child(pdev->dev.of_node, NULL); + audio_dev->dev.platform_data = (void *)hdata->hpd_gpio; + + ret = platform_device_add(audio_dev); + if (ret) { + DRM_ERROR("hdmi audio device add failed.\n"); + goto err_device; + } + + hdmi_audio_device = audio_dev; + return 0; + +err_device: + platform_device_put(audio_dev); + +err: + return ret; +} + +void hdmi_unregister_audio_device(void) +{ + platform_device_unregister(hdmi_audio_device); +} + + static int hdmi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1814,6 +1864,10 @@ static int hdmi_probe(struct platform_device *pdev) hdata->type = drv->type; hdata->hpd_gpio = pdata->hpd_gpio; hdata->dev = dev; + hdata->is_soc_exynos5 = of_device_is_compatible(dev->of_node, + "samsung,exynos5-hdmi"); + hdata->is_soc_exynos5 |= of_device_is_compatible(dev->of_node, + "samsung,exynos5410-hdmi"); ret = hdmi_resources_init(hdata); if (ret) { @@ -1868,7 +1922,7 @@ static int hdmi_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, hdata->irq, NULL, hdmi_irq_thread, IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED, "hdmi", drm_hdmi_ctx); if (ret) { DRM_ERROR("failed to register hdmi interrupt\n"); @@ -1881,10 +1935,19 @@ static int hdmi_probe(struct platform_device *pdev) /* register specific callbacks to common hdmi. */ exynos_hdmi_ops_register(&hdmi_ops); + if (hdata->is_soc_exynos5) { + printk(KERN_INFO "exynos_hdmi: registering hdmi-audio\n"); + ret = hdmi_register_audio_device(pdev); + if (ret) { + DRM_ERROR("hdmi-audio device registering failed.\n"); + goto err_hdmiphy; + } + } + pm_runtime_enable(dev); - + /* Here we force the initialization as DVI just as a fallback option */ - hdata->dvi_mode = true; + /* hdata->dvi_mode = true; */ return 0; @@ -1909,6 +1972,9 @@ static int hdmi_remove(struct platform_device *pdev) struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); struct hdmi_context *hdata = ctx->ctx; + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + hdmi_unregister_audio_device(); pm_runtime_disable(dev); /* hdmiphy driver */ diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index 453eeb1d34e24a..a9229487d15332 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -2,98 +2,147 @@ #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H /* core clocks */ -#define CLK_FOUT_APLL 1 -#define CLK_FOUT_CPLL 2 -#define CLK_FOUT_MPLL 3 -#define CLK_FOUT_BPLL 4 -#define CLK_FOUT_KPLL 5 -#define CLK_FOUT_VPLL 6 -#define CLK_FOUT_DPLL 7 -#define CLK_FOUT_EPLL 8 -#define CLK_FOUT_IPLL 9 -#define CLK_FIN_PLL 10 - -/* gate for special clocks (sclk) */ -#define CLK_SCLK_UART0 128 -#define CLK_SCLK_UART1 129 -#define CLK_SCLK_UART2 130 -#define CLK_SCLK_UART3 131 -#define CLK_SCLK_MMC0 132 -#define CLK_SCLK_MMC1 133 -#define CLK_SCLK_MMC2 134 -#define CLK_SCLK_HDMIPHY 135 -#define CLK_SCLK_PIXEL 136 -#define CLK_SCLK_HDMI 137 -#define CLK_SCLK_FIMD1 138 -#define CLK_SCLK_DP1 139 -#define CLK_SCLK_I2S1 140 -#define CLK_SCLK_I2S2 141 +#define CLK_FIN_PLL 1 +#define CLK_FOUT_APLL 2 +#define CLK_FOUT_BPLL 3 +#define CLK_FOUT_CPLL 4 +#define CLK_FOUT_DPLL 5 +#define CLK_FOUT_EPLL 6 +#define CLK_FOUT_IPLL 7 +#define CLK_FOUT_KPLL 8 +#define CLK_FOUT_MPLL 9 +#define CLK_FOUT_VPLL 10 + +/* some fixed rate clocks */ +#define CLK_SCLK_HDMIPHY 20 + + +/* gate clocks */ +#define CLK_SCLK_MMC0 50 +#define CLK_SCLK_MMC1 51 +#define CLK_SCLK_MMC2 52 + +#define CLK_SCLK_FIMD1 56 +#define CLK_SCLK_HDMI 57 +#define CLK_SCLK_PIXEL 58 +#define CLK_SCLK_DP1 59 +#define CLK_PDMA0 60 +#define CLK_PDMA1 61 +#define CLK_MDMA0 62 +#define CLK_MDMA1 63 +#define CLK_SATA 64 +#define CLK_USBOTG 65 +#define CLK_MIPI_HSI 66 + +#define CLK_MMC0 70 +#define CLK_MMC1 71 +#define CLK_MMC2 72 +#define CLK_SROMC 73 +#define CLK_USB2 74 +#define CLK_USBPHY300 75 +#define CLK_USBPHY301 76 + +#define CLK_UART0 80 +#define CLK_UART1 81 +#define CLK_UART2 82 +#define CLK_UART3 83 + +#define CLK_I2C0 90 +#define CLK_I2C1 91 +#define CLK_I2C2 92 +#define CLK_I2C3 93 +#define CLK_I2C4 94 +#define CLK_I2C5 95 +#define CLK_I2C6 96 +#define CLK_I2C7 97 +#define CLK_I2C_HDMI 98 +#define CLK_ADC 99 +#define CLK_SPI0 100 +#define CLK_SPI1 101 +#define CLK_SPI2 102 +#define CLK_I2S0 103 +#define CLK_I2S1 104 +#define CLK_I2S2 105 +#define CLK_PCM1 106 +#define CLK_PCM2 107 +#define CLK_PWM 108 +#define CLK_PCM0 109 +#define CLK_SPDIF 110 +#define CLK_AC97 111 +#define CLK_KEYIF 112 + +#define CLK_CHIPID 120 +#define CLK_SYSREG 121 +#define CLK_PMU_APBIF 122 +#define CLK_CMU_TOPPART 123 +#define CLK_CMU_CORE 124 +#define CLK_CMU_MEM 125 + +#define CLK_TZPC0 130 +#define CLK_TZPC1 131 +#define CLK_TZPC2 132 +#define CLK_TZPC3 133 +#define CLK_TZPC4 134 +#define CLK_TZPC5 135 +#define CLK_TZPC6 136 +#define CLK_TZPC7 137 +#define CLK_TZPC8 138 +#define CLK_TZPC9 139 +#define CLK_HDMI_CEC 140 +#define CLK_SECKEY_APBIF 141 +#define CLK_MCT 142 +#define CLK_WDT 143 +#define CLK_RTC 144 +#define CLK_TMU_APBIF 145 + +#define CLK_SCLK_MAU_AUDIO0 150 +#define CLK_SCLK_MAU_PCM0 151 +#define CLK_SCLK_AUDIO0 152 +#define CLK_SCLK_AUDIO1 153 +#define CLK_SCLK_AUDIO2 154 +#define CLK_SCLK_SPDIF 155 + +#define CLK_SCLK_UART0 160 +#define CLK_SCLK_UART1 161 +#define CLK_SCLK_UART2 162 +#define CLK_SCLK_UART3 163 + +#define CLK_FIMD1 170 +#define CLK_MIE1 171 +#define CLK_DSIM1 172 +#define CLK_DP 173 +#define CLK_MIXER 174 +#define CLK_HDMI 175 + +#define CLK_GSCL0 180 +#define CLK_GSCL1 181 +#define CLK_GSCL2 182 +#define CLK_GSCL3 183 +#define CLK_GSCL4 184 + +#define CLK_MFC 190 +#define CLK_SMMU_MFCL 191 +#define CLK_SMMU_MFCR 192 + + +#define CLK_SCLK_I2S1 63 +#define CLK_SCLK_I2S2 64 #define CLK_SCLK_PCM1 142 #define CLK_SCLK_PCM2 143 -#define CLK_SCLK_SPDIF 144 -#define CLK_SCLK_MAUDIO0 148 -#define CLK_SCLK_MAUPCM0 149 -#define CLK_SCLK_USBD300 150 -#define CLK_SCLK_USBD301 151 -#define CLK_SCLK_USBPHY300 152 -#define CLK_SCLK_USBPHY301 153 -#define CLK_SCLK_EPLL 154 -/* gate clocks */ -#define CLK_UART0 257 -#define CLK_UART1 258 -#define CLK_UART2 259 -#define CLK_UART3 260 -#define CLK_I2C0 261 -#define CLK_I2C1 262 -#define CLK_I2C2 263 -#define CLK_I2C3 264 -#define CLK_I2C4 265 -#define CLK_I2C5 266 -#define CLK_I2C6 267 -#define CLK_I2C7 268 -#define CLK_I2C_HDMI 269 -#define CLK_I2S1 270 -#define CLK_I2S2 271 -#define CLK_CHIPID 272 - -#define CLK_PDMA0 275 -#define CLK_PDMA1 276 - -#define CLK_MCT 315 -#define CLK_TMU_APBIF 318 - -#define CLK_MDMA0 346 -#define CLK_MDMA1 347 - -#define CLK_MMC0 351 -#define CLK_MMC1 352 -#define CLK_MMC2 353 -#define CLK_MIXER 354 -#define CLK_HDMI 355 -#define CLK_FIMD1 356 -#define CLK_MIE1 357 -#define CLK_DSIM1 358 -#define CLK_DP 359 -#define CLK_GSCL0 360 -#define CLK_GSCL1 361 -#define CLK_GSCL2 362 -#define CLK_GSCL3 363 -#define CLK_GSCL4 364 -#define CLK_USBH20 365 -#define CLK_USBD300 366 -#define CLK_USBD301 367 -#define CLK_MFC 401 -#define CLK_SMMU_MFCL 402 -#define CLK_SMMU_MFCR 403 -#define CLK_PWM 404 /* Div clocks */ -#define CLK_DIV_HDMI_PIXEL 450 +#define CLK_DIV_HDMI_PIXEL 300 +#define CLK_DIV_USBPHY300 152 +#define CLK_DIV_USBPHY301 153 /* mux clocks */ -#define CLK_MOUT_HDMI 500 -#define CLK_MOUT_AUDIO0 501 +#define CLK_MOUT_EPLL 400 +#define CLK_MOUT_MAU_AUDIO0 401 +#define CLK_MOUT_AUDIO0 402 +#define CLK_MOUT_HDMI 403 + + #define CLK_NR_CLKS 512 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */ diff --git a/sound/soc/samsung/daisy_max98095.c b/sound/soc/samsung/daisy_max98095.c index b15b9fd65324db..f0882985202feb 100644 --- a/sound/soc/samsung/daisy_max98095.c +++ b/sound/soc/samsung/daisy_max98095.c @@ -34,6 +34,7 @@ #include #include "i2s.h" +#include "i2s-regs.h" #include "s3c-i2s-v2.h" #include "../codecs/max98095.h" #include "codec_plugin.h" @@ -193,8 +194,6 @@ static int daisy_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int bfs, psr, rfs, ret; unsigned long rclk; - unsigned long fin_rate; - struct clk *fin_pll; struct device *card_dev = substream->pcm->card->dev; switch (params_format(params)) { @@ -287,21 +286,13 @@ static int daisy_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - fin_pll = clk_get(NULL, "fin_pll"); - if (IS_ERR(fin_pll)) { - printk(KERN_ERR "%s: failed to get fin_pll clock\n", __func__); - return PTR_ERR(fin_pll); - } - - fin_rate = clk_get_rate(fin_pll); - clk_put(fin_pll); + ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk, SND_SOC_CLOCK_IN); - ret = snd_soc_dai_set_sysclk(codec_dai, 0, fin_rate, SND_SOC_CLOCK_IN); if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, - 0, SND_SOC_CLOCK_OUT); + rfs, SND_SOC_CLOCK_OUT); if (ret < 0) return ret; @@ -309,6 +300,17 @@ static int daisy_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, + 0, MOD_OPCLK_PCLK); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_1, + rclk, SND_SOC_CLOCK_OUT); + if (ret < 0) + return ret; + + return 0; } diff --git a/sound/soc/samsung/hdmi_audio.c b/sound/soc/samsung/hdmi_audio.c index 8b4aa2502171a4..6a68f43ee63182 100644 --- a/sound/soc/samsung/hdmi_audio.c +++ b/sound/soc/samsung/hdmi_audio.c @@ -40,13 +40,14 @@ struct hdmi_audio_params { }; struct hdmi_audio_params audio_params[] = { - { 32000, 27000, 4096, 0x3 }, - { 44100, 30000, 6272, 0x0 }, - { 88200, 30000, 12544, 0x8 }, - { 176400, 30000, 25088, 0xc }, - { 48000, 27000, 6144, 0x2 }, - { 96000, 27000, 12288, 0xa }, - { 192000, 27000, 24576, 0xe }, + { 32000, 27000, 4096, 0x3 }, + { 44100, 30000, 6272, 0x0 }, + { 48000, 27000, 6144, 0x2 }, + { 96000, 27000, 12288, 0xa }, + /* Not supported in 5410? */ + /* { 88200, 30000, 12544, 0x8 }, + { 176400, 30000, 25088, 0xc }, + { 192000, 27000, 24576, 0xe }, */ }; static inline u32 hdmi_reg_read(struct hdmi_audio_context *ctx, u32 reg_id) @@ -54,6 +55,12 @@ static inline u32 hdmi_reg_read(struct hdmi_audio_context *ctx, u32 reg_id) return readl(ctx->regs + reg_id); } +static inline void hdmi_reg_write(struct hdmi_audio_context *ctx, + u32 reg_id, u32 value) +{ + writel(value, ctx->regs + reg_id); +} + static inline void hdmi_reg_writeb(struct hdmi_audio_context *ctx, u32 reg_id, u8 value) { @@ -166,8 +173,12 @@ static void hdmi_audio_i2s_init(struct hdmi_audio_context *ctx) /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) | HDMI_I2S_SEL_LRCK(6)); - hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1) - | HDMI_I2S_SEL_SDATA2(4)); + if (ctx->params.chan_count == 6 || ctx->params.chan_count == 8) + val = HDMI_I2S_SEL_SDATA1(3) | HDMI_I2S_SEL_SDATA0(4); + else + val = HDMI_I2S_SEL_SDATA1(1) | HDMI_I2S_SEL_SDATA0(4); + + hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_1, val); hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) | HDMI_I2S_SEL_SDATA2(2)); hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); @@ -187,15 +198,71 @@ static void hdmi_audio_i2s_init(struct hdmi_audio_context *ctx) | HDMI_I2S_LINEAR_PCM | HDMI_I2S_CONSUMER_FORMAT); hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER); - hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0)); + + if (ctx->params.chan_count == 6 || ctx->params.chan_count == 8) { + hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_2, + HDMI_I2S_SET_SOURCE_NUM(0) | HDMI_I2S_SET_CHANNEL_NUM(0x6)); + hdmi_reg_writeb(ctx, HDMI_ASP_CON, + HDMI_AUD_MODE_MULTI_CH | HDMI_AUD_SP_AUD2_EN | + HDMI_AUD_SP_AUD1_EN | HDMI_AUD_SP_AUD0_EN); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG0, + HDMI_SPK0R_SEL_I_PCM0R | HDMI_SPK0L_SEL_I_PCM0L); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG1, + HDMI_SPK0L_SEL_I_PCM1R | HDMI_SPK0R_SEL_I_PCM1L); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG2, + HDMI_SPK0R_SEL_I_PCM2R | HDMI_SPK0L_SEL_I_PCM2L); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG3, + HDMI_SPK0R_SEL_I_PCM3R | HDMI_SPK0L_SEL_I_PCM3L); + } else { + hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0)); + hdmi_reg_writeb(ctx, HDMI_ASP_CON, + HDMI_AUD_NO_DST_DOUBLE | HDMI_AUD_TYPE_SAMPLE | + HDMI_AUD_MODE_TWO_CH | HDMI_AUD_SP_ALL_DIS); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG0, + HDMI_SPK0R_SEL_I_PCM0R | HDMI_SPK0L_SEL_I_PCM0L); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG1, + HDMI_SPK0R_SEL_I_PCM0R | HDMI_SPK0L_SEL_I_PCM0L); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG2, + HDMI_SPK0R_SEL_I_PCM0R | HDMI_SPK0L_SEL_I_PCM0L); + hdmi_reg_writeb(ctx, HDMI_ASP_CHCFG3, + HDMI_SPK0R_SEL_I_PCM0R | HDMI_SPK0L_SEL_I_PCM0L); + } + hdmi_reg_writeb(ctx, HDMI_ASP_SP_FLAT, HDMI_ASP_SP_FLAT_AUD_SAMPLE); + + hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2 | HDMI_I2S_SET_SMP_FREQ(sample_frq)); - hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_4, - HDMI_I2S_ORG_SMP_FREQ_44_1 - | HDMI_I2S_WORD_LEN_MAX24_24BITS - | HDMI_I2S_WORD_LEN_MAX_24BITS); + + if (bits_per_sample == 16) + val = HDMI_I2S_ORG_SMP_FREQ_44_1 | + HDMI_I2S_WORD_LEN_MAX20_16BITS | + HDMI_I2S_WORD_LEN_MAX_20BITS; + else if (bits_per_sample == 20) + val = HDMI_I2S_ORG_SMP_FREQ_44_1 | + HDMI_I2S_WORD_LEN_MAX24_20BITS | + HDMI_I2S_WORD_LEN_MAX_24BITS; + else + val = HDMI_I2S_ORG_SMP_FREQ_44_1 | + HDMI_I2S_WORD_LEN_MAX24_24BITS | + HDMI_I2S_WORD_LEN_MAX_24BITS; + hdmi_reg_write(ctx, HDMI_I2S_CH_ST_4, val); hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD); + +#if 0 + hdmi_reg_write(ctx, HDMI_I2S_MUX_CON, + HDMI_I2S_IN_ENABLE | HDMI_I2S_AUD_I2S + | HDMI_I2S_CUV_I2S_ENABLE | HDMI_I2S_MUX_ENABLE); + + hdmi_reg_write(ctx, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_L_EN + | HDMI_I2S_CH0_R_EN | HDMI_I2S_CH1_L_EN + | HDMI_I2S_CH1_R_EN | HDMI_I2S_CH2_L_EN + | HDMI_I2S_CH2_R_EN | HDMI_I2S_CH3_L_EN + | HDMI_I2S_CH3_R_EN); + + hdmi_reg_write(ctx, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_L_EN + | HDMI_I2S_CUV_R_EN); +#endif } static void hdmi_audio_init(struct hdmi_audio_context *ctx) @@ -231,6 +298,7 @@ static int hdmi_audio_control(struct hdmi_audio_context *ctx, HDMI_AUI_CON_TRANS_EVERY_VSYNC : HDMI_AUI_CON_NO_TRAN); hdmi_reg_writemask(ctx, HDMI_CON_0, onoff ? HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK); + hdmi_reg_writemask(ctx, HDMI_CON_0, 0, HDMI_CON_0_MASK); return 0; } @@ -256,6 +324,44 @@ static void hdmi_reg_infoframe(struct hdmi_audio_context *ctx, hdmi_reg_writeb(ctx, HDMI_AUI_HEADER1, infoframe->ver); hdmi_reg_writeb(ctx, HDMI_AUI_HEADER2, infoframe->len); hdr_sum = infoframe->type + infoframe->ver + infoframe->len; + + + /* + * AUI_BYTE(1)[2:0] : Audio Channel Count + * AUI_BYTE(4)[7:0] : Speaker Placement + */ + if (ctx->params.chan_count == 6) { + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(1), HDMI_AUI_DATA_CC_6CH); + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(4), HDMI_AUI_DATA_CA_6CH); + } else if (ctx->params.chan_count == 8) { + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(1), HDMI_AUI_DATA_CC_8CH); + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(4), HDMI_AUI_DATA_CA_8CH); + } else { + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(1), HDMI_AUI_DATA_CC_2CH); + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(4), HDMI_AUI_DATA_CA_2CH); + } + + /* AUI_BYTE(3)[7:0] : Should Be Zero */ + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(3), 0x00); + + /* AUI_BYTE(2)[4:2] : Sampling Frequency */ + if (ctx->params.sample_rate == 32000) + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SF_32); + else if (ctx->params.sample_rate == 48000) + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SF_48); + else if (ctx->params.sample_rate == 96000) + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SF_96); + else + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SF_44_1); + + /* AUI_BYTE(2)[1:0] : Sample Size */ + if (ctx->params.bits_per_sample == 16) + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SS_16BIT); + else if (ctx->params.bits_per_sample == 20) + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SS_20BIT); + else + hdmi_reg_writeb(ctx, HDMI_AUI_BYTE(2), HDMI_AUI_DATA_SS_24BIT); + chksum = hdmi_chksum(ctx, HDMI_AUI_BYTE(1), infoframe->len, hdr_sum); hdmi_reg_writeb(ctx, HDMI_AUI_CHECK_SUM, chksum); @@ -300,8 +406,8 @@ static int hdmi_audio_hw_params(struct device *dev, ctx = container_of(plugin, struct hdmi_audio_context, plugin); switch (params_channels(params)) { + case 8: case 6: - case 4: case 2: case 1: ctx->params.chan_count = params_channels(params); diff --git a/sound/soc/samsung/hdmi_audio.h b/sound/soc/samsung/hdmi_audio.h index f1c998d2b13d48..52a1a0a77f62ba 100644 --- a/sound/soc/samsung/hdmi_audio.h +++ b/sound/soc/samsung/hdmi_audio.h @@ -121,6 +121,7 @@ #define HDMI_ASP_EN (1 << 2) #define HDMI_ASP_DIS (0 << 2) #define HDMI_ASP_MASK (1 << 2) +#define HDMI_CON_0_MASK (0x9 << 3) #define HDMI_EN (1 << 0) /* HDMI_PHY_STATUS */ @@ -184,7 +185,7 @@ /* I2S_PIN_SEL_1 */ #define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) -#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) +#define HDMI_I2S_SEL_SDATA0(x) ((x) & 0x7) /* I2S_PIN_SEL_2 */ #define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) @@ -318,9 +319,121 @@ #define HDMI_AUI_CON_TRANS_ONCE (1 << 0) #define HDMI_AUI_CON_TRANS_EVERY_VSYNC (2 << 0) +/* AUI_DATA1~5 */ +#define HDMI_AUI_DATA_CC_2CH (0x1 << 0) +#define HDMI_AUI_DATA_CC_6CH (0x5 << 0) +#define HDMI_AUI_DATA_CC_8CH (0x7 << 0) +#define HDMI_AUI_DATA_SS_16BIT (0x1 << 0) +#define HDMI_AUI_DATA_SS_20BIT (0x2 << 0) +#define HDMI_AUI_DATA_SS_24BIT (0x3 << 0) +#define HDMI_AUI_DATA_SF_32 (0x1 << 2) +#define HDMI_AUI_DATA_SF_44_1 (0x2 << 2) +#define HDMI_AUI_DATA_SF_48 (0x3 << 2) +#define HDMI_AUI_DATA_SF_96 (0x5 << 2) +#define HDMI_AUI_DATA_CA_2CH (0x0 << 0) +#define HDMI_AUI_DATA_CA_6CH (0xb << 0) +#define HDMI_AUI_DATA_CA_8CH (0x13 << 0) + #define HDMI_VSI_CON_DO_NOT_TRANSMIT (0 << 0) #define HDMI_VSI_CON_EVERY_VSYNC (1 << 1) +/* ASP_CON */ +#define HDMI_AUD_DST_DOUBLE (1 << 7) +#define HDMI_AUD_NO_DST_DOUBLE (0 << 7) +#define HDMI_AUD_TYPE_SAMPLE (0 << 5) +#define HDMI_AUD_TYPE_ONE_BIT (1 << 5) +#define HDMI_AUD_TYPE_HBR (2 << 5) +#define HDMI_AUD_TYPE_DST (3 << 5) +#define HDMI_AUD_MODE_TWO_CH (0 << 4) +#define HDMI_AUD_MODE_MULTI_CH (1 << 4) +#define HDMI_AUD_SP_AUD3_EN (1 << 3) +#define HDMI_AUD_SP_AUD2_EN (1 << 2) +#define HDMI_AUD_SP_AUD1_EN (1 << 1) +#define HDMI_AUD_SP_AUD0_EN (1 << 0) +#define HDMI_AUD_SP_ALL_DIS (0 << 0) + +#define HDMI_AUD_SET_SP_PRE(x) ((x) & 0xF) + +/* ASP_SP_FLAT */ +#define HDMI_ASP_SP_FLAT_AUD_SAMPLE (0) + +/* ASP_CHCFG0/1/2/3 */ +#define HDMI_SPK3R_SEL_I_PCM0L (0 << 27) +#define HDMI_SPK3R_SEL_I_PCM0R (1 << 27) +#define HDMI_SPK3R_SEL_I_PCM1L (2 << 27) +#define HDMI_SPK3R_SEL_I_PCM1R (3 << 27) +#define HDMI_SPK3R_SEL_I_PCM2L (4 << 27) +#define HDMI_SPK3R_SEL_I_PCM2R (5 << 27) +#define HDMI_SPK3R_SEL_I_PCM3L (6 << 27) +#define HDMI_SPK3R_SEL_I_PCM3R (7 << 27) +#define HDMI_SPK3L_SEL_I_PCM0L (0 << 24) +#define HDMI_SPK3L_SEL_I_PCM0R (1 << 24) +#define HDMI_SPK3L_SEL_I_PCM1L (2 << 24) +#define HDMI_SPK3L_SEL_I_PCM1R (3 << 24) +#define HDMI_SPK3L_SEL_I_PCM2L (4 << 24) +#define HDMI_SPK3L_SEL_I_PCM2R (5 << 24) +#define HDMI_SPK3R_SEL_I_PCM3L (6 << 27) +#define HDMI_SPK3R_SEL_I_PCM3R (7 << 27) +#define HDMI_SPK3L_SEL_I_PCM0L (0 << 24) +#define HDMI_SPK3L_SEL_I_PCM0R (1 << 24) +#define HDMI_SPK3L_SEL_I_PCM1L (2 << 24) +#define HDMI_SPK3L_SEL_I_PCM1R (3 << 24) +#define HDMI_SPK3L_SEL_I_PCM2L (4 << 24) +#define HDMI_SPK3L_SEL_I_PCM2R (5 << 24) +#define HDMI_SPK3L_SEL_I_PCM3L (6 << 24) +#define HDMI_SPK3L_SEL_I_PCM3R (7 << 24) +#define HDMI_SPK2R_SEL_I_PCM0L (0 << 19) +#define HDMI_SPK2R_SEL_I_PCM0R (1 << 19) +#define HDMI_SPK2R_SEL_I_PCM1L (2 << 19) +#define HDMI_SPK2R_SEL_I_PCM1R (3 << 19) +#define HDMI_SPK2R_SEL_I_PCM2L (4 << 19) +#define HDMI_SPK2R_SEL_I_PCM2R (5 << 19) +#define HDMI_SPK2R_SEL_I_PCM3L (6 << 19) +#define HDMI_SPK2R_SEL_I_PCM3R (7 << 19) +#define HDMI_SPK2L_SEL_I_PCM0L (0 << 16) +#define HDMI_SPK2L_SEL_I_PCM0R (1 << 16) +#define HDMI_SPK2L_SEL_I_PCM1L (2 << 16) +#define HDMI_SPK2L_SEL_I_PCM1R (3 << 16) +#define HDMI_SPK2L_SEL_I_PCM2L (4 << 16) +#define HDMI_SPK2L_SEL_I_PCM2R (5 << 16) +#define HDMI_SPK2L_SEL_I_PCM3L (6 << 16) +#define HDMI_SPK2L_SEL_I_PCM3R (7 << 16) +#define HDMI_SPK1R_SEL_I_PCM0L (0 << 11) +#define HDMI_SPK1R_SEL_I_PCM0R (1 << 11) +#define HDMI_SPK1R_SEL_I_PCM1L (2 << 11) +#define HDMI_SPK1R_SEL_I_PCM1R (3 << 11) +#define HDMI_SPK1R_SEL_I_PCM2L (4 << 11) +#define HDMI_SPK1R_SEL_I_PCM2R (5 << 11) +#define HDMI_SPK1R_SEL_I_PCM3L (6 << 11) +#define HDMI_SPK1R_SEL_I_PCM3R (7 << 11) +#define HDMI_SPK1L_SEL_I_PCM0L (0 << 8) +#define HDMI_SPK1L_SEL_I_PCM0R (1 << 8) +#define HDMI_SPK1L_SEL_I_PCM1L (2 << 8) +#define HDMI_SPK1L_SEL_I_PCM1R (3 << 8) +#define HDMI_SPK1L_SEL_I_PCM2L (4 << 8) +#define HDMI_SPK1L_SEL_I_PCM2R (5 << 8) +#define HDMI_SPK1L_SEL_I_PCM3L (6 << 8) +#define HDMI_SPK1L_SEL_I_PCM3R (7 << 8) +#define HDMI_SPK0R_SEL_I_PCM0L (0 << 3) +#define HDMI_SPK0R_SEL_I_PCM0R (1 << 3) +#define HDMI_SPK0R_SEL_I_PCM1L (2 << 3) +#define HDMI_SPK0R_SEL_I_PCM1R (3 << 3) +#define HDMI_SPK0R_SEL_I_PCM2L (4 << 3) +#define HDMI_SPK0R_SEL_I_PCM2R (5 << 3) +#define HDMI_SPK0R_SEL_I_PCM3L (6 << 3) +#define HDMI_SPK0R_SEL_I_PCM3R (7 << 3) +#define HDMI_SPK0L_SEL_I_PCM0L (0) +#define HDMI_SPK0L_SEL_I_PCM0R (1) +#define HDMI_SPK0L_SEL_I_PCM1L (2) +#define HDMI_SPK0L_SEL_I_PCM1R (3) +#define HDMI_SPK0L_SEL_I_PCM2L (4) +#define HDMI_SPK0L_SEL_I_PCM2R (5) +#define HDMI_SPK0L_SEL_I_PCM3L (6) +#define HDMI_SPK0L_SEL_I_PCM3R (7) + + + + #define DEFAULT_RATE (44100) #define DEFAULT_BPS (16) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 37e47c92118b43..38c26c4d58c306 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -512,6 +512,10 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, u32 mod = readl(i2s->addr + I2SMOD); switch (clk_id) { + case SAMSUNG_I2S_OPCLK: + mod &= ~MOD_OPCLK_MASK; + mod |= dir; + break; case SAMSUNG_I2S_CDCLK: /* Shouldn't matter in GATING(CLOCK_IN) mode */ if (dir == SND_SOC_CLOCK_IN) @@ -564,6 +568,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, i2s->op_clk = clk_get(&i2s->pdev->dev, "i2s_opclk0"); clk_prepare_enable(i2s->op_clk); + clk_set_rate(i2s->op_clk, rfs); i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); /* Over-ride the other's */ @@ -659,10 +664,11 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, tmp |= MOD_SLAVE; break; case SND_SOC_DAIFMT_CBS_CFS: + tmp &= ~MOD_SLAVE; /* Set default source clock in Master mode */ - if (i2s->rclk_srcrate == 0) + /* if (i2s->rclk_srcrate == 0) i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0, - 0, SND_SOC_CLOCK_IN); + 0, SND_SOC_CLOCK_IN); */ break; default: dev_err(&i2s->pdev->dev, "master/slave format not supported\n"); diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h index 7966afc934db39..a1036714bde019 100644 --- a/sound/soc/samsung/i2s.h +++ b/sound/soc/samsung/i2s.h @@ -17,6 +17,8 @@ #define SAMSUNG_I2S_RCLKSRC_0 0 #define SAMSUNG_I2S_RCLKSRC_1 1 -#define SAMSUNG_I2S_CDCLK 2 +#define SAMSUNG_I2S_CDCLK 2 +#define SAMSUNG_I2S_OPCLK 3 + #endif /* __SND_SOC_SAMSUNG_I2S_H */