diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-01-05 21:44:15 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-05 22:17:18 -0500 |
commit | 98d27b8abf413a310df6676f7d2128ada1cccc08 (patch) | |
tree | 5fc2a5cc95b1e3188f341194c2d79045b3cb690c | |
parent | 12c4309b78854ba117ea38a9178018591abd16ab (diff) |
ARM: mach-shmobile: mackerel: Add HDMI sound support
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-mackerel.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index c7d378b57cfc..6a5ce9a0dcf3 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
@@ -373,6 +373,7 @@ static struct platform_device hdmi_lcdc_device = { | |||
373 | static struct sh_mobile_hdmi_info hdmi_info = { | 373 | static struct sh_mobile_hdmi_info hdmi_info = { |
374 | .lcd_chan = &hdmi_lcdc_info.ch[0], | 374 | .lcd_chan = &hdmi_lcdc_info.ch[0], |
375 | .lcd_dev = &hdmi_lcdc_device.dev, | 375 | .lcd_dev = &hdmi_lcdc_device.dev, |
376 | .flags = HDMI_SND_SRC_SPDIF, | ||
376 | }; | 377 | }; |
377 | 378 | ||
378 | static struct resource hdmi_resources[] = { | 379 | static struct resource hdmi_resources[] = { |
@@ -534,12 +535,93 @@ static struct platform_device leds_device = { | |||
534 | 535 | ||
535 | /* FSI */ | 536 | /* FSI */ |
536 | #define IRQ_FSI evt2irq(0x1840) | 537 | #define IRQ_FSI evt2irq(0x1840) |
538 | static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) | ||
539 | { | ||
540 | int ret; | ||
541 | |||
542 | if (rate <= 0) | ||
543 | return 0; | ||
544 | |||
545 | if (!enable) { | ||
546 | clk_disable(clk); | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | ret = clk_set_rate(clk, clk_round_rate(clk, rate)); | ||
551 | if (ret < 0) | ||
552 | return ret; | ||
553 | |||
554 | return clk_enable(clk); | ||
555 | } | ||
556 | |||
557 | static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) | ||
558 | { | ||
559 | struct clk *fsib_clk; | ||
560 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; | ||
561 | long fsib_rate = 0; | ||
562 | long fdiv_rate = 0; | ||
563 | int ackmd_bpfmd; | ||
564 | int ret; | ||
565 | |||
566 | /* FSIA is slave mode. nothing to do here */ | ||
567 | if (is_porta) | ||
568 | return 0; | ||
569 | |||
570 | /* clock start */ | ||
571 | switch (rate) { | ||
572 | case 44100: | ||
573 | fsib_rate = rate * 256; | ||
574 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
575 | break; | ||
576 | case 48000: | ||
577 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ | ||
578 | fdiv_rate = rate * 256; | ||
579 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
580 | break; | ||
581 | default: | ||
582 | pr_err("unsupported rate in FSI2 port B\n"); | ||
583 | return -EINVAL; | ||
584 | } | ||
585 | |||
586 | /* FSI B setting */ | ||
587 | fsib_clk = clk_get(dev, "ickb"); | ||
588 | if (IS_ERR(fsib_clk)) | ||
589 | return -EIO; | ||
590 | |||
591 | /* fsib */ | ||
592 | ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable); | ||
593 | if (ret < 0) | ||
594 | goto fsi_set_rate_end; | ||
595 | |||
596 | /* FSI DIV */ | ||
597 | ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable); | ||
598 | if (ret < 0) { | ||
599 | /* disable FSI B */ | ||
600 | if (enable) | ||
601 | __fsi_set_round_rate(fsib_clk, fsib_rate, 0); | ||
602 | goto fsi_set_rate_end; | ||
603 | } | ||
604 | |||
605 | ret = ackmd_bpfmd; | ||
606 | |||
607 | fsi_set_rate_end: | ||
608 | clk_put(fsib_clk); | ||
609 | return ret; | ||
610 | } | ||
611 | |||
537 | static struct sh_fsi_platform_info fsi_info = { | 612 | static struct sh_fsi_platform_info fsi_info = { |
538 | .porta_flags = SH_FSI_BRS_INV | | 613 | .porta_flags = SH_FSI_BRS_INV | |
539 | SH_FSI_OUT_SLAVE_MODE | | 614 | SH_FSI_OUT_SLAVE_MODE | |
540 | SH_FSI_IN_SLAVE_MODE | | 615 | SH_FSI_IN_SLAVE_MODE | |
541 | SH_FSI_OFMT(PCM) | | 616 | SH_FSI_OFMT(PCM) | |
542 | SH_FSI_IFMT(PCM), | 617 | SH_FSI_IFMT(PCM), |
618 | |||
619 | .portb_flags = SH_FSI_BRS_INV | | ||
620 | SH_FSI_BRM_INV | | ||
621 | SH_FSI_LRS_INV | | ||
622 | SH_FSI_OFMT(SPDIF), | ||
623 | |||
624 | .set_rate = fsi_set_rate, | ||
543 | }; | 625 | }; |
544 | 626 | ||
545 | static struct resource fsi_resources[] = { | 627 | static struct resource fsi_resources[] = { |
@@ -919,9 +1001,11 @@ static void __init mackerel_map_io(void) | |||
919 | #define GPIO_PORT9CR 0xE6051009 | 1001 | #define GPIO_PORT9CR 0xE6051009 |
920 | #define GPIO_PORT10CR 0xE605100A | 1002 | #define GPIO_PORT10CR 0xE605100A |
921 | #define SRCR4 0xe61580bc | 1003 | #define SRCR4 0xe61580bc |
1004 | #define USCCR1 0xE6058144 | ||
922 | static void __init mackerel_init(void) | 1005 | static void __init mackerel_init(void) |
923 | { | 1006 | { |
924 | u32 srcr4; | 1007 | u32 srcr4; |
1008 | struct clk *clk; | ||
925 | 1009 | ||
926 | sh7372_pinmux_init(); | 1010 | sh7372_pinmux_init(); |
927 | 1011 | ||
@@ -993,6 +1077,17 @@ static void __init mackerel_init(void) | |||
993 | 1077 | ||
994 | intc_set_priority(IRQ_FSI, 3); /* irq priority FSI(3) > SMSC911X(2) */ | 1078 | intc_set_priority(IRQ_FSI, 3); /* irq priority FSI(3) > SMSC911X(2) */ |
995 | 1079 | ||
1080 | /* setup FSI2 port B (HDMI) */ | ||
1081 | gpio_request(GPIO_FN_FSIBCK, NULL); | ||
1082 | __raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */ | ||
1083 | |||
1084 | /* set SPU2 clock to 119.6 MHz */ | ||
1085 | clk = clk_get(NULL, "spu_clk"); | ||
1086 | if (!IS_ERR(clk)) { | ||
1087 | clk_set_rate(clk, clk_round_rate(clk, 119600000)); | ||
1088 | clk_put(clk); | ||
1089 | } | ||
1090 | |||
996 | /* enable Keypad */ | 1091 | /* enable Keypad */ |
997 | gpio_request(GPIO_FN_IRQ9_42, NULL); | 1092 | gpio_request(GPIO_FN_IRQ9_42, NULL); |
998 | set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH); | 1093 | set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH); |