diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2010-11-23 21:44:06 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-11-24 01:29:56 -0500 |
commit | d4bc99b977e3a1dd10a84a01ebe59ac2ccebf0cd (patch) | |
tree | 441a72709a1dd40ac84b89cec8b036f00960a96b | |
parent | e8ee13a818db4954517cea7da6e7c15b9656eb00 (diff) |
ARM: mach-shmobile: ap4evb: FSI clock use proper process for HDMI
Current AP4 FSI set_rate function used bogus clock process
which didn't care enable/disable and clk->usecound.
To solve this issue, this patch also modify FSI driver to call
set_rate with enough options.
This patch modify it.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/clock-sh7372.c | 2 | ||||
-rw-r--r-- | include/sound/sh_fsi.h | 6 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 19 |
4 files changed, 67 insertions, 18 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index d3260542b943..61c1068198ec 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -567,40 +567,72 @@ static struct platform_device *qhd_devices[] __initdata = { | |||
567 | 567 | ||
568 | /* FSI */ | 568 | /* FSI */ |
569 | #define IRQ_FSI evt2irq(0x1840) | 569 | #define IRQ_FSI evt2irq(0x1840) |
570 | static int __fsi_set_rate(struct clk *clk, long rate, int enable) | ||
571 | { | ||
572 | int ret = 0; | ||
573 | |||
574 | if (rate <= 0) | ||
575 | return ret; | ||
570 | 576 | ||
571 | static int fsi_set_rate(int is_porta, int rate) | 577 | if (enable) { |
578 | ret = clk_set_rate(clk, clk_round_rate(clk, rate)); | ||
579 | if (0 == ret) | ||
580 | ret = clk_enable(clk); | ||
581 | } else { | ||
582 | clk_disable(clk); | ||
583 | } | ||
584 | |||
585 | return ret; | ||
586 | } | ||
587 | |||
588 | static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) | ||
572 | { | 589 | { |
573 | struct clk *fsib_clk; | 590 | struct clk *fsib_clk; |
574 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; | 591 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; |
592 | long fsib_rate = 0; | ||
593 | long fdiv_rate = 0; | ||
594 | int ackmd_bpfmd; | ||
575 | int ret; | 595 | int ret; |
576 | 596 | ||
577 | /* set_rate is not needed if port A */ | 597 | /* set_rate is not needed if port A */ |
578 | if (is_porta) | 598 | if (is_porta) |
579 | return 0; | 599 | return 0; |
580 | 600 | ||
581 | fsib_clk = clk_get(NULL, "fsib_clk"); | ||
582 | if (IS_ERR(fsib_clk)) | ||
583 | return -EINVAL; | ||
584 | |||
585 | switch (rate) { | 601 | switch (rate) { |
586 | case 44100: | 602 | case 44100: |
587 | clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 11283000)); | 603 | fsib_rate = rate * 256; |
588 | ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | 604 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; |
589 | break; | 605 | break; |
590 | case 48000: | 606 | case 48000: |
591 | clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000)); | 607 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ |
592 | clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000)); | 608 | fdiv_rate = rate * 256; |
593 | ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | 609 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; |
594 | break; | 610 | break; |
595 | default: | 611 | default: |
596 | pr_err("unsupported rate in FSI2 port B\n"); | 612 | pr_err("unsupported rate in FSI2 port B\n"); |
597 | ret = -EINVAL; | 613 | return -EINVAL; |
598 | break; | ||
599 | } | 614 | } |
600 | 615 | ||
616 | /* FSI B setting */ | ||
617 | fsib_clk = clk_get(dev, "ickb"); | ||
618 | if (IS_ERR(fsib_clk)) | ||
619 | return -EIO; | ||
620 | |||
621 | ret = __fsi_set_rate(fsib_clk, fsib_rate, enable); | ||
601 | clk_put(fsib_clk); | 622 | clk_put(fsib_clk); |
623 | if (ret < 0) | ||
624 | return ret; | ||
602 | 625 | ||
603 | return ret; | 626 | /* FSI DIV setting */ |
627 | ret = __fsi_set_rate(fdiv_clk, fdiv_rate, enable); | ||
628 | if (ret < 0) { | ||
629 | /* disable FSI B */ | ||
630 | if (enable) | ||
631 | __fsi_set_rate(fsib_clk, fsib_rate, 0); | ||
632 | return ret; | ||
633 | } | ||
634 | |||
635 | return ackmd_bpfmd; | ||
604 | } | 636 | } |
605 | 637 | ||
606 | static struct sh_fsi_platform_info fsi_info = { | 638 | static struct sh_fsi_platform_info fsi_info = { |
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 13226323e4e0..4191e2921127 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c | |||
@@ -471,7 +471,7 @@ static int fsidiv_set_rate(struct clk *clk, | |||
471 | return -ENOENT; | 471 | return -ENOENT; |
472 | 472 | ||
473 | __raw_writel(idx << 16, clk->mapping->base); | 473 | __raw_writel(idx << 16, clk->mapping->base); |
474 | return fsidiv_enable(clk); | 474 | return 0; |
475 | } | 475 | } |
476 | 476 | ||
477 | static struct clk_ops fsidiv_clk_ops = { | 477 | static struct clk_ops fsidiv_clk_ops = { |
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index fa60cbda90a4..d79894192ae3 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h | |||
@@ -85,7 +85,9 @@ | |||
85 | * ACK_MD (FSI2) | 85 | * ACK_MD (FSI2) |
86 | * CKG1 (FSI) | 86 | * CKG1 (FSI) |
87 | * | 87 | * |
88 | * err: return value < 0 | 88 | * err : return value < 0 |
89 | * no change : return value == 0 | ||
90 | * change xMD : return value > 0 | ||
89 | * | 91 | * |
90 | * 0x-00000AB | 92 | * 0x-00000AB |
91 | * | 93 | * |
@@ -111,7 +113,7 @@ | |||
111 | struct sh_fsi_platform_info { | 113 | struct sh_fsi_platform_info { |
112 | unsigned long porta_flags; | 114 | unsigned long porta_flags; |
113 | unsigned long portb_flags; | 115 | unsigned long portb_flags; |
114 | int (*set_rate)(int is_porta, int rate); /* for master mode */ | 116 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); |
115 | }; | 117 | }; |
116 | 118 | ||
117 | #endif /* __SOUND_FSI_H */ | 119 | #endif /* __SOUND_FSI_H */ |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 507e709f2807..136414f163e9 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -132,6 +132,8 @@ struct fsi_priv { | |||
132 | struct fsi_stream playback; | 132 | struct fsi_stream playback; |
133 | struct fsi_stream capture; | 133 | struct fsi_stream capture; |
134 | 134 | ||
135 | long rate; | ||
136 | |||
135 | u32 mst_ctrl; | 137 | u32 mst_ctrl; |
136 | }; | 138 | }; |
137 | 139 | ||
@@ -854,10 +856,17 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
854 | { | 856 | { |
855 | struct fsi_priv *fsi = fsi_get_priv(substream); | 857 | struct fsi_priv *fsi = fsi_get_priv(substream); |
856 | int is_play = fsi_is_play(substream); | 858 | int is_play = fsi_is_play(substream); |
859 | struct fsi_master *master = fsi_get_master(fsi); | ||
860 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | ||
857 | 861 | ||
858 | fsi_irq_disable(fsi, is_play); | 862 | fsi_irq_disable(fsi, is_play); |
859 | fsi_clk_ctrl(fsi, 0); | 863 | fsi_clk_ctrl(fsi, 0); |
860 | 864 | ||
865 | set_rate = master->info->set_rate; | ||
866 | if (set_rate && fsi->rate) | ||
867 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | ||
868 | fsi->rate = 0; | ||
869 | |||
861 | pm_runtime_put_sync(dai->dev); | 870 | pm_runtime_put_sync(dai->dev); |
862 | } | 871 | } |
863 | 872 | ||
@@ -891,9 +900,10 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
891 | { | 900 | { |
892 | struct fsi_priv *fsi = fsi_get_priv(substream); | 901 | struct fsi_priv *fsi = fsi_get_priv(substream); |
893 | struct fsi_master *master = fsi_get_master(fsi); | 902 | struct fsi_master *master = fsi_get_master(fsi); |
894 | int (*set_rate)(int is_porta, int rate) = master->info->set_rate; | 903 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); |
895 | int fsi_ver = master->core->ver; | 904 | int fsi_ver = master->core->ver; |
896 | int is_play = fsi_is_play(substream); | 905 | int is_play = fsi_is_play(substream); |
906 | long rate = params_rate(params); | ||
897 | int ret; | 907 | int ret; |
898 | 908 | ||
899 | /* if slave mode, set_rate is not needed */ | 909 | /* if slave mode, set_rate is not needed */ |
@@ -901,10 +911,15 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
901 | return 0; | 911 | return 0; |
902 | 912 | ||
903 | /* it is error if no set_rate */ | 913 | /* it is error if no set_rate */ |
914 | set_rate = master->info->set_rate; | ||
904 | if (!set_rate) | 915 | if (!set_rate) |
905 | return -EIO; | 916 | return -EIO; |
906 | 917 | ||
907 | ret = set_rate(fsi_is_port_a(fsi), params_rate(params)); | 918 | ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); |
919 | if (ret < 0) /* error */ | ||
920 | return ret; | ||
921 | |||
922 | fsi->rate = rate; | ||
908 | if (ret > 0) { | 923 | if (ret > 0) { |
909 | u32 data = 0; | 924 | u32 data = 0; |
910 | 925 | ||