[alsa-devel] [PATCH 0/10] Add S/PDIF common driver for Samsung SoCs
Hi,
This patch-set is for new S/PDIF common driver that supports S/PDIF PCM audio on S5PC100, S5PC110 and S5PV210.
This patch-set is based on two different branches that :- o ASoC patches are based on Mark Brown's git branch 'for-next' (commit id - 135e44aaa47c22b66c8d2acb54da1106a6c17598) o ARM patches are based on Kukjin Kim's git branch 'for-next' (commit id - a9d09cac7485062c599ee8f341bb0c5ccc2cc9d6)
Based on these patches S/PDIF driver supports followings :- o Playback supports {32, 44.1, 48 and 96}kHz sampling rates. o Playback supports 16-bit Little-endian PCM format.
This patch-set contains followings :- o To Kukjin Kim and Ben Dooks, - [PATCH 1/10] ARM: S5PC100: Add S/PDIF platform device - [PATCH 2/10] ARM: S5PC100: Modify SCLK_AUDIO{0,1,2} clock as sysclks - [PATCH 3/10] ARM: S5PC100: Add SCLK_SPDIF clock - [PATCH 4/10] ARM: S5PV210: Add S/PDIF platform device - [PATCH 5/10] ARM: S5PV210: Add SCLK_SPDIF clock - [PATCH 6/10] ARM: S5PV210: Add audio clocks as sysclk - [PATCH 7/10] ARM: S5PV210: Fix wrong EPLL rate getting on setup clocks - [PATCH 8/10] ARM: S5PV210: Add EPLL clock operations o To Jassi Brar, Mark Brown and Liam Girdwood, - [PATCH 9/10] ASoC: SAMSUNG: Add S/PDIF CPU driver - [PATCH 10/10] ASoC: SAMSUNG: Add Machine driver for S/PDIF PCM audio
Best Regards, Claude(Seungwhan Youn)
This patch add S/PDIF platform device to support S/PDIF PCM audio on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pc100/dev-audio.c | 54 ++++++++++++++++++++++++++++ arch/arm/mach-s5pc100/include/mach/map.h | 2 + arch/arm/mach-s5pc100/mach-smdkc100.c | 4 ++ arch/arm/plat-samsung/include/plat/audio.h | 9 +++++ arch/arm/plat-samsung/include/plat/devs.h | 1 + 5 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c index a699ed6..9f7b17a 100644 --- a/arch/arm/mach-s5pc100/dev-audio.c +++ b/arch/arm/mach-s5pc100/dev-audio.c @@ -285,3 +285,57 @@ struct platform_device s5pc100_device_ac97 = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; + +/* S/PDIF Controller platform_device */ +static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev) +{ + s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3)); + + return 0; +} + +static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev) +{ + s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3)); + + return 0; +} + +static struct resource s5pc100_spdif_resource[] = { + [0] = { + .start = S5PC100_PA_SPDIF, + .end = S5PC100_PA_SPDIF + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPDIF, + .end = DMACH_SPDIF, + .flags = IORESOURCE_DMA, + }, +}; + +static struct s3c_audio_pdata s5p_spdif_pdata = { + .cfg_gpio = s5pc100_spdif_cfg_gpd, +}; + +static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32); + +struct platform_device s5pc100_device_spdif = { + .name = "samsung-spdif", + .id = -1, + .num_resources = ARRAY_SIZE(s5pc100_spdif_resource), + .resource = s5pc100_spdif_resource, + .dev = { + .platform_data = &s5p_spdif_pdata, + .dma_mask = &s5pc100_spdif_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +void __init s5pc100_spdif_setup_gpio(int gpio) +{ + if (gpio == S5PC100_SPDIF_GPD) + s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd; + else + s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3; +} diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index 8751ef4..32e9cab 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -110,6 +110,8 @@ #define S5PC100_PA_PCM0 0xF2400000 #define S5PC100_PA_PCM1 0xF2500000
+#define S5PC100_PA_SPDIF 0xF2600000 + #define S5PC100_PA_TSADC (0xF3000000)
/* KEYPAD */ diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 020c3f9..994a1e1 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -47,6 +47,7 @@ #include <plat/adc.h> #include <plat/keypad.h> #include <plat/ts.h> +#include <plat/audio.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */ #define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -196,6 +197,7 @@ static struct platform_device *smdkc100_devices[] __initdata = { &s5p_device_fimc0, &s5p_device_fimc1, &s5p_device_fimc2, + &s5pc100_device_spdif, };
static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { @@ -226,6 +228,8 @@ static void __init smdkc100_machine_init(void)
samsung_keypad_set_platdata(&smdkc100_keypad_data);
+ s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD); + /* LCD init */ gpio_request(S5PC100_GPD(0), "GPD"); gpio_request(S5PC100_GPH0(6), "GPH0"); diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h index e32f9ed..7712ff6 100644 --- a/arch/arm/plat-samsung/include/plat/audio.h +++ b/arch/arm/plat-samsung/include/plat/audio.h @@ -16,6 +16,15 @@ #define S3C64XX_AC97_GPE 1 extern void s3c64xx_ac97_setup_gpio(int);
+/* + * The machine init code calls s5p*_spdif_setup_gpio with + * one of these defines in order to select appropriate bank + * of GPIO for S/PDIF pins + */ +#define S5PC100_SPDIF_GPD 0 +#define S5PC100_SPDIF_GPG3 1 +extern void s5pc100_spdif_setup_gpio(int); + /** * struct s3c_audio_pdata - common platform data for audio device drivers * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 7d448e1..a1c3b93 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -106,6 +106,7 @@ extern struct platform_device s5pc100_device_pcm1; extern struct platform_device s5pc100_device_iis0; extern struct platform_device s5pc100_device_iis1; extern struct platform_device s5pc100_device_iis2; +extern struct platform_device s5pc100_device_spdif;
extern struct platform_device samsung_device_keypad;
On Mon, Oct 04, 2010 at 08:31:59PM +0900, Seungwhan Youn wrote:
This patch add S/PDIF platform device to support S/PDIF PCM audio on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
Seungwhan Youn wrote:
This patch add S/PDIF platform device to support S/PDIF PCM audio on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pc100/dev-audio.c | 54 ++++++++++++++++++++++++++++ arch/arm/mach-s5pc100/include/mach/map.h | 2 + arch/arm/mach-s5pc100/mach-smdkc100.c | 4 ++ arch/arm/plat-samsung/include/plat/audio.h | 9 +++++ arch/arm/plat-samsung/include/plat/devs.h | 1 + 5 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pc100/dev-audio.c
b/arch/arm/mach-s5pc100/dev-
audio.c index a699ed6..9f7b17a 100644 --- a/arch/arm/mach-s5pc100/dev-audio.c +++ b/arch/arm/mach-s5pc100/dev-audio.c @@ -285,3 +285,57 @@ struct platform_device s5pc100_device_ac97 = { .coherent_dma_mask = DMA_BIT_MASK(32), }, };
+/* S/PDIF Controller platform_device */ +static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev) +{
- s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3));
- return 0;
+}
+static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev) +{
- s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3));
- return 0;
+}
+static struct resource s5pc100_spdif_resource[] = {
- [0] = {
.start = S5PC100_PA_SPDIF,
.end = S5PC100_PA_SPDIF + 0x100 - 1,
.flags = IORESOURCE_MEM,
- },
- [1] = {
.start = DMACH_SPDIF,
.end = DMACH_SPDIF,
.flags = IORESOURCE_DMA,
- },
+};
+static struct s3c_audio_pdata s5p_spdif_pdata = {
- .cfg_gpio = s5pc100_spdif_cfg_gpd,
+};
+static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32);
+struct platform_device s5pc100_device_spdif = {
- .name = "samsung-spdif",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5pc100_spdif_resource),
- .resource = s5pc100_spdif_resource,
- .dev = {
.platform_data = &s5p_spdif_pdata,
.dma_mask = &s5pc100_spdif_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- },
+};
+void __init s5pc100_spdif_setup_gpio(int gpio) +{
- if (gpio == S5PC100_SPDIF_GPD)
s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd;
- else
s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3;
+} diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach- s5pc100/include/mach/map.h index 8751ef4..32e9cab 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -110,6 +110,8 @@ #define S5PC100_PA_PCM0 0xF2400000 #define S5PC100_PA_PCM1 0xF2500000
+#define S5PC100_PA_SPDIF 0xF2600000
#define S5PC100_PA_TSADC (0xF3000000)
/* KEYPAD */ diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach- s5pc100/mach-smdkc100.c index 020c3f9..994a1e1 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -47,6 +47,7 @@ #include <plat/adc.h> #include <plat/keypad.h> #include <plat/ts.h> +#include <plat/audio.h>
/* Following are default values for UCON, ULCON and UFCON UART registers
*/
#define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -196,6 +197,7 @@ static struct platform_device *smdkc100_devices[] __initdata = { &s5p_device_fimc0, &s5p_device_fimc1, &s5p_device_fimc2,
- &s5pc100_device_spdif,
};
static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { @@ -226,6 +228,8 @@ static void __init smdkc100_machine_init(void)
samsung_keypad_set_platdata(&smdkc100_keypad_data);
- s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD);
- /* LCD init */ gpio_request(S5PC100_GPD(0), "GPD"); gpio_request(S5PC100_GPH0(6), "GPH0");
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat- samsung/include/plat/audio.h index e32f9ed..7712ff6 100644 --- a/arch/arm/plat-samsung/include/plat/audio.h +++ b/arch/arm/plat-samsung/include/plat/audio.h @@ -16,6 +16,15 @@ #define S3C64XX_AC97_GPE 1 extern void s3c64xx_ac97_setup_gpio(int);
+/*
- The machine init code calls s5p*_spdif_setup_gpio with
- one of these defines in order to select appropriate bank
- of GPIO for S/PDIF pins
- */
+#define S5PC100_SPDIF_GPD 0 +#define S5PC100_SPDIF_GPG3 1 +extern void s5pc100_spdif_setup_gpio(int);
/**
- struct s3c_audio_pdata - common platform data for audio device drivers
- @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat- samsung/include/plat/devs.h index 7d448e1..a1c3b93 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -106,6 +106,7 @@ extern struct platform_device s5pc100_device_pcm1; extern struct platform_device s5pc100_device_iis0; extern struct platform_device s5pc100_device_iis1; extern struct platform_device s5pc100_device_iis2; +extern struct platform_device s5pc100_device_spdif;
extern struct platform_device samsung_device_keypad;
--
Ok...will apply.
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
This patch modify SCLK_AUDIO{0,1,2} to be initial as sysclks on boot-time.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pc100/clock.c | 72 ++++++++++++++++++++++------------------- 1 files changed, 39 insertions(+), 33 deletions(-)
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 084abd1..42b7138 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -848,6 +848,18 @@ struct clksrc_sources clk_src_group3 = { .nr_sources = ARRAY_SIZE(clk_src_group3_list), };
+static struct clksrc_clk clk_sclk_audio0 = { + .clk = { + .name = "sclk_audio", + .id = 0, + .ctrlbit = (1 << 8), + .enable = s5pc100_sclk1_ctrl, + }, + .sources = &clk_src_group3, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, +}; + static struct clk *clk_src_group4_list[] = { [0] = &clk_mout_epll.clk, [1] = &clk_div_mpll.clk, @@ -862,6 +874,18 @@ struct clksrc_sources clk_src_group4 = { .nr_sources = ARRAY_SIZE(clk_src_group4_list), };
+static struct clksrc_clk clk_sclk_audio1 = { + .clk = { + .name = "sclk_audio", + .id = 1, + .ctrlbit = (1 << 9), + .enable = s5pc100_sclk1_ctrl, + }, + .sources = &clk_src_group4, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, +}; + static struct clk *clk_src_group5_list[] = { [0] = &clk_mout_epll.clk, [1] = &clk_div_mpll.clk, @@ -875,6 +899,18 @@ struct clksrc_sources clk_src_group5 = { .nr_sources = ARRAY_SIZE(clk_src_group5_list), };
+static struct clksrc_clk clk_sclk_audio2 = { + .clk = { + .name = "sclk_audio", + .id = 2, + .ctrlbit = (1 << 10), + .enable = s5pc100_sclk1_ctrl, + }, + .sources = &clk_src_group5, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, +}; + static struct clk *clk_src_group6_list[] = { [0] = &s5p_clk_27m, [1] = &clk_vclk54m, @@ -1001,39 +1037,6 @@ static struct clksrc_clk clksrcs[] = { .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, }, { .clk = { - .name = "sclk_audio", - .id = 0, - .ctrlbit = (1 << 8), - .enable = s5pc100_sclk1_ctrl, - - }, - .sources = &clk_src_group3, - .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, - }, { - .clk = { - .name = "sclk_audio", - .id = 1, - .ctrlbit = (1 << 9), - .enable = s5pc100_sclk1_ctrl, - - }, - .sources = &clk_src_group4, - .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "sclk_audio", - .id = 2, - .ctrlbit = (1 << 10), - .enable = s5pc100_sclk1_ctrl, - - }, - .sources = &clk_src_group5, - .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, - }, { - .clk = { .name = "sclk_lcd", .id = -1, .ctrlbit = (1 << 0), @@ -1179,6 +1182,9 @@ static struct clksrc_clk *sysclks[] = { &clk_div_pclkd1, &clk_div_cam, &clk_div_hdmi, + &clk_sclk_audio0, + &clk_sclk_audio1, + &clk_sclk_audio2, };
void __init_or_cpufreq s5pc100_setup_clocks(void)
On Mon, Oct 04, 2010 at 08:39:16PM +0900, Seungwhan Youn wrote:
This patch modify SCLK_AUDIO{0,1,2} to be initial as sysclks on boot-time.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
Seungwhan Youn wrote:
This patch modify SCLK_AUDIO{0,1,2} to be initial as sysclks on boot-time.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pc100/clock.c | 72
++++++++++++++++++++++-------------------
1 files changed, 39 insertions(+), 33 deletions(-)
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 084abd1..42b7138 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -848,6 +848,18 @@ struct clksrc_sources clk_src_group3 = { .nr_sources = ARRAY_SIZE(clk_src_group3_list), };
+static struct clksrc_clk clk_sclk_audio0 = {
- .clk = {
.name = "sclk_audio",
.id = 0,
.ctrlbit = (1 << 8),
.enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_group3,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
+};
static struct clk *clk_src_group4_list[] = { [0] = &clk_mout_epll.clk, [1] = &clk_div_mpll.clk, @@ -862,6 +874,18 @@ struct clksrc_sources clk_src_group4 = { .nr_sources = ARRAY_SIZE(clk_src_group4_list), };
+static struct clksrc_clk clk_sclk_audio1 = {
- .clk = {
.name = "sclk_audio",
.id = 1,
.ctrlbit = (1 << 9),
.enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_group4,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
+};
static struct clk *clk_src_group5_list[] = { [0] = &clk_mout_epll.clk, [1] = &clk_div_mpll.clk, @@ -875,6 +899,18 @@ struct clksrc_sources clk_src_group5 = { .nr_sources = ARRAY_SIZE(clk_src_group5_list), };
+static struct clksrc_clk clk_sclk_audio2 = {
- .clk = {
.name = "sclk_audio",
.id = 2,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_group5,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
+};
static struct clk *clk_src_group6_list[] = { [0] = &s5p_clk_27m, [1] = &clk_vclk54m, @@ -1001,39 +1037,6 @@ static struct clksrc_clk clksrcs[] = { .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, }, { .clk = {
.name = "sclk_audio",
.id = 0,
.ctrlbit = (1 << 8),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group3,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
- }, {
.clk = {
.name = "sclk_audio",
.id = 1,
.ctrlbit = (1 << 9),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group4,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
- }, {
.clk = {
.name = "sclk_audio",
.id = 2,
.ctrlbit = (1 << 10),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_group5,
.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
- }, {
.clk = { .name = "sclk_lcd", .id = -1, .ctrlbit = (1 << 0),
@@ -1179,6 +1182,9 @@ static struct clksrc_clk *sysclks[] = { &clk_div_pclkd1, &clk_div_cam, &clk_div_hdmi,
- &clk_sclk_audio0,
- &clk_sclk_audio1,
- &clk_sclk_audio2,
};
void __init_or_cpufreq s5pc100_setup_clocks(void)
Ok...will apply.
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pc100/clock.c | 59 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 42b7138..306ae74 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -980,6 +980,64 @@ struct clksrc_sources clk_src_pwi = { .nr_sources = ARRAY_SIZE(clk_src_pwi_list), };
+static struct clk *clk_sclk_spdif_list[] = { + [0] = &clk_sclk_audio0.clk, + [1] = &clk_sclk_audio1.clk, + [2] = &clk_sclk_audio2.clk, +}; + +struct clksrc_sources clk_src_sclk_spdif = { + .sources = clk_sclk_spdif_list, + .nr_sources = ARRAY_SIZE(clk_sclk_spdif_list), +}; + +static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *pclk; + int ret; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + ret = pclk->ops->set_rate(pclk, rate); + clk_put(pclk); + + return ret; +} + +static unsigned long s5pc100_spdif_get_rate(struct clk *clk) +{ + struct clk *pclk; + int rate; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + rate = pclk->ops->get_rate(clk); + clk_put(pclk); + + return rate; +} + +static struct clk_ops s5pc100_sclk_spdif_ops = { + .set_rate = s5pc100_spdif_set_rate, + .get_rate = s5pc100_spdif_get_rate, +}; + +static struct clksrc_clk clk_sclk_spdif = { + .clk = { + .name = "sclk_spdif", + .id = -1, + .ctrlbit = (1 << 11), + .enable = s5pc100_sclk1_ctrl, + .ops = &s5pc100_sclk_spdif_ops, + }, + .sources = &clk_src_sclk_spdif, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 }, +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -1185,6 +1243,7 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_audio0, &clk_sclk_audio1, &clk_sclk_audio2, + &clk_sclk_spdif, };
void __init_or_cpufreq s5pc100_setup_clocks(void)
On Mon, Oct 04, 2010 at 08:42:25PM +0900, Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
but...
+static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *pclk;
- int ret;
This and the get() look like they're generic (they just proxy the operation on to the parent clock, which I imagine applies to a bunch of other clocks too.
On Tue, Oct 5, 2010 at 3:30 AM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Mon, Oct 04, 2010 at 08:42:25PM +0900, Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
but...
+static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *pclk;
- int ret;
This and the get() look like they're generic (they just proxy the operation on to the parent clock, which I imagine applies to a bunch of other clocks too.
Yes, that should apply to all Mux-Out and PAD 'clocks'. I plan to submit a patch to have that feature in Samsung clock API -- call parent's operators if the clock doesn't have one. Since that might be a controversial change and hence delays in acceptance (if at all), we decided to do that for the devices that need it for now.
Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PC100.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pc100/clock.c | 59 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 42b7138..306ae74 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -980,6 +980,64 @@ struct clksrc_sources clk_src_pwi = { .nr_sources = ARRAY_SIZE(clk_src_pwi_list), };
+static struct clk *clk_sclk_spdif_list[] = {
- [0] = &clk_sclk_audio0.clk,
- [1] = &clk_sclk_audio1.clk,
- [2] = &clk_sclk_audio2.clk,
+};
+struct clksrc_sources clk_src_sclk_spdif = {
- .sources = clk_sclk_spdif_list,
- .nr_sources = ARRAY_SIZE(clk_sclk_spdif_list),
+};
+static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *pclk;
- int ret;
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
return -EINVAL;
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
- return ret;
How about following?
static int parent_set_rate(struct clk *clk, unsigned long rate) { struct clk *p_clk; int ret; p_clk = clk_get_parent(clk); ret = clk_set_rate(p_clk, rate);
clk_put(p_clk);
return ret; }
Hmm...isn't there any method?...
+}
+static unsigned long s5pc100_spdif_get_rate(struct clk *clk) +{
- struct clk *pclk;
- int rate;
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
return -EINVAL;
- rate = pclk->ops->get_rate(clk);
- clk_put(pclk);
- return rate;
+}
Similar...
+static struct clk_ops s5pc100_sclk_spdif_ops = {
- .set_rate = s5pc100_spdif_set_rate,
- .get_rate = s5pc100_spdif_get_rate,
+};
+static struct clksrc_clk clk_sclk_spdif = {
- .clk = {
.name = "sclk_spdif",
.id = -1,
.ctrlbit = (1 << 11),
.enable = s5pc100_sclk1_ctrl,
.ops = &s5pc100_sclk_spdif_ops,
- },
- .sources = &clk_src_sclk_spdif,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 },
+};
static struct clksrc_clk clksrcs[] = { { .clk = { @@ -1185,6 +1243,7 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_audio0, &clk_sclk_audio1, &clk_sclk_audio2,
- &clk_sclk_spdif,
};
void __init_or_cpufreq s5pc100_setup_clocks(void)
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
Hi,
+static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *pclk;
- int ret;
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
- return ret;
How about following?
static int parent_set_rate(struct clk *clk, unsigned long rate) { struct clk *p_clk; int ret;
p_clk = clk_get_parent(clk); ret = clk_set_rate(p_clk, rate);
clk_put(p_clk);
return ret; }
Hmm...isn't there any method?...
I think you mean is that adds a new clock api function that sets parent clock rate.(am I right?) But as you know, this also needs that S/PDIF knows it's source clock can not set rate directly and set it's parent clock.
Actually my point was that I want to make S/PDIF does not care about clock characteristics, so I did make it solve in clock part, not in audio driver. And also, I do not want to modify a common function 'clk_set_rate()' that can support jassi's opinion, because I'm not sure about side effect that I can not grantee it's safety with other drivers.
(snip)
Thanks, Claude
Seungwhan Youn wrote:
Hi,
+static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) +{
struct clk *pclk;
int ret;
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
return -EINVAL;
ret = pclk->ops->set_rate(pclk, rate);
clk_put(pclk);
return ret;
How about following?
static int parent_set_rate(struct clk *clk, unsigned long rate) { struct clk *p_clk; int ret;
p_clk = clk_get_parent(clk); ret = clk_set_rate(p_clk, rate); clk_put(p_clk); return ret;
}
Hmm...isn't there any method?...
I think you mean is that adds a new clock api function that sets parent clock rate.(am I right?) But as you know, this also needs that
If possible?...yes.
S/PDIF knows it's source clock can not set rate directly and set it's parent clock.
Hmm...ok.
Actually my point was that I want to make S/PDIF does not care about clock characteristics, so I did make it solve in clock part, not in audio driver. And also, I do not want to modify a common function 'clk_set_rate()' that can support jassi's opinion, because I'm not sure about side effect that I can not grantee it's safety with other drivers.
Oh yes...it's expected recursive lockup or any side effect in this case.
Ok...Firstly will apply this...but we need to sort out this later.
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
This patch add S/PDIF platform device to support S/PDIF PCM audio on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pv210/dev-audio.c | 40 +++++++++++++++++++++++++++++ arch/arm/mach-s5pv210/include/mach/map.h | 3 ++ arch/arm/mach-s5pv210/mach-smdkc110.c | 1 + arch/arm/mach-s5pv210/mach-smdkv210.c | 1 + arch/arm/plat-samsung/include/plat/devs.h | 1 + 5 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c index 21dc6cf..4a02cdd 100644 --- a/arch/arm/mach-s5pv210/dev-audio.c +++ b/arch/arm/mach-s5pv210/dev-audio.c @@ -325,3 +325,43 @@ struct platform_device s5pv210_device_ac97 = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; + +/* S/PDIF Controller platform_device */ + +static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev) +{ + s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3)); + + return 0; +} + +static struct resource s5pv210_spdif_resource[] = { + [0] = { + .start = S5PV210_PA_SPDIF, + .end = S5PV210_PA_SPDIF + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_SPDIF, + .end = DMACH_SPDIF, + .flags = IORESOURCE_DMA, + }, +}; + +static struct s3c_audio_pdata samsung_spdif_pdata = { + .cfg_gpio = s5pv210_spdif_cfg_gpio, +}; + +static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32); + +struct platform_device s5pv210_device_spdif = { + .name = "samsung-spdif", + .id = -1, + .num_resources = ARRAY_SIZE(s5pv210_spdif_resource), + .resource = s5pv210_spdif_resource, + .dev = { + .platform_data = &samsung_spdif_pdata, + .dma_mask = &s5pv210_spdif_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index 12a409f..9669f69 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -84,6 +84,9 @@ #define S5PV210_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5PV210_PA_SDRAM
+/* S/PDIF */ +#define S5PV210_PA_SPDIF 0xE1100000 + /* I2S */ #define S5PV210_PA_IIS0 0xEEE30000 #define S5PV210_PA_IIS1 0xE2100000 diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c index 8211bb8..a282513 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -81,6 +81,7 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = { static struct platform_device *smdkc110_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97, + &s5pv210_device_spdif, &s3c_device_cfcon, &s3c_device_i2c0, &s3c_device_i2c1, diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index fbbc0a3..c38c110 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -103,6 +103,7 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = { static struct platform_device *smdkv210_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97, + &s5pv210_device_spdif, &s3c_device_adc, &s3c_device_cfcon, &s3c_device_hsmmc0, diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index a1c3b93..328b40d 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -87,6 +87,7 @@ extern struct platform_device s5pv210_device_pcm2; extern struct platform_device s5pv210_device_iis0; extern struct platform_device s5pv210_device_iis1; extern struct platform_device s5pv210_device_iis2; +extern struct platform_device s5pv210_device_spdif;
extern struct platform_device s5p6442_device_pcm0; extern struct platform_device s5p6442_device_pcm1;
On Mon, Oct 04, 2010 at 08:46:40PM +0900, Seungwhan Youn wrote:
This patch add S/PDIF platform device to support S/PDIF PCM audio on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
Seungwhan Youn wrote:
This patch add S/PDIF platform device to support S/PDIF PCM audio on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/dev-audio.c | 40 +++++++++++++++++++++++++++++ arch/arm/mach-s5pv210/include/mach/map.h | 3 ++ arch/arm/mach-s5pv210/mach-smdkc110.c | 1 + arch/arm/mach-s5pv210/mach-smdkv210.c | 1 + arch/arm/plat-samsung/include/plat/devs.h | 1 + 5 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/dev-audio.c
b/arch/arm/mach-s5pv210/dev-
audio.c index 21dc6cf..4a02cdd 100644 --- a/arch/arm/mach-s5pv210/dev-audio.c +++ b/arch/arm/mach-s5pv210/dev-audio.c @@ -325,3 +325,43 @@ struct platform_device s5pv210_device_ac97 = { .coherent_dma_mask = DMA_BIT_MASK(32), }, };
+/* S/PDIF Controller platform_device */
+static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev) +{
- s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3));
- return 0;
+}
+static struct resource s5pv210_spdif_resource[] = {
- [0] = {
.start = S5PV210_PA_SPDIF,
.end = S5PV210_PA_SPDIF + 0x100 - 1,
.flags = IORESOURCE_MEM,
- },
- [1] = {
.start = DMACH_SPDIF,
.end = DMACH_SPDIF,
.flags = IORESOURCE_DMA,
- },
+};
+static struct s3c_audio_pdata samsung_spdif_pdata = {
- .cfg_gpio = s5pv210_spdif_cfg_gpio,
+};
+static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32);
+struct platform_device s5pv210_device_spdif = {
- .name = "samsung-spdif",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5pv210_spdif_resource),
- .resource = s5pv210_spdif_resource,
- .dev = {
.platform_data = &samsung_spdif_pdata,
.dma_mask = &s5pv210_spdif_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- },
+}; diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach- s5pv210/include/mach/map.h index 12a409f..9669f69 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -84,6 +84,9 @@ #define S5PV210_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5PV210_PA_SDRAM
+/* S/PDIF */ +#define S5PV210_PA_SPDIF 0xE1100000
/* I2S */ #define S5PV210_PA_IIS0 0xEEE30000 #define S5PV210_PA_IIS1 0xE2100000 diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach- s5pv210/mach-smdkc110.c index 8211bb8..a282513 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -81,6 +81,7 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = { static struct platform_device *smdkc110_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97,
- &s5pv210_device_spdif, &s3c_device_cfcon, &s3c_device_i2c0, &s3c_device_i2c1,
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach- s5pv210/mach-smdkv210.c index fbbc0a3..c38c110 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -103,6 +103,7 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = { static struct platform_device *smdkv210_devices[] __initdata = { &s5pv210_device_iis0, &s5pv210_device_ac97,
- &s5pv210_device_spdif, &s3c_device_adc, &s3c_device_cfcon, &s3c_device_hsmmc0,
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat- samsung/include/plat/devs.h index a1c3b93..328b40d 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -87,6 +87,7 @@ extern struct platform_device s5pv210_device_pcm2; extern struct platform_device s5pv210_device_iis0; extern struct platform_device s5pv210_device_iis1; extern struct platform_device s5pv210_device_iis2; +extern struct platform_device s5pv210_device_spdif;
extern struct platform_device s5p6442_device_pcm0; extern struct platform_device s5p6442_device_pcm1; --
Ok...will apply.
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pv210/clock.c | 62 +++++++++++++++++++++++++++++++++++------ 1 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d562670..195a088 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -431,6 +431,12 @@ static struct clk init_clocks_disable[] = { .parent = &clk_p, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1 << 6), + }, { + .name = "spdif", + .id = -1, + .parent = &clk_p, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 0), }, };
@@ -660,6 +666,53 @@ static struct clksrc_sources clkset_sclk_spdif = { .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), };
+static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *pclk; + int ret; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + ret = pclk->ops->set_rate(pclk, rate); + clk_put(pclk); + + return ret; +} + +static unsigned long s5pv210_spdif_get_rate(struct clk *clk) +{ + struct clk *pclk; + int rate; + + pclk = clk_get_parent(clk); + if (IS_ERR(pclk)) + return -EINVAL; + + rate = pclk->ops->get_rate(clk); + clk_put(pclk); + + return rate; +} + +static struct clk_ops s5pv210_sclk_spdif_ops = { + .set_rate = s5pv210_spdif_set_rate, + .get_rate = s5pv210_spdif_get_rate, +}; + +static struct clksrc_clk clk_sclk_spdif = { + .clk = { + .name = "sclk_spdif", + .id = -1, + .enable = s5pv210_clk_mask0_ctrl, + .ctrlbit = (1 << 27), + .ops = &s5pv210_sclk_spdif_ops, + }, + .sources = &clkset_sclk_spdif, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, +}; + static struct clk *clkset_group2_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, @@ -744,15 +797,6 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_sclk_mixer, .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, }, { - .clk = { - .name = "sclk_spdif", - .id = -1, - .enable = s5pv210_clk_mask0_ctrl, - .ctrlbit = (1 << 27), - }, - .sources = &clkset_sclk_spdif, - .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, - }, { .clk = { .name = "sclk_fimc", .id = 0,
On Mon, Oct 04, 2010 at 08:52:34PM +0900, Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
but this looks like an example of where the get and set rate operations could readily be shared as mentioned in reply to the previous patch.
On Tue, Oct 5, 2010 at 3:39 AM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Mon, Oct 04, 2010 at 08:52:34PM +0900, Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
but this looks like an example of where the get and set rate operations could readily be shared as mentioned in reply to the previous patch.
Please see this in context of my reply to your previous comment.
Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 62 +++++++++++++++++++++++++++++++++++------ 1 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d562670..195a088 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -431,6 +431,12 @@ static struct clk init_clocks_disable[] = { .parent = &clk_p, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1 << 6),
- }, {
.name = "spdif",
.id = -1,
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
},.ctrlbit = (1 << 0),
};
@@ -660,6 +666,53 @@ static struct clksrc_sources clkset_sclk_spdif = { .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), };
+static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *pclk;
- int ret;
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
return -EINVAL;
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
- return ret;
+}
Similar with previous reply...please refer to it...
+static unsigned long s5pv210_spdif_get_rate(struct clk *clk) +{
- struct clk *pclk;
- int rate;
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
return -EINVAL;
- rate = pclk->ops->get_rate(clk);
- clk_put(pclk);
- return rate;
+}
+static struct clk_ops s5pv210_sclk_spdif_ops = {
- .set_rate = s5pv210_spdif_set_rate,
- .get_rate = s5pv210_spdif_get_rate,
+};
+static struct clksrc_clk clk_sclk_spdif = {
- .clk = {
.name = "sclk_spdif",
.id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 27),
.ops = &s5pv210_sclk_spdif_ops,
- },
- .sources = &clkset_sclk_spdif,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
+};
static struct clk *clkset_group2_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, @@ -744,15 +797,6 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_sclk_mixer, .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, }, {
.clk = {
.name = "sclk_spdif",
.id = -1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 27),
},
.sources = &clkset_sclk_spdif,
.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
- }, { .clk = { .name = "sclk_fimc", .id = 0,
--
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
On Fri, Oct 8, 2010 at 7:16 PM, Kukjin Kim kgene.kim@samsung.com wrote:
Seungwhan Youn wrote:
This patch add SCLK_SPDIF clock to support source clock of S/PDIF on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 62 +++++++++++++++++++++++++++++++++++------ 1 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d562670..195a088 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -431,6 +431,12 @@ static struct clk init_clocks_disable[] = { .parent = &clk_p, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1 << 6),
- }, {
- .name = "spdif",
- .id = -1,
- .parent = &clk_p,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 0),
}, };
@@ -660,6 +666,53 @@ static struct clksrc_sources clkset_sclk_spdif = { .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), };
+static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate) +{
- struct clk *pclk;
- int ret;
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
- return ret;
+}
Similar with previous reply...please refer to it...
Please refer my previous reply on "[PATCH 3/10] ARM: S5PC100: Add SCLK_SPDIF clock".
(snip)
Thanks, Claude
This patch adds audio clocks(SCLK_AUDIO{0,1,2} and SCLK_AUDIO) to be initial as a sysclk on boot-time.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pv210/clock.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 195a088..3f3b7ba 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -997,6 +997,10 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_dac, &clk_sclk_pixel, &clk_sclk_hdmi, + &clk_sclk_audio0, + &clk_sclk_audio1, + &clk_sclk_audio2, + &clk_sclk_spdif, };
void __init_or_cpufreq s5pv210_setup_clocks(void)
On Mon, Oct 04, 2010 at 08:57:48PM +0900, Seungwhan Youn wrote:
This patch adds audio clocks(SCLK_AUDIO{0,1,2} and SCLK_AUDIO) to be initial as a sysclk on boot-time.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
Acked-by: Mark Brown broonie@opensource.wolfsonmicro.com
Seungwhan Youn wrote:
This patch adds audio clocks(SCLK_AUDIO{0,1,2} and SCLK_AUDIO) to be initial as a sysclk on boot-time.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 195a088..3f3b7ba 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -997,6 +997,10 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_dac, &clk_sclk_pixel, &clk_sclk_hdmi,
- &clk_sclk_audio0,
- &clk_sclk_audio1,
- &clk_sclk_audio2,
- &clk_sclk_spdif,
};
void __init_or_cpufreq s5pv210_setup_clocks(void)
Ok...will apply.
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
This patch fix wrong EPLL getting on setup clocks on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pv210/clock.c | 3 ++- arch/arm/mach-s5pv210/include/mach/regs-clock.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 3f3b7ba..bcbe7e9 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -1040,7 +1040,8 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); - epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); + epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON0), + __raw_readl(S5P_EPLL_CON1)); vpllsrc = clk_get_rate(&clk_vpllsrc.clk); vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h index 499aef7..5968535 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h @@ -24,7 +24,8 @@
#define S5P_APLL_CON S5P_CLKREG(0x100) #define S5P_MPLL_CON S5P_CLKREG(0x108) -#define S5P_EPLL_CON S5P_CLKREG(0x110) +#define S5P_EPLL_CON0 S5P_CLKREG(0x110) +#define S5P_EPLL_CON1 S5P_CLKREG(0x114) #define S5P_VPLL_CON S5P_CLKREG(0x120)
#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
Seungwhan Youn wrote:
This patch fix wrong EPLL getting on setup clocks on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 3 ++- arch/arm/mach-s5pv210/include/mach/regs-clock.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 3f3b7ba..bcbe7e9 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -1040,7 +1040,8 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
- epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
- epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON0),
__raw_readl(S5P_EPLL_CON1));
Maybe you wanted to implement fractional PLL 4600B...not used 90xx in there. So need to update plat/pll.h to epll of s5pv210.
vpllsrc = clk_get_rate(&clk_vpllsrc.clk); vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON),
pll_4502);
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
b/arch/arm/mach-
s5pv210/include/mach/regs-clock.h index 499aef7..5968535 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h @@ -24,7 +24,8 @@
#define S5P_APLL_CON S5P_CLKREG(0x100) #define S5P_MPLL_CON S5P_CLKREG(0x108) -#define S5P_EPLL_CON S5P_CLKREG(0x110) +#define S5P_EPLL_CON0 S5P_CLKREG(0x110) +#define S5P_EPLL_CON1 S5P_CLKREG(0x114) #define S5P_VPLL_CON S5P_CLKREG(0x120)
#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
On Fri, Oct 8, 2010 at 7:37 PM, Kukjin Kim kgene.kim@samsung.com wrote:
Seungwhan Youn wrote:
This patch fix wrong EPLL getting on setup clocks on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 3 ++- arch/arm/mach-s5pv210/include/mach/regs-clock.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 3f3b7ba..bcbe7e9 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -1040,7 +1040,8 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
- epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
- epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON0),
- __raw_readl(S5P_EPLL_CON1));
Maybe you wanted to implement fractional PLL 4600B...not used 90xx in there. So need to update plat/pll.h to epll of s5pv210.
Okay, I'll fix it and add PLL_4600B also.
Thanks, Claude
This patch adds EPLL specific clock get_rate/set_rate operations on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com --- arch/arm/mach-s5pv210/clock.c | 95 ++++++++++++++++++++++++++++++++++ arch/arm/plat-s5p/include/plat/pll.h | 2 + 2 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index bcbe7e9..affa5a0 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -1003,6 +1003,97 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_spdif, };
+static int s5pv210_epll_enable(struct clk *clk, int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + unsigned int epll_con = __raw_readl(S5P_EPLL_CON0) & ~ctrlbit; + + if (enable) + __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON0); + else + __raw_writel(epll_con, S5P_EPLL_CON0); + + return 0; +} + +static unsigned long s5pv210_epll_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static u32 epll_div[][6] = { + { 48000000, 0, 48, 3, 3, 0 }, + { 96000000, 0, 48, 3, 2, 0 }, + { 144000000, 1, 72, 3, 2, 0 }, + { 192000000, 0, 48, 3, 1, 0 }, + { 288000000, 1, 72, 3, 1, 0 }, + { 32750000, 1, 65, 3, 4, 35127 }, + { 32768000, 1, 65, 3, 4, 35127 }, + { 45158400, 0, 45, 3, 3, 10355 }, + { 45000000, 0, 45, 3, 3, 10355 }, + { 45158000, 0, 45, 3, 3, 10355 }, + { 49125000, 0, 49, 3, 3, 9961 }, + { 49152000, 0, 49, 3, 3, 9961 }, + { 67737600, 1, 67, 3, 3, 48366 }, + { 67738000, 1, 67, 3, 3, 48366 }, + { 73800000, 1, 73, 3, 3, 47710 }, + { 73728000, 1, 73, 3, 3, 47710 }, + { 36000000, 1, 32, 3, 4, 0 }, + { 60000000, 1, 60, 3, 3, 0 }, + { 72000000, 1, 72, 3, 3, 0 }, + { 80000000, 1, 80, 3, 3, 0 }, + { 84000000, 0, 42, 3, 2, 0 }, + { 50000000, 0, 50, 3, 3, 0 }, +}; + +static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + + /* Return if nothing changed */ + if (clk->rate == rate) + return 0; + + epll_con = __raw_readl(S5P_EPLL_CON0); + epll_con_k = __raw_readl(S5P_EPLL_CON1); + + epll_con_k &= ~(PLL90XX_KDIV_MASK << PLL90XX_KDIV_SHIFT); + epll_con &= ~(PLL90XX_VSEL_MASK << PLL90XX_VSEL_SHIFT | + PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT | + PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT | + PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con_k |= epll_div[i][5] << 0; + epll_con |= (epll_div[i][1] << PLL90XX_VSEL_SHIFT | + epll_div[i][2] << PLL90XX_MDIV_SHIFT | + epll_div[i][3] << PLL90XX_PDIV_SHIFT | + epll_div[i][4] << PLL90XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", + __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P_EPLL_CON0); + __raw_writel(epll_con_k, S5P_EPLL_CON1); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5pv210_epll_ops = { + .get_rate = s5pv210_epll_get_rate, + .set_rate = s5pv210_epll_set_rate, +}; + void __init_or_cpufreq s5pv210_setup_clocks(void) { struct clk *xtal_clk; @@ -1022,6 +1113,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned int ptr; u32 clkdiv0, clkdiv1;
+ /* Set functions for clk_fout_epll */ + clk_fout_epll.enable = s5pv210_epll_enable; + clk_fout_epll.ops = &s5pv210_epll_ops; + printk(KERN_DEBUG "%s: registering clocks\n", __func__);
clkdiv0 = __raw_readl(S5P_CLK_DIV0); diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index bf28fad..389663a 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -102,6 +102,8 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, #define PLL90XX_PDIV_SHIFT (8) #define PLL90XX_SDIV_SHIFT (0) #define PLL90XX_KDIV_SHIFT (0) +#define PLL90XX_VSEL_MASK 1 +#define PLL90XX_VSEL_SHIFT 27
static inline unsigned long s5p_get_pll90xx(unsigned long baseclk, u32 pll_con, u32 pll_conk)
Seungwhan Youn wrote:
This patch adds EPLL specific clock get_rate/set_rate operations on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 95 ++++++++++++++++++++++++++++++++++ arch/arm/plat-s5p/include/plat/pll.h | 2 + 2 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index bcbe7e9..affa5a0 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -1003,6 +1003,97 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_spdif, };
+static int s5pv210_epll_enable(struct clk *clk, int enable) +{
- unsigned int ctrlbit = clk->ctrlbit;
- unsigned int epll_con = __raw_readl(S5P_EPLL_CON0) & ~ctrlbit;
- if (enable)
__raw_writel(epll_con | ctrlbit, S5P_EPLL_CON0);
- else
__raw_writel(epll_con, S5P_EPLL_CON0);
- return 0;
+}
Maybe if we move s5p64x0_epll_enable() to common part i.e., plat-s5p/clock.c, we can use common_epll_enable() in here. Of course, need to sort out the regarding definitions such as S5PXX_EPLL_CON0...
+static unsigned long s5pv210_epll_get_rate(struct clk *clk) +{
- return clk->rate;
+}
+static u32 epll_div[][6] = {
- { 48000000, 0, 48, 3, 3, 0 },
- { 96000000, 0, 48, 3, 2, 0 },
- { 144000000, 1, 72, 3, 2, 0 },
- { 192000000, 0, 48, 3, 1, 0 },
- { 288000000, 1, 72, 3, 1, 0 },
- { 32750000, 1, 65, 3, 4, 35127 },
- { 32768000, 1, 65, 3, 4, 35127 },
- { 45158400, 0, 45, 3, 3, 10355 },
- { 45000000, 0, 45, 3, 3, 10355 },
- { 45158000, 0, 45, 3, 3, 10355 },
- { 49125000, 0, 49, 3, 3, 9961 },
- { 49152000, 0, 49, 3, 3, 9961 },
- { 67737600, 1, 67, 3, 3, 48366 },
- { 67738000, 1, 67, 3, 3, 48366 },
- { 73800000, 1, 73, 3, 3, 47710 },
- { 73728000, 1, 73, 3, 3, 47710 },
- { 36000000, 1, 32, 3, 4, 0 },
- { 60000000, 1, 60, 3, 3, 0 },
- { 72000000, 1, 72, 3, 3, 0 },
- { 80000000, 1, 80, 3, 3, 0 },
- { 84000000, 0, 42, 3, 2, 0 },
- { 50000000, 0, 50, 3, 3, 0 },
+};
+static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate) +{
- unsigned int epll_con, epll_con_k;
- unsigned int i;
- /* Return if nothing changed */
- if (clk->rate == rate)
return 0;
- epll_con = __raw_readl(S5P_EPLL_CON0);
- epll_con_k = __raw_readl(S5P_EPLL_CON1);
- epll_con_k &= ~(PLL90XX_KDIV_MASK << PLL90XX_KDIV_SHIFT);
- epll_con &= ~(PLL90XX_VSEL_MASK << PLL90XX_VSEL_SHIFT |
PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |
PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |
PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
if (epll_div[i][0] == rate) {
epll_con_k |= epll_div[i][5] << 0;
epll_con |= (epll_div[i][1] << PLL90XX_VSEL_SHIFT |
epll_div[i][2] <<
PLL90XX_MDIV_SHIFT |
epll_div[i][3] <<
PLL90XX_PDIV_SHIFT |
epll_div[i][4] <<
PLL90XX_SDIV_SHIFT);
break;
}
- }
- if (i == ARRAY_SIZE(epll_div)) {
printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
__func__);
return -EINVAL;
- }
- __raw_writel(epll_con, S5P_EPLL_CON0);
- __raw_writel(epll_con_k, S5P_EPLL_CON1);
- clk->rate = rate;
- return 0;
+}
Same...
+static struct clk_ops s5pv210_epll_ops = {
- .get_rate = s5pv210_epll_get_rate,
- .set_rate = s5pv210_epll_set_rate,
+};
void __init_or_cpufreq s5pv210_setup_clocks(void) { struct clk *xtal_clk; @@ -1022,6 +1113,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned int ptr; u32 clkdiv0, clkdiv1;
/* Set functions for clk_fout_epll */
clk_fout_epll.enable = s5pv210_epll_enable;
clk_fout_epll.ops = &s5pv210_epll_ops;
printk(KERN_DEBUG "%s: registering clocks\n", __func__);
clkdiv0 = __raw_readl(S5P_CLK_DIV0);
diff --git a/arch/arm/plat-s5p/include/plat/pll.h
b/arch/arm/plat-s5p/include/plat/pll.h
index bf28fad..389663a 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -102,6 +102,8 @@ static inline unsigned long s5p_get_pll46xx(unsigned
long
baseclk, #define PLL90XX_PDIV_SHIFT (8) #define PLL90XX_SDIV_SHIFT (0) #define PLL90XX_KDIV_SHIFT (0) +#define PLL90XX_VSEL_MASK 1 +#define PLL90XX_VSEL_SHIFT 27
static inline unsigned long s5p_get_pll90xx(unsigned long baseclk, u32 pll_con, u32 pll_conk) --
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
On Fri, Oct 8, 2010 at 7:29 PM, Kukjin Kim kgene.kim@samsung.com wrote:
Seungwhan Youn wrote:
This patch adds EPLL specific clock get_rate/set_rate operations on S5PV210.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com
arch/arm/mach-s5pv210/clock.c | 95 ++++++++++++++++++++++++++++++++++ arch/arm/plat-s5p/include/plat/pll.h | 2 + 2 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index bcbe7e9..affa5a0 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -1003,6 +1003,97 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_spdif, };
+static int s5pv210_epll_enable(struct clk *clk, int enable) +{
- unsigned int ctrlbit = clk->ctrlbit;
- unsigned int epll_con = __raw_readl(S5P_EPLL_CON0) & ~ctrlbit;
- if (enable)
- __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON0);
- else
- __raw_writel(epll_con, S5P_EPLL_CON0);
- return 0;
+}
Maybe if we move s5p64x0_epll_enable() to common part i.e., plat-s5p/clock.c, we can use common_epll_enable() in here. Of course, need to sort out the regarding definitions such as S5PXX_EPLL_CON0...
Okay, I'll fix.
+static unsigned long s5pv210_epll_get_rate(struct clk *clk) +{
- return clk->rate;
+}
+static u32 epll_div[][6] = {
- { 48000000, 0, 48, 3, 3, 0 },
- { 96000000, 0, 48, 3, 2, 0 },
- { 144000000, 1, 72, 3, 2, 0 },
- { 192000000, 0, 48, 3, 1, 0 },
- { 288000000, 1, 72, 3, 1, 0 },
- { 32750000, 1, 65, 3, 4, 35127 },
- { 32768000, 1, 65, 3, 4, 35127 },
- { 45158400, 0, 45, 3, 3, 10355 },
- { 45000000, 0, 45, 3, 3, 10355 },
- { 45158000, 0, 45, 3, 3, 10355 },
- { 49125000, 0, 49, 3, 3, 9961 },
- { 49152000, 0, 49, 3, 3, 9961 },
- { 67737600, 1, 67, 3, 3, 48366 },
- { 67738000, 1, 67, 3, 3, 48366 },
- { 73800000, 1, 73, 3, 3, 47710 },
- { 73728000, 1, 73, 3, 3, 47710 },
- { 36000000, 1, 32, 3, 4, 0 },
- { 60000000, 1, 60, 3, 3, 0 },
- { 72000000, 1, 72, 3, 3, 0 },
- { 80000000, 1, 80, 3, 3, 0 },
- { 84000000, 0, 42, 3, 2, 0 },
- { 50000000, 0, 50, 3, 3, 0 },
+};
+static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate) +{
- unsigned int epll_con, epll_con_k;
- unsigned int i;
- /* Return if nothing changed */
- if (clk->rate == rate)
- return 0;
- epll_con = __raw_readl(S5P_EPLL_CON0);
- epll_con_k = __raw_readl(S5P_EPLL_CON1);
- epll_con_k &= ~(PLL90XX_KDIV_MASK << PLL90XX_KDIV_SHIFT);
- epll_con &= ~(PLL90XX_VSEL_MASK << PLL90XX_VSEL_SHIFT |
- PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |
- PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |
- PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
- if (epll_div[i][0] == rate) {
- epll_con_k |= epll_div[i][5] << 0;
- epll_con |= (epll_div[i][1] << PLL90XX_VSEL_SHIFT |
- epll_div[i][2] <<
PLL90XX_MDIV_SHIFT |
- epll_div[i][3] <<
PLL90XX_PDIV_SHIFT |
- epll_div[i][4] <<
PLL90XX_SDIV_SHIFT);
- break;
- }
- }
- if (i == ARRAY_SIZE(epll_div)) {
- printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
- __func__);
- return -EINVAL;
- }
- __raw_writel(epll_con, S5P_EPLL_CON0);
- __raw_writel(epll_con_k, S5P_EPLL_CON1);
- clk->rate = rate;
- return 0;
+}
Same...
This also, I'll fix it.
(snip)
Thanks, Claude
This patch adds S/PDIF CPU driver for various Samsung SoCs.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com Acked-by: Jassi Brar jassi.brar@samsung.com --- sound/soc/s3c24xx/Kconfig | 4 + sound/soc/s3c24xx/Makefile | 2 + sound/soc/s3c24xx/spdif.c | 435 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/s3c24xx/spdif.h | 90 +++++++++ 4 files changed, 531 insertions(+), 0 deletions(-) create mode 100644 sound/soc/s3c24xx/spdif.c create mode 100644 sound/soc/s3c24xx/spdif.h
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 7d8235d..e2cba93 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -36,6 +36,10 @@ config SND_S3C_SOC_AC97 tristate select SND_SOC_AC97_BUS
+config SND_S5P_SOC_SPDIF + tristate + select SND_SOC_SPDIF + config SND_S3C24XX_SOC_NEO1973_WM8753 tristate "SoC I2S Audio support for NEO1973 - WM8753" depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01 diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index dd412a9..0a02735 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -7,6 +7,7 @@ snd-soc-s3c-ac97-objs := s3c-ac97.o snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o snd-soc-s3c-pcm-objs := s3c-pcm.o +snd-soc-samsung-spdif-objs := spdif.o
obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o @@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o +obj-$(CONFIG_SND_S5P_SOC_SPDIF) += snd-soc-samsung-spdif.o
# S3C24XX Machine Support snd-soc-jive-wm8750-objs := jive_wm8750.o diff --git a/sound/soc/s3c24xx/spdif.c b/sound/soc/s3c24xx/spdif.c new file mode 100644 index 0000000..e21d57d --- /dev/null +++ b/sound/soc/s3c24xx/spdif.c @@ -0,0 +1,435 @@ +/* sound/soc/s3c24xx/spdif.c + * + * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver + * + * Copyright (c) 2010 Samsung Electronics Co. Ltd + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/io.h> + +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +#include <plat/audio.h> +#include <mach/dma.h> + +#include "s3c-dma.h" +#include "spdif.h" + +static struct s3c2410_dma_client spdif_dma_client_out = { + .name = "S/PDIF Stereo out", +}; + +static struct s3c_dma_params spdif_stereo_out; +static struct samsung_spdif_info spdif_info; + +static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai) +{ + return snd_soc_dai_get_drvdata(cpu_dai); +} + +static void spdif_snd_txctrl(struct samsung_spdif_info *spdif, int on) +{ + void __iomem *regs = spdif->regs; + u32 clkcon; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + clkcon = readl(regs + CLKCON) & CLKCTL_MASK; + if (on) + writel(clkcon | CLKCTL_PWR_ON, regs + CLKCON); + else + writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON); +} + +static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct samsung_spdif_info *spdif = to_info(cpu_dai); + u32 clkcon; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + clkcon = readl(spdif->regs + CLKCON); + + if (clk_id == SND_SOC_SPDIF_INT_MCLK) + clkcon &= ~CLKCTL_MCLK_EXT; + else + clkcon |= CLKCTL_MCLK_EXT; + + writel(clkcon, spdif->regs + CLKCON); + + return 0; +} + +static int spdif_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) +{ + struct samsung_spdif_info *spdif = to_info(cpu_dai); + u32 con; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + con = readl(spdif->regs + CON); + + switch (div_id) { + case SND_SOC_SPDIF_MAIN_AUDIO_CLK: + switch (div) { + case 256: + con |= CON_MCLKDIV_256FS; + break; + case 384: + con |= CON_MCLKDIV_384FS; + break; + case 512: + con |= CON_MCLKDIV_512FS; + break; + default: + return -EINVAL; + } + default: + dev_err(spdif->dev, "Invalid div_id(%d)\n", div_id); + return -EINVAL; + } + + writel(con, spdif->regs + CON); + + return 0; +} + +static int spdif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); + unsigned long flags; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + spin_lock_irqsave(&spdif->lock, flags); + spdif_snd_txctrl(spdif, 1); + spin_unlock_irqrestore(&spdif->lock, flags); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + spin_lock_irqsave(&spdif->lock, flags); + spdif_snd_txctrl(spdif, 0); + spin_unlock_irqrestore(&spdif->lock, flags); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int spdif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *socdai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); + void __iomem *regs = spdif->regs; + struct s3c_dma_params *dma_data; + u32 con, clkcon, cstas; + unsigned long flags; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_data = spdif->dma_playback; + else { + dev_err(spdif->dev, "Capture is not supported\n"); + return -EINVAL; + } + + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); + + spin_lock_irqsave(&spdif->lock, flags); + + con = readl(regs + CON) & CON_MASK; + cstas = readl(regs + CSTAS) & CSTAS_MASK; + clkcon = readl(regs + CLKCON) & CLKCTL_MASK; + + con &= ~CON_FIFO_TH_MASK; + con |= (0x7 << CON_FIFO_TH_SHIFT); + con |= CON_USERDATA_23RDBIT; + con |= CON_PCM_DATA; + + con &= ~CON_PCM_MASK; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + con |= CON_PCM_16BIT; + break; + default: + dev_err(spdif->dev, "Unsupported data size.\n"); + goto err; + } + + cstas &= ~CSTAS_SAMP_FREQ_MASK; + switch (params_rate(params)) { + case 44100: + cstas |= CSTAS_SAMP_FREQ_44; + break; + case 48000: + cstas |= CSTAS_SAMP_FREQ_48; + break; + case 32000: + cstas |= CSTAS_SAMP_FREQ_32; + break; + case 96000: + cstas |= CSTAS_SAMP_FREQ_96; + break; + default: + dev_err(spdif->dev, "Invalid sampling rate %d\n", + params_rate(params)); + goto err; + } + + cstas &= ~CSTAS_CATEGORY_MASK; + cstas |= CSTAS_CATEGORY_CODE_CDP; + cstas |= CSTAS_NO_COPYRIGHT; + + writel(con, regs + CON); + writel(cstas, regs + CSTAS); + writel(clkcon, regs + CLKCON); + + spin_unlock_irqrestore(&spdif->lock, flags); + + return 0; +err: + spin_unlock_irqrestore(&spdif->lock, flags); + return -EINVAL; +} + +static void spdif_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai); + void __iomem *regs = spdif->regs; + u32 con, clkcon; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + con = readl(regs + CON) & CON_MASK; + clkcon = readl(regs + CLKCON) & CLKCTL_MASK; + + writel(con | CON_SW_RESET, regs + CON); + cpu_relax(); + + writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON); +} + +#ifdef CONFIG_PM +static int spdif_suspend(struct snd_soc_dai *cpu_dai) +{ + struct samsung_spdif_info *spdif = to_info(cpu_dai); + u32 con = spdif->saved_con; + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + spdif->saved_clkcon = readl(spdif->regs + CLKCON) & CLKCTL_MASK; + spdif->saved_con = readl(spdif->regs + CON) & CON_MASK; + spdif->saved_cstas = readl(spdif->regs + CSTAS) & CSTAS_MASK; + + writel(con | CON_SW_RESET, spdif->regs + CON); + cpu_relax(); + + return 0; +} + +static int spdif_resume(struct snd_soc_dai *cpu_dai) +{ + struct samsung_spdif_info *spdif = to_info(cpu_dai); + + dev_dbg(spdif->dev, "Entered %s\n", __func__); + + writel(spdif->saved_clkcon, spdif->regs + CLKCON); + writel(spdif->saved_con, spdif->regs + CON); + writel(spdif->saved_cstas, spdif->regs + CSTAS); + + return 0; +} +#else +#define spdif_suspend NULL +#define spdif_resume NULL +#endif + +static struct snd_soc_dai_ops spdif_dai_ops = { + .set_sysclk = spdif_set_sysclk, + .set_clkdiv = spdif_set_clkdiv, + .trigger = spdif_trigger, + .hw_params = spdif_hw_params, + .shutdown = spdif_shutdown, +}; + +struct snd_soc_dai_driver samsung_spdif_dai = { + .name = "samsung-spdif", + .playback = { + .stream_name = "S/PDIF Playback", + .channels_min = 2, + .channels_max = 2, + .rates = (SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, }, + .ops = &spdif_dai_ops, + .suspend = spdif_suspend, + .resume = spdif_resume, +}; + +static __devinit int spdif_probe(struct platform_device *pdev) +{ + struct s3c_audio_pdata *spdif_pdata; + struct resource *mem_res, *dma_res; + struct samsung_spdif_info *spdif; + int ret; + + spdif_pdata = pdev->dev.platform_data; + + dev_dbg(&pdev->dev, "Entered %s\n", __func__); + + dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!dma_res) { + dev_err(&pdev->dev, "Unable to get dma resource.\n"); + return -ENXIO; + } + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "Unable to get register resource.\n"); + return -ENXIO; + } + + if (spdif_pdata && spdif_pdata->cfg_gpio + && spdif_pdata->cfg_gpio(pdev)) { + dev_err(&pdev->dev, "Unable to configure GPIO pins\n"); + return -EINVAL; + } + + spdif = &spdif_info; + spdif->dev = &pdev->dev; + + spin_lock_init(&spdif->lock); + + spdif->pclk = clk_get(&pdev->dev, "spdif"); + if (IS_ERR(spdif->pclk)) { + dev_err(&pdev->dev, "failed to get peri-clock\n"); + ret = -ENOENT; + goto err0; + } + clk_enable(spdif->pclk); + + spdif->sclk = clk_get(&pdev->dev, "sclk_spdif"); + if (IS_ERR(spdif->sclk)) { + dev_err(&pdev->dev, "failed to get internal source clock\n"); + ret = -ENOENT; + goto err1; + } + clk_enable(spdif->sclk); + + /* Request S/PDIF Register's memory region */ + if (!request_mem_region(mem_res->start, + resource_size(mem_res), "samsung-spdif")) { + dev_err(&pdev->dev, "Unable to request register region\n"); + ret = -EBUSY; + goto err2; + } + + spdif->regs = ioremap(mem_res->start, 0x100); + if (spdif->regs == NULL) { + dev_err(&pdev->dev, "Cannot ioremap registers\n"); + ret = -ENXIO; + goto err3; + } + + dev_set_drvdata(&pdev->dev, spdif); + + ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai); + if (ret != 0) { + dev_err(&pdev->dev, "fail to register dai\n"); + goto err4; + } + + spdif_stereo_out.dma_size = 2; + spdif_stereo_out.client = &spdif_dma_client_out; + spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; + spdif_stereo_out.channel = dma_res->start; + + spdif->dma_playback = &spdif_stereo_out; + + return 0; + +err4: + iounmap(spdif->regs); +err3: + release_mem_region(mem_res->start, resource_size(mem_res)); +err2: + clk_disable(spdif->sclk); + clk_put(spdif->sclk); +err1: + clk_disable(spdif->pclk); + clk_put(spdif->pclk); +err0: + return ret; +} + +static __devexit int spdif_remove(struct platform_device *pdev) +{ + struct samsung_spdif_info *spdif = &spdif_info; + struct resource *mem_res; + + snd_soc_unregister_dai(&pdev->dev); + + iounmap(spdif->regs); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (mem_res) + release_mem_region(mem_res->start, resource_size(mem_res)); + + clk_disable(spdif->sclk); + clk_put(spdif->sclk); + clk_disable(spdif->pclk); + clk_put(spdif->pclk); + + return 0; +} + +static struct platform_driver samsung_spdif_driver = { + .probe = spdif_probe, + .remove = spdif_remove, + .driver = { + .name = "samsung-spdif", + .owner = THIS_MODULE, + }, +}; + +static int __init spdif_init(void) +{ + return platform_driver_register(&samsung_spdif_driver); +} +module_init(spdif_init); + +static void __exit spdif_exit(void) +{ + platform_driver_unregister(&samsung_spdif_driver); +} +module_exit(spdif_exit); + +MODULE_AUTHOR("Seungwhan Youn, sw.youn@samsung.com"); +MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-spdif"); diff --git a/sound/soc/s3c24xx/spdif.h b/sound/soc/s3c24xx/spdif.h new file mode 100644 index 0000000..106e066 --- /dev/null +++ b/sound/soc/s3c24xx/spdif.h @@ -0,0 +1,90 @@ +/* sound/soc/s3c24xx/spdif.h + * + * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver + * + * Copyright (c) 2010 Samsung Electronics Co. Ltd + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __SND_SOC_SAMSUNG_SPDIF_H +#define __SND_SOC_SAMSUNG_SPDIF_H __FILE__ + +/** + * struct samsung_spdif_info - Samsung S/PDIF Controller information + * @lock: Spin lock for S/PDIF. + * @dev: The parent device passed to use from the probe. + * @regs: The pointer to the device register block. + * @pclk: The peri-clock pointer for spdif master operation. + * @sclk: The source clock pointer for making sync signals. + * @save_clkcon: Backup clkcon reg. in suspend. + * @save_con: Backup con reg. in suspend. + * @save_cstas: Backup cstas reg. in suspend. + * @dma_playback: DMA information for playback channel. + */ +struct samsung_spdif_info { + spinlock_t lock; + struct device *dev; + void __iomem *regs; + struct clk *pclk; + struct clk *sclk; + u32 saved_clkcon; + u32 saved_con; + u32 saved_cstas; + struct s3c_dma_params *dma_playback; +}; + +/* Registers */ +#define CLKCON 0x00 +#define CON 0x04 +#define BSTAS 0x08 +#define CSTAS 0x0C +#define DATA_OUTBUF 0x10 +#define DCNT 0x14 +#define BSTAS_S 0x18 +#define DCNT_S 0x1C + +#define CLKCTL_MASK 0x7 +#define CLKCTL_MCLK_EXT (0x1 << 2) +#define CLKCTL_PWR_ON (0x1 << 0) + +#define CON_MASK 0x3ffffff +#define CON_FIFO_TH_SHIFT 19 +#define CON_FIFO_TH_MASK (0x7 << 19) +#define CON_USERDATA_23RDBIT (0x1 << 12) + +#define CON_SW_RESET (0x1 << 5) + +#define CON_MCLKDIV_MASK (0x3 << 3) +#define CON_MCLKDIV_256FS (0x0 << 3) +#define CON_MCLKDIV_384FS (0x1 << 3) +#define CON_MCLKDIV_512FS (0x2 << 3) + +#define CON_PCM_MASK (0x3 << 1) +#define CON_PCM_16BIT (0x0 << 1) +#define CON_PCM_20BIT (0x1 << 1) +#define CON_PCM_24BIT (0x2 << 1) + +#define CON_PCM_DATA (0x1 << 0) + +#define CSTAS_MASK 0x3fffffff +#define CSTAS_SAMP_FREQ_MASK (0xF << 24) +#define CSTAS_SAMP_FREQ_44 (0x0 << 24) +#define CSTAS_SAMP_FREQ_48 (0x2 << 24) +#define CSTAS_SAMP_FREQ_32 (0x3 << 24) +#define CSTAS_SAMP_FREQ_96 (0xA << 24) + +#define CSTAS_CATEGORY_MASK (0xFF << 8) +#define CSTAS_CATEGORY_CODE_CDP (0x01 << 8) + +#define CSTAS_NO_COPYRIGHT (0x1 << 2) + +#define SND_SOC_SPDIF_INT_MCLK 0 +#define SND_SOC_SPDIF_EXT_MCLK 1 + +#define SND_SOC_SPDIF_MAIN_AUDIO_CLK 0 + +#endif /* __SND_SOC_SAMSUNG_SPDIF_H */
On Mon, Oct 04, 2010 at 09:13:17PM +0900, Seungwhan Youn wrote:
+static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
+{
If you save the clock rate here...
- case SND_SOC_SPDIF_MAIN_AUDIO_CLK:
switch (div) {
case 256:
con |= CON_MCLKDIV_256FS;
break;
case 384:
con |= CON_MCLKDIV_384FS;
break;
case 512:
con |= CON_MCLKDIV_512FS;
break;
...then you can calculate this dynamically at runtime in hw_params which makes life easier for users.
+/**
- struct samsung_spdif_info - Samsung S/PDIF Controller information
- @lock: Spin lock for S/PDIF.
- @dev: The parent device passed to use from the probe.
- @regs: The pointer to the device register block.
- @pclk: The peri-clock pointer for spdif master operation.
- @sclk: The source clock pointer for making sync signals.
- @save_clkcon: Backup clkcon reg. in suspend.
- @save_con: Backup con reg. in suspend.
- @save_cstas: Backup cstas reg. in suspend.
- @dma_playback: DMA information for playback channel.
- */
+struct samsung_spdif_info {
- spinlock_t lock;
No need to have this in the headers.
+/* Registers */ +#define CLKCON 0x00 +#define CON 0x04 +#define BSTAS 0x08
These should all be namespaced or in the driver file to avoid collisoons with other things - even if only used in this driver things like CON are risky for collisions with normal kernel headers the driver needs.
Hi,
On Tue, Oct 5, 2010 at 7:02 AM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Mon, Oct 04, 2010 at 09:13:17PM +0900, Seungwhan Youn wrote:
+static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
+{
If you save the clock rate here...
- case SND_SOC_SPDIF_MAIN_AUDIO_CLK:
- switch (div) {
- case 256:
- con |= CON_MCLKDIV_256FS;
- break;
- case 384:
- con |= CON_MCLKDIV_384FS;
- break;
- case 512:
- con |= CON_MCLKDIV_512FS;
- break;
...then you can calculate this dynamically at runtime in hw_params which makes life easier for users.
Yes, right. I'll fix this and resend a patch. Actually the first time, I implemented like your opinion but I and Jassi were afraid about S/PDIF use external clock rate. But it's no matter that machine driver can give external clock rate also.
+/**
- struct samsung_spdif_info - Samsung S/PDIF Controller information
- @lock: Spin lock for S/PDIF.
- @dev: The parent device passed to use from the probe.
- @regs: The pointer to the device register block.
- @pclk: The peri-clock pointer for spdif master operation.
- @sclk: The source clock pointer for making sync signals.
- @save_clkcon: Backup clkcon reg. in suspend.
- @save_con: Backup con reg. in suspend.
- @save_cstas: Backup cstas reg. in suspend.
- @dma_playback: DMA information for playback channel.
- */
+struct samsung_spdif_info {
- spinlock_t lock;
No need to have this in the headers.
+/* Registers */ +#define CLKCON 0x00 +#define CON 0x04 +#define BSTAS 0x08
These should all be namespaced or in the driver file to avoid collisoons with other things - even if only used in this driver things like CON are risky for collisions with normal kernel headers the driver needs.
Okay, I'll move these into driver file(and remove header file), and resend patch few days later after listen other people's opinions.
Thanks, Claude
This patch add S/PDIF machine driver to support S/PDIF PCM audio on SMDKC100, SMDKC110 and SMDKV210 boards.
Signed-off-by: Seungwhan Youn sw.youn@samsung.com Acked-by: Jassi Brar jassi.brar@samsung.com --- sound/soc/s3c24xx/Kconfig | 7 ++ sound/soc/s3c24xx/Makefile | 2 + sound/soc/s3c24xx/smdk_spdif.c | 228 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 0 deletions(-) create mode 100644 sound/soc/s3c24xx/smdk_spdif.c
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index e2cba93..8a6b53c 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -161,3 +161,10 @@ config SND_S5PV210_SOC_GONI_WM8994 help Say Y if you want to add support for SoC audio on goni with the WM8994. + +config SND_SOC_SMDK_SPDIF + tristate "SoC S/PDIF Audio support for SMDK" + depends on SND_S3C24XX_SOC && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210) + select SND_S5P_SOC_SPDIF + help + Say Y if you want to add support for SoC S/PDIF audio on the SMDK. diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 0a02735..ee8f41d 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -35,6 +35,7 @@ snd-soc-smdk-wm9713-objs := smdk_wm9713.o snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o snd-soc-aquila-wm8994-objs := aquila_wm8994.o snd-soc-goni-wm8994-objs := goni_wm8994.o +snd-soc-smdk-spdif-objs := smdk_spdif.o
obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -51,3 +52,4 @@ obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o +obj-$(CONFIG_SND_SOC_SMDK_SPDIF) += snd-soc-smdk-spdif.o diff --git a/sound/soc/s3c24xx/smdk_spdif.c b/sound/soc/s3c24xx/smdk_spdif.c new file mode 100644 index 0000000..e96b9e1 --- /dev/null +++ b/sound/soc/s3c24xx/smdk_spdif.c @@ -0,0 +1,228 @@ +/* + * smdk_spdif.c -- S/PDIF audio for SMDK + * + * Copyright 2010 Samsung Electronics Co. Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/clk.h> + +#include <plat/devs.h> + +#include <sound/soc.h> + +#include "s3c-dma.h" +#include "spdif.h" + +/* Audio clock settings are belonged to board specific part. Every + * board can set audio source clock setting which is matched with H/W + * like this function-'set_audio_clock_heirachy'. + */ +static int set_audio_clock_heirachy(struct platform_device *pdev) +{ + struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif; + int ret; + + fout_epll = clk_get(NULL, "fout_epll"); + if (IS_ERR(fout_epll)) { + printk(KERN_WARNING "%s: Cannot find fout_epll.\n", + __func__); + return -EINVAL; + } + + mout_epll = clk_get(NULL, "mout_epll"); + if (IS_ERR(fout_epll)) { + printk(KERN_WARNING "%s: Cannot find mout_epll.\n", + __func__); + ret = -EINVAL; + goto out1; + } + + sclk_audio0 = clk_get(&pdev->dev, "sclk_audio"); + if (IS_ERR(sclk_audio0)) { + printk(KERN_WARNING "%s: Cannot find sclk_audio.\n", + __func__); + ret = -EINVAL; + goto out2; + } + + sclk_spdif = clk_get(NULL, "sclk_spdif"); + if (IS_ERR(fout_epll)) { + printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n", + __func__); + ret = -EINVAL; + goto out3; + } + + /* Set audio clock heirachy for S/PDIF */ + clk_set_parent(mout_epll, fout_epll); + clk_set_parent(sclk_audio0, mout_epll); + clk_set_parent(sclk_spdif, sclk_audio0); + + clk_put(sclk_spdif); +out3: + clk_put(sclk_audio0); +out2: + clk_put(mout_epll); +out1: + clk_put(fout_epll); + + return ret; +} + +/* We should haved to set clock directly on this part because of clock + * scheme of Samsudng SoCs did not support to set rates from abstrct + * clock of it's heirachy. + */ +static int set_audio_clock_rate(unsigned long epll_rate, + unsigned long audio_rate) +{ + struct clk *fout_epll, *sclk_spdif; + + fout_epll = clk_get(NULL, "fout_epll"); + if (IS_ERR(fout_epll)) { + printk(KERN_ERR "%s: failed to get fout_epll\n", __func__); + return -ENOENT; + } + + clk_set_rate(fout_epll, epll_rate); + clk_put(fout_epll); + + sclk_spdif = clk_get(NULL, "sclk_spdif"); + if (IS_ERR(sclk_spdif)) { + printk(KERN_ERR "%s: failed to get sclk_spdif\n", __func__); + return -ENOENT; + } + + clk_set_rate(sclk_spdif, audio_rate); + clk_put(sclk_spdif); + + return 0; +} + +static int smdk_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned long pll_out; + int ret, ratio; + + switch (params_rate(params)) { + case 44100: + pll_out = 45158400; + break; + case 32000: + case 48000: + case 96000: + pll_out = 49152000; + break; + default: + return -EINVAL; + } + + /* Setting ratio to 512fs helps to use S/PDIF with HDMI without + * modify S/PDIF ASoC machine driver. + */ + ratio = 512; + + /* Set audio source clock rates */ + ret = set_audio_clock_rate(pll_out, (params_rate(params) * ratio)); + if (ret < 0) + return ret; + + /* Set S/PDIF uses internal source clock */ + ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* Set Main Audio Clock Frequency */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, SND_SOC_SPDIF_MAIN_AUDIO_CLK, + ratio); + if (ret < 0) + return ret; + + return ret; +} + +static struct snd_soc_ops smdk_spdif_ops = { + .hw_params = smdk_hw_params, +}; + +static struct snd_soc_card smdk; + +static struct snd_soc_dai_link smdk_dai = { + .name = "S/PDIF", + .stream_name = "S/PDIF PCM Playback", + .platform_name = "s3c24xx-pcm-audio", + .cpu_dai_name = "samsung-spdif", + .codec_dai_name = "dit-hifi", + .codec_name = "spdif-dit", + .ops = &smdk_spdif_ops, +}; + +static struct snd_soc_card smdk = { + .name = "SMDK-S/PDIF", + .dai_link = &smdk_dai, + .num_links = 1, +}; + +static struct platform_device *smdk_snd_spdif_dit_device; +static struct platform_device *smdk_snd_spdif_device; + +static int __init smdk_init(void) +{ + int ret; + + smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1); + if (!smdk_snd_spdif_dit_device) + return -ENOMEM; + + ret = platform_device_add(smdk_snd_spdif_dit_device); + if (ret) + goto err2; + + smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1); + if (!smdk_snd_spdif_device) { + ret = -ENOMEM; + goto err2; + } + + platform_set_drvdata(smdk_snd_spdif_device, &smdk); + + ret = platform_device_add(smdk_snd_spdif_device); + if (ret) + goto err1; + + /* Set audio clock heirachy manually */ + ret = set_audio_clock_heirachy(smdk_snd_spdif_device); + if (ret) + goto err1; + + return 0; +err1: + platform_device_put(smdk_snd_spdif_device); +err2: + platform_device_put(smdk_snd_spdif_dit_device); + return ret; +} + +static void __exit smdk_exit(void) +{ + platform_device_unregister(smdk_snd_spdif_device); +} + +module_init(smdk_init); +module_exit(smdk_exit); + +MODULE_AUTHOR("Seungwhan Youn, sw.youn@samsung.com"); +MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF"); +MODULE_LICENSE("GPL");
On Mon, Oct 04, 2010 at 09:16:23PM +0900, Seungwhan Youn wrote:
+/* Audio clock settings are belonged to board specific part. Every
- board can set audio source clock setting which is matched with H/W
- like this function-'set_audio_clock_heirachy'.
- */
+static int set_audio_clock_heirachy(struct platform_device *pdev) +{
I'd expect this to be with the other clock configuration code under arch/arm, especially as it's involving the EPLL which can have fairly wide usage - it seems better to make sure people working with other, non-audio, bits of the system are aware of the EPLL usage.
On Tue, Oct 5, 2010 at 7:42 AM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Mon, Oct 04, 2010 at 09:16:23PM +0900, Seungwhan Youn wrote:
+/* Audio clock settings are belonged to board specific part. Every
- board can set audio source clock setting which is matched with H/W
- like this function-'set_audio_clock_heirachy'.
- */
+static int set_audio_clock_heirachy(struct platform_device *pdev) +{
I'd expect this to be with the other clock configuration code under arch/arm, especially as it's involving the EPLL which can have fairly wide usage - it seems better to make sure people working with other, non-audio, bits of the system are aware of the EPLL usage.
Please let me explain on Claude's behalf. That is the first option that crossed my mind as well. But that would have made us have EPLL manipulation in two places - one in arch/arm/mach/board-init and other in ASoC Machine driver because we would need to change the source clock's rate in runtime(using callback pointers for the purpose seemed too over the top). If ASoC doesn't change EPLL, it doesn't matter to other devices, if it does there is currently no means for other drivers to know about it. So, we might just as well move the EPLL related code to ASoC machine driver.
On Tue, Oct 5, 2010 at 10:10 AM, Jassi Brar jassisinghbrar@gmail.com wrote:
On Tue, Oct 5, 2010 at 7:42 AM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Mon, Oct 04, 2010 at 09:16:23PM +0900, Seungwhan Youn wrote:
+/* Audio clock settings are belonged to board specific part. Every
- board can set audio source clock setting which is matched with H/W
- like this function-'set_audio_clock_heirachy'.
- */
+static int set_audio_clock_heirachy(struct platform_device *pdev) +{
I'd expect this to be with the other clock configuration code under arch/arm, especially as it's involving the EPLL which can have fairly wide usage - it seems better to make sure people working with other, non-audio, bits of the system are aware of the EPLL usage.
Please let me explain on Claude's behalf. That is the first option that crossed my mind as well. But that would have made us have EPLL manipulation in two places - one in arch/arm/mach/board-init and other in ASoC Machine driver because we would need to change the source clock's rate in runtime(using callback pointers for the purpose seemed too over the top). If ASoC doesn't change EPLL, it doesn't matter to other devices, if it does there is currently no means for other drivers to know about it. So, we might just as well move the EPLL related code to ASoC machine driver.
Btw, another important reason is that having EPLL manipulation in board-int would result in code-duplication on other SMDK platforms as most have the same clock routing options available in h/w and we want to use the same ASoC machine driver for SoCs whenever possible.
On Tue, Oct 05, 2010 at 11:19:35AM +0900, Jassi Brar wrote:
On Tue, Oct 5, 2010 at 10:10 AM, Jassi Brar jassisinghbrar@gmail.com wrote:
On Tue, Oct 5, 2010 at 7:42 AM, Mark Brown
I'd expect this to be with the other clock configuration code under arch/arm, especially as it's involving the EPLL which can have fairly wide usage - it seems better to make sure people working with other, non-audio, bits of the system are aware of the EPLL usage.
But that would have made us have EPLL manipulation in two places - one in arch/arm/mach/board-init and other in ASoC Machine driver because we would need to change the source clock's rate in runtime(using callback pointers for the purpose seemed too over the top). If ASoC doesn't change EPLL, it doesn't matter to other devices, if it does there is currently no means for other drivers to know about it. So, we might just as well move the EPLL related code to ASoC machine driver.
The reason I'm concerned about this is that I've had actual problems with users of your out of tree BSPs getting confused by similar code there. Thinking about it some more it's not so much the fact that the code is spread out as the fact that the the EPLL is so widely used within the system that having one driver change it can easily disrupt another subsystem in surprising ways.
Since the clock API currently doesn't have a good way of resolving this perhaps a config option or something which masks the EPLL behaviour controllable and leaves it alone by default? That would show people how to use this chip feature without affecting the other subsystems so non-obviously.
Btw, another important reason is that having EPLL manipulation in board-int would result in code-duplication on other SMDK platforms as most have the same clock routing options available in h/w and we want to use the same ASoC machine driver for SoCs whenever possible.
This doesn't seem such a big deal - you could create a shared file for the code under arch/arm.
On Tue, Oct 5, 2010 at 1:43 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Tue, Oct 05, 2010 at 11:19:35AM +0900, Jassi Brar wrote:
On Tue, Oct 5, 2010 at 10:10 AM, Jassi Brar jassisinghbrar@gmail.com wrote:
On Tue, Oct 5, 2010 at 7:42 AM, Mark Brown
The reason I'm concerned about this is that I've had actual problems with users of your out of tree BSPs getting confused by similar code there.
Yes, past mistakes haunt us still.
Since the clock API currently doesn't have a good way of resolving this perhaps a config option or something which masks the EPLL behaviour controllable and leaves it alone by default? That would show people how to use this chip feature without affecting the other subsystems so non-obviously.
Yes we can have a kconfig entry for 'Controllable EPLL' but that seems orthogonal to ASoC because, for SMDKs, we choose to produce accurate signals hence need to manipulate EPLL. The only point is where to do it. (our priority is accuracy of each IP's functioning rather than having all parts of SMDK playing nice with each other on such h/w design issues)
Btw, another important reason is that having EPLL manipulation in board-int would result in code-duplication on other SMDK platforms as most have the same clock routing options available in h/w and we want to use the same ASoC machine driver for SoCs whenever possible.
This doesn't seem such a big deal - you could create a shared file for the code under arch/arm.
I hope you noticed that this clock hierarchy is a _very_ board specific thing. We can easily place SoCs' shared stuff in arch/arm/plat-samsung (or similar) Any suggestions, where do we place code shared by SMDK-boards ?
Thanks
On Tue, Oct 05, 2010 at 02:39:00PM +0900, Jassi Brar wrote:
Yes we can have a kconfig entry for 'Controllable EPLL' but that seems orthogonal to ASoC because, for SMDKs, we choose to produce accurate signals hence need to manipulate EPLL. The only point is where to do it.
Well, there's two approaches the driver can take: one is to change the EPLL to deliver the clock rates which allow maximum flexibility, the other is to constrain the clock rates offered to applications based on the frequencies that can be generated from the current EPLL setup.
(our priority is accuracy of each IP's functioning rather than having all parts of SMDK playing nice with each other on such h/w design issues)
That'd be the problem, kind of - it does mean people can get burned when they pick up the BSP code and use it as a reference for their systems.
I hope you noticed that this clock hierarchy is a _very_ board specific thing. We can easily place SoCs' shared stuff in arch/arm/plat-samsung (or similar) Any suggestions, where do we place code shared by SMDK-boards ?
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-smdk style approach too, though I'm not sure how tasteful I find that personally.
On Tue, Oct 5, 2010 at 2:59 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Tue, Oct 05, 2010 at 02:39:00PM +0900, Jassi Brar wrote:
Yes we can have a kconfig entry for 'Controllable EPLL' but that seems orthogonal to ASoC because, for SMDKs, we choose to produce accurate signals hence need to manipulate EPLL. The only point is where to do it.
Well, there's two approaches the driver can take: one is to change the EPLL to deliver the clock rates which allow maximum flexibility, the other is to constrain the clock rates offered to applications based on the frequencies that can be generated from the current EPLL setup.
For SMDKs(our reference platform) I would like to change EPLL in order to be able to verify accuracy and provide all capabilities of the controllers. For a final product, it would make sense to fix the EPLL to one optimal value according to the type of h/w and s/w components(ex PA can be configured to 48KHz after making sure EPLL can also be used to generate suitable clocks for the SPI devices on board)
(our priority is accuracy of each IP's functioning rather than having all parts of SMDK playing nice with each other on such h/w design issues)
That'd be the problem, kind of - it does mean people can get burned when they pick up the BSP code and use it as a reference for their systems.
I expect people to replace/modify/inspect board specific code before they run the BSP on their systems. IMO reference platforms are not good for integrated-testing. Meanwhile, we should make sure the SoC specific stuff supports and is tested with as many configurations as are possible on SMDKs.
I hope you noticed that this clock hierarchy is a _very_ board specific thing. We can easily place SoCs' shared stuff in arch/arm/plat-samsung (or similar) Any suggestions, where do we place code shared by SMDK-boards ?
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-smdk style approach too, though I'm not sure how tasteful I find that personally.
Even though I would personally like to have EPLL control for a device in machine specific manner as part of its driver, I accept your opinion.
Claude, let us create one arch/arm/plat-samsung/smdk.c to do common stuff for SMKDs like EPLL control. What do you think ?
Thanks.
I hope you noticed that this clock hierarchy is a _very_ board specific thing. We can easily place SoCs' shared stuff in arch/arm/plat-samsung (or similar) Any suggestions, where do we place code shared by SMDK-boards ?
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-smdk style approach too, though I'm not sure how tasteful I find that personally.
Even though I would personally like to have EPLL control for a device in machine specific manner as part of its driver, I accept your opinion.
Claude, let us create one arch/arm/plat-samsung/smdk.c to do common stuff for SMKDs like EPLL control. What do you think ?
Actually if we add this file on plat-samsung, board-init will be separated two-part, one is machine(board) specific and other is all smdk specific. So, If it doesn't make confusion to other guys who wants to add settings for their features on board-init, it looks good to me. But I think that we also have to listen Mr. Ben Dooks and Mr. Kukjin Kim's opinion about this before we get a conclusion.
Seungwhan Youn wrote:
I hope you noticed that this clock hierarchy is a _very_ board specific thing. We can easily place SoCs' shared stuff in arch/arm/plat-samsung (or similar) Any suggestions, where do we place code shared by SMDK-boards ?
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-smdk style approach too, though I'm not sure how tasteful I find that personally.
Even though I would personally like to have EPLL control for a device in machine specific manner as part of its driver, I accept your opinion.
Claude, let us create one arch/arm/plat-samsung/smdk.c to do common stuff for SMKDs like EPLL control. What do you think ?
Actually if we add this file on plat-samsung, board-init will be separated two-part, one is machine(board) specific and other is all smdk specific. So, If it doesn't make confusion to other guys who wants to add settings for their features on board-init, it looks good to me. But I think that we also have to listen Mr. Ben Dooks and Mr. Kukjin Kim's opinion about this before we get a conclusion.
Hi all,
I think, basically it'd better if could control clock stuff in each driver for it when need it such as clk_get, clk_enable and so on. Actually there is no policy/protection for EPLL usage in plat-samsung or plat-s5p now and need to sort out other similar case for it also....so in my opinion, right now to proceed with the current style is helpful to me and will consider it in the future.
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
Dear Maintainers,
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-smdk style approach too, though I'm not sure how tasteful I find that personally.
Even though I would personally like to have EPLL control for a device in machine specific manner as part of its driver, I accept your opinion.
Claude, let us create one arch/arm/plat-samsung/smdk.c to do common stuff for SMKDs like EPLL control. What do you think ?
Actually if we add this file on plat-samsung, board-init will be separated two-part, one is machine(board) specific and other is all smdk specific. So, If it doesn't make confusion to other guys who wants to add settings for their features on board-init, it looks good to me. But I think that we also have to listen Mr. Ben Dooks and Mr. Kukjin Kim's opinion about this before we get a conclusion.
Hi all,
I think, basically it'd better if could control clock stuff in each driver for it when need it such as clk_get, clk_enable and so on. Actually there is no policy/protection for EPLL usage in plat-samsung or plat-s5p now and need to sort out other similar case for it also....so in my opinion, right now to proceed with the current style is helpful to me and will consider it in the future.
I wander to know that this is a last discussion, or more, and also know about finial decision. Of course, if we didn't get reached to the conclusion, we can talk more.
Can you give me a hand to finish this? :-)
with Best Regards, Claude
On Thu, Oct 7, 2010 at 10:33 AM, Seungwhan Youn claude.youn@gmail.com wrote:
Dear Maintainers,
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-smdk style approach too, though I'm not sure how tasteful I find that personally.
Even though I would personally like to have EPLL control for a device in machine specific manner as part of its driver, I accept your opinion.
Claude, let us create one arch/arm/plat-samsung/smdk.c to do common stuff for SMKDs like EPLL control. What do you think ?
Actually if we add this file on plat-samsung, board-init will be separated two-part, one is machine(board) specific and other is all smdk specific. So, If it doesn't make confusion to other guys who wants to add settings for their features on board-init, it looks good to me. But I think that we also have to listen Mr. Ben Dooks and Mr. Kukjin Kim's opinion about this before we get a conclusion.
Hi all,
I think, basically it'd better if could control clock stuff in each driver for it when need it such as clk_get, clk_enable and so on. Actually there is no policy/protection for EPLL usage in plat-samsung or plat-s5p now and need to sort out other similar case for it also....so in my opinion, right now to proceed with the current style is helpful to me and will consider it in the future.
I wander to know that this is a last discussion, or more, and also know about finial decision. Of course, if we didn't get reached to the conclusion, we can talk more.
Can you give me a hand to finish this? :-)
Dear Mr. Mark and Mr. Jassi,
Now, I'm almost finished 2nd patch for submit except this audio clock setting. For now, I can only think that remove audio clock setting from this machine code, and add audio clock settings in arch later(may be after arch/arm/plat-samsung get EPLL policy as Mr. Kukjin said).
Is this okay?
BRs, Claude.
Seungwhan Youn wrote:
On Thu, Oct 7, 2010 at 10:33 AM, Seungwhan Youn claude.youn@gmail.com wrote:
Dear Maintainers,
plat-samsung would probably be fine for that also - create a file called common-smdk or something. Some other things have gone for a plat-
smdk
style approach too, though I'm not sure how tasteful I find that personally.
Even though I would personally like to have EPLL control for a device in machine specific manner as part of its driver, I accept your opinion.
Claude, let us create one arch/arm/plat-samsung/smdk.c to do common stuff for SMKDs like EPLL control. What do you think ?
Actually if we add this file on plat-samsung, board-init will be separated two-part, one is machine(board) specific and other is all smdk specific. So, If it doesn't make confusion to other guys who wants to add settings for their features on board-init, it looks good to me. But I think that we also have to listen Mr. Ben Dooks and Mr. Kukjin Kim's opinion about this before we get a conclusion.
Hi all,
I think, basically it'd better if could control clock stuff in each driver for it when
need it such as clk_get, clk_enable and so on.
Actually there is no policy/protection for EPLL usage in plat-samsung or plat-
s5p now and need to sort out other similar case for it also....so in my opinion, right now to proceed with the current style is helpful to me and will consider it in the future.
I wander to know that this is a last discussion, or more, and also know about finial decision. Of course, if we didn't get reached to the conclusion, we can talk more.
Can you give me a hand to finish this? :-)
Dear Mr. Mark and Mr. Jassi,
Now, I'm almost finished 2nd patch for submit except this audio clock setting. For now, I can only think that remove audio clock setting
Hmm...so, maybe its working has problem...right?
from this machine code, and add audio clock settings in arch later(may be after arch/arm/plat-samsung get EPLL policy as Mr. Kukjin said).
I think, firstly put the clock stuff in the driver like your patch, and then if required, to move is better later.
Is this okay?
Thanks.
Best regards, Kgene. -- Kukjin Kim kgene.kim@samsung.com, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.
On Fri, Oct 8, 2010 at 6:07 PM, Seungwhan Youn claude.youn@gmail.com wrote:
Dear Mr. Mark and Mr. Jassi,
Now, I'm almost finished 2nd patch for submit except this audio clock setting. For now, I can only think that remove audio clock setting from this machine code, and add audio clock settings in arch later(may be after arch/arm/plat-samsung get EPLL policy as Mr. Kukjin said).
Is this okay?
IMO neither of the method is much better than the other.
If neither of the maintainers relent, maybe drop the clock setting altogether and mark the machine driver 'BROKEN' until the EPLL management is fixed?
On Sat, Oct 09, 2010 at 10:52:26AM +0900, Jassi Brar wrote:
On Fri, Oct 8, 2010 at 6:07 PM, Seungwhan Youn claude.youn@gmail.com wrote:
Now, I'm almost finished 2nd patch for submit except this audio clock setting. For now, I can only think that remove audio clock setting from this machine code, and add audio clock settings in arch later(may be after arch/arm/plat-samsung get EPLL policy as Mr. Kukjin said).
Is this okay?
IMO neither of the method is much better than the other.
If neither of the maintainers relent, maybe drop the clock setting altogether and mark the machine driver 'BROKEN' until the EPLL management is fixed?
I'm OK with having the code in the driver, I just want something there that makes it more discoverable that it's there like a config option. Having the driver log loudly when it reconfigures the EPLL would probably also cover it.
On Mon, Oct 11, 2010 at 7:47 PM, Mark Brown broonie@opensource.wolfsonmicro.com wrote:
On Sat, Oct 09, 2010 at 10:52:26AM +0900, Jassi Brar wrote:
On Fri, Oct 8, 2010 at 6:07 PM, Seungwhan Youn claude.youn@gmail.com wrote:
Now, I'm almost finished 2nd patch for submit except this audio clock setting. For now, I can only think that remove audio clock setting from this machine code, and add audio clock settings in arch later(may be after arch/arm/plat-samsung get EPLL policy as Mr. Kukjin said).
Is this okay?
IMO neither of the method is much better than the other.
If neither of the maintainers relent, maybe drop the clock setting altogether and mark the machine driver 'BROKEN' until the EPLL management is fixed?
I'm OK with having the code in the driver, I just want something there that makes it more discoverable that it's there like a config option. Having the driver log loudly when it reconfigures the EPLL would probably also cover it.
Thanks. Yes, we should print warning upon changing EPLL. Even better would be to have some sane EPLL(clocks in general) management policy in place. Perhaps, after I am done with Samsung ASoC overhaul, I'll take it up if others parameters favor.
I'm OK with having the code in the driver, I just want something there that makes it more discoverable that it's there like a config option. Having the driver log loudly when it reconfigures the EPLL would probably also cover it.
Thanks. Yes, we should print warning upon changing EPLL.
Okay, I'll fix this also and will re-submit today. :-)
On Tue, Oct 05, 2010 at 04:09:47PM +0900, Jassi Brar wrote:
On Tue, Oct 5, 2010 at 2:59 PM, Mark Brown
Well, there's two approaches the driver can take: one is to change the EPLL to deliver the clock rates which allow maximum flexibility, the other is to constrain the clock rates offered to applications based on the frequencies that can be generated from the current EPLL setup.
For SMDKs(our reference platform) I would like to change EPLL in order to be able to verify accuracy and provide all capabilities of the controllers.
That's why I'm saying provide an option to turn this behaviour on - I agree that it's useful to be able to show the feature, I just think it's going to catch users out if they're not warned that it's happening somehow.
(our priority is accuracy of each IP's functioning rather than having all parts of SMDK playing nice with each other on such h/w design issues)
That'd be the problem, kind of - it does mean people can get burned when they pick up the BSP code and use it as a reference for their systems.
I expect people to replace/modify/inspect board specific code before they run the BSP on their systems. IMO reference platforms are not good for integrated-testing.
To be fair the users doing this the individual drivers do look OK by themselves - there's only a problem when it comes to system integration and that's not going to be obvious unless someone has reviewed the drivers while understanding the clock tree for the chip as a whole.
On Mon, Oct 4, 2010 at 8:25 PM, Seungwhan Youn sw.youn@samsung.com wrote:
Hi,
This patch-set is for new S/PDIF common driver that supports S/PDIF PCM audio on S5PC100, S5PC110 and S5PV210.
This patch-set is based on two different branches that :- o ASoC patches are based on Mark Brown's git branch 'for-next' (commit id - 135e44aaa47c22b66c8d2acb54da1106a6c17598) o ARM patches are based on Kukjin Kim's git branch 'for-next' (commit id - a9d09cac7485062c599ee8f341bb0c5ccc2cc9d6)
Based on these patches S/PDIF driver supports followings :- o Playback supports {32, 44.1, 48 and 96}kHz sampling rates. o Playback supports 16-bit Little-endian PCM format.
This patch-set contains followings :- o To Kukjin Kim and Ben Dooks, - [PATCH 1/10] ARM: S5PC100: Add S/PDIF platform device - [PATCH 2/10] ARM: S5PC100: Modify SCLK_AUDIO{0,1,2} clock as sysclks - [PATCH 3/10] ARM: S5PC100: Add SCLK_SPDIF clock - [PATCH 4/10] ARM: S5PV210: Add S/PDIF platform device - [PATCH 5/10] ARM: S5PV210: Add SCLK_SPDIF clock - [PATCH 6/10] ARM: S5PV210: Add audio clocks as sysclk - [PATCH 7/10] ARM: S5PV210: Fix wrong EPLL rate getting on setup clocks - [PATCH 8/10] ARM: S5PV210: Add EPLL clock operations o To Jassi Brar, Mark Brown and Liam Girdwood, - [PATCH 9/10] ASoC: SAMSUNG: Add S/PDIF CPU driver - [PATCH 10/10] ASoC: SAMSUNG: Add Machine driver for S/PDIF PCM audio
All Acked-by: Jassi Brar jassi.brar@samsung.com
participants (5)
-
Jassi Brar
-
Kukjin Kim
-
Mark Brown
-
Seungwhan Youn
-
Seungwhan Youn