aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-10-28 15:14:38 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-10-28 15:14:38 -0400
commitb3773301c4290f054aa2aa5379e59a1bf4f78bdf (patch)
treeaac1619d32800393b587bf034c7dadb9e3c24f7b
parentbe6786ac738801d39cfd264ec88c352efd029578 (diff)
parent1a0b1eac5012326e52d1dcf78695ac08f41c37d7 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/genesis-2.6 into devel-stable
Conflicts: drivers/video/sh_mobile_hdmi.c
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c326
-rw-r--r--arch/arm/mach-shmobile/clock-sh7367.c2
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c78
-rw-r--r--arch/arm/mach-shmobile/clock-sh7377.c2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h10
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c28
-rw-r--r--arch/arm/mach-shmobile/pfc-sh7372.c8
-rw-r--r--arch/arm/mach-shmobile/setup-sh7367.c1
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c94
-rw-r--r--arch/arm/mach-shmobile/setup-sh7377.c1
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c29
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c60
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c29
-rw-r--r--arch/sh/boards/mach-migor/setup.c58
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c54
-rw-r--r--drivers/video/sh_mipi_dsi.c32
-rw-r--r--drivers/video/sh_mobile_hdmi.c629
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c348
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h41
-rw-r--r--include/video/sh_mobile_lcdc.h5
20 files changed, 1222 insertions, 613 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 14923989ea05..f5d55efda386 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -30,7 +30,6 @@
30#include <linux/mtd/mtd.h> 30#include <linux/mtd/mtd.h>
31#include <linux/mtd/partitions.h> 31#include <linux/mtd/partitions.h>
32#include <linux/mtd/physmap.h> 32#include <linux/mtd/physmap.h>
33#include <linux/mmc/host.h>
34#include <linux/mmc/sh_mmcif.h> 33#include <linux/mmc/sh_mmcif.h>
35#include <linux/i2c.h> 34#include <linux/i2c.h>
36#include <linux/i2c/tsc2007.h> 35#include <linux/i2c/tsc2007.h>
@@ -44,6 +43,10 @@
44#include <linux/input/sh_keysc.h> 43#include <linux/input/sh_keysc.h>
45#include <linux/usb/r8a66597.h> 44#include <linux/usb/r8a66597.h>
46 45
46#include <media/sh_mobile_ceu.h>
47#include <media/sh_mobile_csi2.h>
48#include <media/soc_camera.h>
49
47#include <sound/sh_fsi.h> 50#include <sound/sh_fsi.h>
48 51
49#include <video/sh_mobile_hdmi.h> 52#include <video/sh_mobile_hdmi.h>
@@ -238,7 +241,7 @@ static struct platform_device smc911x_device = {
238/* SH_MMCIF */ 241/* SH_MMCIF */
239static struct resource sh_mmcif_resources[] = { 242static struct resource sh_mmcif_resources[] = {
240 [0] = { 243 [0] = {
241 .name = "SH_MMCIF", 244 .name = "MMCIF",
242 .start = 0xE6BD0000, 245 .start = 0xE6BD0000,
243 .end = 0xE6BD00FF, 246 .end = 0xE6BD00FF,
244 .flags = IORESOURCE_MEM, 247 .flags = IORESOURCE_MEM,
@@ -375,10 +378,40 @@ static struct platform_device usb1_host_device = {
375 .resource = usb1_host_resources, 378 .resource = usb1_host_resources,
376}; 379};
377 380
381const static struct fb_videomode ap4evb_lcdc_modes[] = {
382 {
383#ifdef CONFIG_AP4EVB_QHD
384 .name = "R63302(QHD)",
385 .xres = 544,
386 .yres = 961,
387 .left_margin = 72,
388 .right_margin = 600,
389 .hsync_len = 16,
390 .upper_margin = 8,
391 .lower_margin = 8,
392 .vsync_len = 2,
393 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
394#else
395 .name = "WVGA Panel",
396 .xres = 800,
397 .yres = 480,
398 .left_margin = 220,
399 .right_margin = 110,
400 .hsync_len = 70,
401 .upper_margin = 20,
402 .lower_margin = 5,
403 .vsync_len = 5,
404 .sync = 0,
405#endif
406 },
407};
408
378static struct sh_mobile_lcdc_info lcdc_info = { 409static struct sh_mobile_lcdc_info lcdc_info = {
379 .ch[0] = { 410 .ch[0] = {
380 .chan = LCDC_CHAN_MAINLCD, 411 .chan = LCDC_CHAN_MAINLCD,
381 .bpp = 16, 412 .bpp = 16,
413 .lcd_cfg = ap4evb_lcdc_modes,
414 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
382 } 415 }
383}; 416};
384 417
@@ -517,27 +550,6 @@ static struct platform_device *qhd_devices[] __initdata = {
517 550
518/* FSI */ 551/* FSI */
519#define IRQ_FSI evt2irq(0x1840) 552#define IRQ_FSI evt2irq(0x1840)
520#define FSIACKCR 0xE6150018
521static void fsiackcr_init(struct clk *clk)
522{
523 u32 status = __raw_readl(clk->enable_reg);
524
525 /* use external clock */
526 status &= ~0x000000ff;
527 status |= 0x00000080;
528 __raw_writel(status, clk->enable_reg);
529}
530
531static struct clk_ops fsiackcr_clk_ops = {
532 .init = fsiackcr_init,
533};
534
535static struct clk fsiackcr_clk = {
536 .ops = &fsiackcr_clk_ops,
537 .enable_reg = (void __iomem *)FSIACKCR,
538 .rate = 0, /* unknown */
539};
540
541static struct sh_fsi_platform_info fsi_info = { 553static struct sh_fsi_platform_info fsi_info = {
542 .porta_flags = SH_FSI_BRS_INV | 554 .porta_flags = SH_FSI_BRS_INV |
543 SH_FSI_OUT_SLAVE_MODE | 555 SH_FSI_OUT_SLAVE_MODE |
@@ -577,26 +589,6 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
577 .interface_type = RGB24, 589 .interface_type = RGB24,
578 .clock_divider = 1, 590 .clock_divider = 1,
579 .flags = LCDC_FLAGS_DWPOL, 591 .flags = LCDC_FLAGS_DWPOL,
580 .lcd_cfg = {
581 .name = "HDMI",
582 /* So far only 720p is supported */
583 .xres = 1280,
584 .yres = 720,
585 /*
586 * If left and right margins are not multiples of 8,
587 * LDHAJR will be adjusted accordingly by the LCDC
588 * driver. Until we start using EDID, these values
589 * might have to be adjusted for different monitors.
590 */
591 .left_margin = 200,
592 .right_margin = 88,
593 .hsync_len = 48,
594 .upper_margin = 20,
595 .lower_margin = 5,
596 .vsync_len = 5,
597 .pixclock = 13468,
598 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
599 },
600 } 592 }
601}; 593};
602 594
@@ -608,7 +600,7 @@ static struct resource lcdc1_resources[] = {
608 .flags = IORESOURCE_MEM, 600 .flags = IORESOURCE_MEM,
609 }, 601 },
610 [1] = { 602 [1] = {
611 .start = intcs_evt2irq(0x17a0), 603 .start = intcs_evt2irq(0x1780),
612 .flags = IORESOURCE_IRQ, 604 .flags = IORESOURCE_IRQ,
613 }, 605 },
614}; 606};
@@ -689,6 +681,95 @@ static struct platform_device leds_device = {
689 }, 681 },
690}; 682};
691 683
684static struct i2c_board_info imx074_info = {
685 I2C_BOARD_INFO("imx074", 0x1a),
686};
687
688struct soc_camera_link imx074_link = {
689 .bus_id = 0,
690 .board_info = &imx074_info,
691 .i2c_adapter_id = 0,
692 .module_name = "imx074",
693};
694
695static struct platform_device ap4evb_camera = {
696 .name = "soc-camera-pdrv",
697 .id = 0,
698 .dev = {
699 .platform_data = &imx074_link,
700 },
701};
702
703static struct sh_csi2_client_config csi2_clients[] = {
704 {
705 .phy = SH_CSI2_PHY_MAIN,
706 .lanes = 3,
707 .channel = 0,
708 .pdev = &ap4evb_camera,
709 },
710};
711
712static struct sh_csi2_pdata csi2_info = {
713 .type = SH_CSI2C,
714 .clients = csi2_clients,
715 .num_clients = ARRAY_SIZE(csi2_clients),
716 .flags = SH_CSI2_ECC | SH_CSI2_CRC,
717};
718
719static struct resource csi2_resources[] = {
720 [0] = {
721 .name = "CSI2",
722 .start = 0xffc90000,
723 .end = 0xffc90fff,
724 .flags = IORESOURCE_MEM,
725 },
726 [1] = {
727 .start = intcs_evt2irq(0x17a0),
728 .flags = IORESOURCE_IRQ,
729 },
730};
731
732static struct platform_device csi2_device = {
733 .name = "sh-mobile-csi2",
734 .id = 0,
735 .num_resources = ARRAY_SIZE(csi2_resources),
736 .resource = csi2_resources,
737 .dev = {
738 .platform_data = &csi2_info,
739 },
740};
741
742static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
743 .flags = SH_CEU_FLAG_USE_8BIT_BUS,
744 .csi2_dev = &csi2_device.dev,
745};
746
747static struct resource ceu_resources[] = {
748 [0] = {
749 .name = "CEU",
750 .start = 0xfe910000,
751 .end = 0xfe91009f,
752 .flags = IORESOURCE_MEM,
753 },
754 [1] = {
755 .start = intcs_evt2irq(0x880),
756 .flags = IORESOURCE_IRQ,
757 },
758 [2] = {
759 /* place holder for contiguous memory */
760 },
761};
762
763static struct platform_device ceu_device = {
764 .name = "sh_mobile_ceu",
765 .id = 0, /* "ceu0" clock */
766 .num_resources = ARRAY_SIZE(ceu_resources),
767 .resource = ceu_resources,
768 .dev = {
769 .platform_data = &sh_mobile_ceu_info,
770 },
771};
772
692static struct platform_device *ap4evb_devices[] __initdata = { 773static struct platform_device *ap4evb_devices[] __initdata = {
693 &leds_device, 774 &leds_device,
694 &nor_flash_device, 775 &nor_flash_device,
@@ -701,6 +782,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
701 &lcdc1_device, 782 &lcdc1_device,
702 &lcdc_device, 783 &lcdc_device,
703 &hdmi_device, 784 &hdmi_device,
785 &csi2_device,
786 &ceu_device,
787 &ap4evb_camera,
704}; 788};
705 789
706static int __init hdmi_init_pm_clock(void) 790static int __init hdmi_init_pm_clock(void)
@@ -715,22 +799,22 @@ static int __init hdmi_init_pm_clock(void)
715 goto out; 799 goto out;
716 } 800 }
717 801
718 ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk); 802 ret = clk_set_parent(&sh7372_pllc2_clk, &sh7372_dv_clki_div2_clk);
719 if (ret < 0) { 803 if (ret < 0) {
720 pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount); 804 pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, sh7372_pllc2_clk.usecount);
721 goto out; 805 goto out;
722 } 806 }
723 807
724 pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk)); 808 pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&sh7372_pllc2_clk));
725 809
726 rate = clk_round_rate(&pllc2_clk, 594000000); 810 rate = clk_round_rate(&sh7372_pllc2_clk, 594000000);
727 if (rate < 0) { 811 if (rate < 0) {
728 pr_err("Cannot get suitable rate: %ld\n", rate); 812 pr_err("Cannot get suitable rate: %ld\n", rate);
729 ret = rate; 813 ret = rate;
730 goto out; 814 goto out;
731 } 815 }
732 816
733 ret = clk_set_rate(&pllc2_clk, rate); 817 ret = clk_set_rate(&sh7372_pllc2_clk, rate);
734 if (ret < 0) { 818 if (ret < 0) {
735 pr_err("Cannot set rate %ld: %d\n", rate, ret); 819 pr_err("Cannot set rate %ld: %d\n", rate, ret);
736 goto out; 820 goto out;
@@ -738,7 +822,7 @@ static int __init hdmi_init_pm_clock(void)
738 822
739 pr_debug("PLLC2 set frequency %lu\n", rate); 823 pr_debug("PLLC2 set frequency %lu\n", rate);
740 824
741 ret = clk_set_parent(hdmi_ick, &pllc2_clk); 825 ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
742 if (ret < 0) { 826 if (ret < 0) {
743 pr_err("Cannot set HDMI parent: %d\n", ret); 827 pr_err("Cannot set HDMI parent: %d\n", ret);
744 goto out; 828 goto out;
@@ -752,11 +836,51 @@ out:
752 836
753device_initcall(hdmi_init_pm_clock); 837device_initcall(hdmi_init_pm_clock);
754 838
839#define FSIACK_DUMMY_RATE 48000
840static int __init fsi_init_pm_clock(void)
841{
842 struct clk *fsia_ick;
843 int ret;
844
845 /*
846 * FSIACK is connected to AK4642,
847 * and the rate is depend on playing sound rate.
848 * So, set dummy rate (= 48k) here
849 */
850 ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE);
851 if (ret < 0) {
852 pr_err("Cannot set FSIACK dummy rate: %d\n", ret);
853 return ret;
854 }
855
856 fsia_ick = clk_get(&fsi_device.dev, "icka");
857 if (IS_ERR(fsia_ick)) {
858 ret = PTR_ERR(fsia_ick);
859 pr_err("Cannot get FSI ICK: %d\n", ret);
860 return ret;
861 }
862
863 ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
864 if (ret < 0) {
865 pr_err("Cannot set FSI-A parent: %d\n", ret);
866 goto out;
867 }
868
869 ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE);
870 if (ret < 0)
871 pr_err("Cannot set FSI-A rate: %d\n", ret);
872
873out:
874 clk_put(fsia_ick);
875
876 return ret;
877}
878device_initcall(fsi_init_pm_clock);
879
755/* 880/*
756 * FIXME !! 881 * FIXME !!
757 * 882 *
758 * gpio_no_direction 883 * gpio_no_direction
759 * gpio_pull_up
760 * are quick_hack. 884 * are quick_hack.
761 * 885 *
762 * current gpio frame work doesn't have 886 * current gpio frame work doesn't have
@@ -768,49 +892,37 @@ static void __init gpio_no_direction(u32 addr)
768 __raw_writeb(0x00, addr); 892 __raw_writeb(0x00, addr);
769} 893}
770 894
771static void __init gpio_pull_up(u32 addr)
772{
773 u8 data = __raw_readb(addr);
774
775 data &= 0x0F;
776 data |= 0xC0;
777 __raw_writeb(data, addr);
778}
779
780/* TouchScreen */ 895/* TouchScreen */
896#ifdef CONFIG_AP4EVB_QHD
897# define GPIO_TSC_IRQ GPIO_FN_IRQ28_123
898# define GPIO_TSC_PORT GPIO_PORT123
899#else /* WVGA */
900# define GPIO_TSC_IRQ GPIO_FN_IRQ7_40
901# define GPIO_TSC_PORT GPIO_PORT40
902#endif
903
781#define IRQ28 evt2irq(0x3380) /* IRQ28A */ 904#define IRQ28 evt2irq(0x3380) /* IRQ28A */
782#define IRQ7 evt2irq(0x02e0) /* IRQ7A */ 905#define IRQ7 evt2irq(0x02e0) /* IRQ7A */
783static int ts_get_pendown_state(void) 906static int ts_get_pendown_state(void)
784{ 907{
785 int val1, val2; 908 int val;
786 909
787 gpio_free(GPIO_FN_IRQ28_123); 910 gpio_free(GPIO_TSC_IRQ);
788 gpio_free(GPIO_FN_IRQ7_40);
789 911
790 gpio_request(GPIO_PORT123, NULL); 912 gpio_request(GPIO_TSC_PORT, NULL);
791 gpio_request(GPIO_PORT40, NULL);
792 913
793 gpio_direction_input(GPIO_PORT123); 914 gpio_direction_input(GPIO_TSC_PORT);
794 gpio_direction_input(GPIO_PORT40);
795 915
796 val1 = gpio_get_value(GPIO_PORT123); 916 val = gpio_get_value(GPIO_TSC_PORT);
797 val2 = gpio_get_value(GPIO_PORT40);
798 917
799 gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ 918 gpio_request(GPIO_TSC_IRQ, NULL);
800 gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */
801 919
802 return val1 ^ val2; 920 return !val;
803} 921}
804 922
805#define PORT40CR 0xE6051028
806#define PORT123CR 0xE605007B
807static int ts_init(void) 923static int ts_init(void)
808{ 924{
809 gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ 925 gpio_request(GPIO_TSC_IRQ, NULL);
810 gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */
811
812 gpio_pull_up(PORT40CR);
813 gpio_pull_up(PORT123CR);
814 926
815 return 0; 927 return 0;
816} 928}
@@ -955,14 +1067,6 @@ static void __init ap4evb_init(void)
955 clk_put(clk); 1067 clk_put(clk);
956 } 1068 }
957 1069
958 /* change parent of FSI A */
959 clk = clk_get(NULL, "fsia_clk");
960 if (!IS_ERR(clk)) {
961 clk_register(&fsiackcr_clk);
962 clk_set_parent(clk, &fsiackcr_clk);
963 clk_put(clk);
964 }
965
966 /* 1070 /*
967 * set irq priority, to avoid sound chopping 1071 * set irq priority, to avoid sound chopping
968 * when NFS rootfs is used 1072 * when NFS rootfs is used
@@ -977,8 +1081,10 @@ static void __init ap4evb_init(void)
977 ARRAY_SIZE(i2c1_devices)); 1081 ARRAY_SIZE(i2c1_devices));
978 1082
979#ifdef CONFIG_AP4EVB_QHD 1083#ifdef CONFIG_AP4EVB_QHD
1084
980 /* 1085 /*
981 * QHD 1086 * For QHD Panel (MIPI-DSI, CONFIG_AP4EVB_QHD=y) and
1087 * IRQ28 for Touch Panel, set dip switches S3, S43 as OFF, ON.
982 */ 1088 */
983 1089
984 /* enable KEYSC */ 1090 /* enable KEYSC */
@@ -1004,17 +1110,6 @@ static void __init ap4evb_init(void)
1004 lcdc_info.ch[0].interface_type = RGB24; 1110 lcdc_info.ch[0].interface_type = RGB24;
1005 lcdc_info.ch[0].clock_divider = 1; 1111 lcdc_info.ch[0].clock_divider = 1;
1006 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; 1112 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL;
1007 lcdc_info.ch[0].lcd_cfg.name = "R63302(QHD)";
1008 lcdc_info.ch[0].lcd_cfg.xres = 544;
1009 lcdc_info.ch[0].lcd_cfg.yres = 961;
1010 lcdc_info.ch[0].lcd_cfg.left_margin = 72;
1011 lcdc_info.ch[0].lcd_cfg.right_margin = 600;
1012 lcdc_info.ch[0].lcd_cfg.hsync_len = 16;
1013 lcdc_info.ch[0].lcd_cfg.upper_margin = 8;
1014 lcdc_info.ch[0].lcd_cfg.lower_margin = 8;
1015 lcdc_info.ch[0].lcd_cfg.vsync_len = 2;
1016 lcdc_info.ch[0].lcd_cfg.sync = FB_SYNC_VERT_HIGH_ACT |
1017 FB_SYNC_HOR_HIGH_ACT;
1018 lcdc_info.ch[0].lcd_size_cfg.width = 44; 1113 lcdc_info.ch[0].lcd_size_cfg.width = 44;
1019 lcdc_info.ch[0].lcd_size_cfg.height = 79; 1114 lcdc_info.ch[0].lcd_size_cfg.height = 79;
1020 1115
@@ -1022,8 +1117,10 @@ static void __init ap4evb_init(void)
1022 1117
1023#else 1118#else
1024 /* 1119 /*
1025 * WVGA 1120 * For WVGA Panel (18-bit RGB, CONFIG_AP4EVB_WVGA=y) and
1121 * IRQ7 for Touch Panel, set dip switches S3, S43 to ON, OFF.
1026 */ 1122 */
1123
1027 gpio_request(GPIO_FN_LCDD17, NULL); 1124 gpio_request(GPIO_FN_LCDD17, NULL);
1028 gpio_request(GPIO_FN_LCDD16, NULL); 1125 gpio_request(GPIO_FN_LCDD16, NULL);
1029 gpio_request(GPIO_FN_LCDD15, NULL); 1126 gpio_request(GPIO_FN_LCDD15, NULL);
@@ -1055,16 +1152,6 @@ static void __init ap4evb_init(void)
1055 lcdc_info.ch[0].interface_type = RGB18; 1152 lcdc_info.ch[0].interface_type = RGB18;
1056 lcdc_info.ch[0].clock_divider = 2; 1153 lcdc_info.ch[0].clock_divider = 2;
1057 lcdc_info.ch[0].flags = 0; 1154 lcdc_info.ch[0].flags = 0;
1058 lcdc_info.ch[0].lcd_cfg.name = "WVGA Panel";
1059 lcdc_info.ch[0].lcd_cfg.xres = 800;
1060 lcdc_info.ch[0].lcd_cfg.yres = 480;
1061 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1062 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1063 lcdc_info.ch[0].lcd_cfg.hsync_len = 70;
1064 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1065 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1066 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1067 lcdc_info.ch[0].lcd_cfg.sync = 0;
1068 lcdc_info.ch[0].lcd_size_cfg.width = 152; 1155 lcdc_info.ch[0].lcd_size_cfg.width = 152;
1069 lcdc_info.ch[0].lcd_size_cfg.height = 91; 1156 lcdc_info.ch[0].lcd_size_cfg.height = 91;
1070 1157
@@ -1075,6 +1162,23 @@ static void __init ap4evb_init(void)
1075 i2c_register_board_info(0, &tsc_device, 1); 1162 i2c_register_board_info(0, &tsc_device, 1);
1076#endif /* CONFIG_AP4EVB_QHD */ 1163#endif /* CONFIG_AP4EVB_QHD */
1077 1164
1165 /* CEU */
1166
1167 /*
1168 * TODO: reserve memory for V4L2 DMA buffers, when a suitable API
1169 * becomes available
1170 */
1171
1172 /* MIPI-CSI stuff */
1173 gpio_request(GPIO_FN_VIO_CKO, NULL);
1174
1175 clk = clk_get(NULL, "vck1_clk");
1176 if (!IS_ERR(clk)) {
1177 clk_set_rate(clk, clk_round_rate(clk, 13000000));
1178 clk_enable(clk);
1179 clk_put(clk);
1180 }
1181
1078 sh7372_add_standard_devices(); 1182 sh7372_add_standard_devices();
1079 1183
1080 /* HDMI */ 1184 /* HDMI */
@@ -1097,7 +1201,7 @@ static void __init ap4evb_timer_init(void)
1097 shmobile_timer.init(); 1201 shmobile_timer.init();
1098 1202
1099 /* External clock source */ 1203 /* External clock source */
1100 clk_set_rate(&dv_clki_clk, 27000000); 1204 clk_set_rate(&sh7372_dv_clki_clk, 27000000);
1101} 1205}
1102 1206
1103static struct sys_timer ap4evb_timer = { 1207static struct sys_timer ap4evb_timer = {
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
index b6454c9f2abb..9f78729098f2 100644
--- a/arch/arm/mach-shmobile/clock-sh7367.c
+++ b/arch/arm/mach-shmobile/clock-sh7367.c
@@ -321,7 +321,7 @@ static struct clk_lookup lookups[] = {
321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */ 321 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */
322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */ 322 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */
323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */ 323 CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */
324 CLKDEV_CON_ID("cmt1", &mstp_clks[SYMSTP229]), /* CMT10 */ 324 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */
325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */ 325 CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */
326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */ 326 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */
327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */ 327 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 759468992ad2..8565aefa21fd 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -51,7 +51,7 @@
51#define SMSTPCR4 0xe6150140 51#define SMSTPCR4 0xe6150140
52 52
53/* Platforms must set frequency on their DV_CLKI pin */ 53/* Platforms must set frequency on their DV_CLKI pin */
54struct clk dv_clki_clk = { 54struct clk sh7372_dv_clki_clk = {
55}; 55};
56 56
57/* Fixed 32 KHz root clock from EXTALR pin */ 57/* Fixed 32 KHz root clock from EXTALR pin */
@@ -86,9 +86,9 @@ static struct clk_ops div2_clk_ops = {
86}; 86};
87 87
88/* Divide dv_clki by two */ 88/* Divide dv_clki by two */
89struct clk dv_clki_div2_clk = { 89struct clk sh7372_dv_clki_div2_clk = {
90 .ops = &div2_clk_ops, 90 .ops = &div2_clk_ops,
91 .parent = &dv_clki_clk, 91 .parent = &sh7372_dv_clki_clk,
92}; 92};
93 93
94/* Divide extal1 by two */ 94/* Divide extal1 by two */
@@ -150,7 +150,7 @@ static struct clk pllc1_div2_clk = {
150static struct clk *pllc2_parent[] = { 150static struct clk *pllc2_parent[] = {
151 [0] = &extal1_div2_clk, 151 [0] = &extal1_div2_clk,
152 [1] = &extal2_div2_clk, 152 [1] = &extal2_div2_clk,
153 [2] = &dv_clki_div2_clk, 153 [2] = &sh7372_dv_clki_div2_clk,
154}; 154};
155 155
156/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */ 156/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */
@@ -284,7 +284,7 @@ static struct clk_ops pllc2_clk_ops = {
284 .set_parent = pllc2_set_parent, 284 .set_parent = pllc2_set_parent,
285}; 285};
286 286
287struct clk pllc2_clk = { 287struct clk sh7372_pllc2_clk = {
288 .ops = &pllc2_clk_ops, 288 .ops = &pllc2_clk_ops,
289 .parent = &extal1_div2_clk, 289 .parent = &extal1_div2_clk,
290 .freq_table = pllc2_freq_table, 290 .freq_table = pllc2_freq_table,
@@ -292,19 +292,28 @@ struct clk pllc2_clk = {
292 .parent_num = ARRAY_SIZE(pllc2_parent), 292 .parent_num = ARRAY_SIZE(pllc2_parent),
293}; 293};
294 294
295/* External input clock (pin name: FSIACK/FSIBCK ) */
296struct clk sh7372_fsiack_clk = {
297};
298
299struct clk sh7372_fsibck_clk = {
300};
301
295static struct clk *main_clks[] = { 302static struct clk *main_clks[] = {
296 &dv_clki_clk, 303 &sh7372_dv_clki_clk,
297 &r_clk, 304 &r_clk,
298 &sh7372_extal1_clk, 305 &sh7372_extal1_clk,
299 &sh7372_extal2_clk, 306 &sh7372_extal2_clk,
300 &dv_clki_div2_clk, 307 &sh7372_dv_clki_div2_clk,
301 &extal1_div2_clk, 308 &extal1_div2_clk,
302 &extal2_div2_clk, 309 &extal2_div2_clk,
303 &extal2_div4_clk, 310 &extal2_div4_clk,
304 &pllc0_clk, 311 &pllc0_clk,
305 &pllc1_clk, 312 &pllc1_clk,
306 &pllc1_div2_clk, 313 &pllc1_div2_clk,
307 &pllc2_clk, 314 &sh7372_pllc2_clk,
315 &sh7372_fsiack_clk,
316 &sh7372_fsibck_clk,
308}; 317};
309 318
310static void div4_kick(struct clk *clk) 319static void div4_kick(struct clk *clk)
@@ -357,7 +366,7 @@ static struct clk div4_clks[DIV4_NR] = {
357}; 366};
358 367
359enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO, 368enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO,
360 DIV6_FSIA, DIV6_FSIB, DIV6_SUB, DIV6_SPU, 369 DIV6_SUB, DIV6_SPU,
361 DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P, 370 DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
362 DIV6_NR }; 371 DIV6_NR };
363 372
@@ -367,8 +376,6 @@ static struct clk div6_clks[DIV6_NR] = {
367 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0), 376 [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
368 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0), 377 [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0),
369 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0), 378 [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0),
370 [DIV6_FSIA] = SH_CLK_DIV6(&pllc1_div2_clk, FSIACKCR, 0),
371 [DIV6_FSIB] = SH_CLK_DIV6(&pllc1_div2_clk, FSIBCKCR, 0),
372 [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0), 379 [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0),
373 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0), 380 [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
374 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0), 381 [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
@@ -377,24 +384,42 @@ static struct clk div6_clks[DIV6_NR] = {
377 [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0), 384 [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0),
378}; 385};
379 386
380enum { DIV6_HDMI, DIV6_REPARENT_NR }; 387enum { DIV6_HDMI, DIV6_FSIA, DIV6_FSIB, DIV6_REPARENT_NR };
381 388
382/* Indices are important - they are the actual src selecting values */ 389/* Indices are important - they are the actual src selecting values */
383static struct clk *hdmi_parent[] = { 390static struct clk *hdmi_parent[] = {
384 [0] = &pllc1_div2_clk, 391 [0] = &pllc1_div2_clk,
385 [1] = &pllc2_clk, 392 [1] = &sh7372_pllc2_clk,
386 [2] = &dv_clki_clk, 393 [2] = &sh7372_dv_clki_clk,
387 [3] = NULL, /* pllc2_div4 not implemented yet */ 394 [3] = NULL, /* pllc2_div4 not implemented yet */
388}; 395};
389 396
397static struct clk *fsiackcr_parent[] = {
398 [0] = &pllc1_div2_clk,
399 [1] = &sh7372_pllc2_clk,
400 [2] = &sh7372_fsiack_clk, /* external input for FSI A */
401 [3] = NULL, /* setting prohibited */
402};
403
404static struct clk *fsibckcr_parent[] = {
405 [0] = &pllc1_div2_clk,
406 [1] = &sh7372_pllc2_clk,
407 [2] = &sh7372_fsibck_clk, /* external input for FSI B */
408 [3] = NULL, /* setting prohibited */
409};
410
390static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { 411static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
391 [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0, 412 [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0,
392 hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), 413 hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
414 [DIV6_FSIA] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIACKCR, 0,
415 fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2),
416 [DIV6_FSIB] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIBCKCR, 0,
417 fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2),
393}; 418};
394 419
395enum { MSTP001, 420enum { MSTP001,
396 MSTP131, MSTP130, 421 MSTP131, MSTP130,
397 MSTP129, MSTP128, MSTP127, MSTP126, 422 MSTP129, MSTP128, MSTP127, MSTP126, MSTP125,
398 MSTP118, MSTP117, MSTP116, 423 MSTP118, MSTP117, MSTP116,
399 MSTP106, MSTP101, MSTP100, 424 MSTP106, MSTP101, MSTP100,
400 MSTP223, 425 MSTP223,
@@ -414,6 +439,7 @@ static struct clk mstp_clks[MSTP_NR] = {
414 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */ 439 [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
415 [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */ 440 [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */
416 [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */ 441 [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */
442 [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
417 [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ 443 [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */
418 [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ 444 [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
419 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ 445 [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
@@ -429,7 +455,7 @@ static struct clk mstp_clks[MSTP_NR] = {
429 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ 455 [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
430 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ 456 [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
431 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ 457 [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
432 [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSIA */ 458 [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */
433 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ 459 [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
434 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ 460 [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
435 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ 461 [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
@@ -445,10 +471,11 @@ static struct clk mstp_clks[MSTP_NR] = {
445 471
446#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } 472#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
447#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } 473#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
474#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
448 475
449static struct clk_lookup lookups[] = { 476static struct clk_lookup lookups[] = {
450 /* main clocks */ 477 /* main clocks */
451 CLKDEV_CON_ID("dv_clki_div2_clk", &dv_clki_div2_clk), 478 CLKDEV_CON_ID("dv_clki_div2_clk", &sh7372_dv_clki_div2_clk),
452 CLKDEV_CON_ID("r_clk", &r_clk), 479 CLKDEV_CON_ID("r_clk", &r_clk),
453 CLKDEV_CON_ID("extal1", &sh7372_extal1_clk), 480 CLKDEV_CON_ID("extal1", &sh7372_extal1_clk),
454 CLKDEV_CON_ID("extal2", &sh7372_extal2_clk), 481 CLKDEV_CON_ID("extal2", &sh7372_extal2_clk),
@@ -458,7 +485,7 @@ static struct clk_lookup lookups[] = {
458 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), 485 CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
459 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), 486 CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
460 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), 487 CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
461 CLKDEV_CON_ID("pllc2_clk", &pllc2_clk), 488 CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
462 489
463 /* DIV4 clocks */ 490 /* DIV4 clocks */
464 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), 491 CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -483,8 +510,8 @@ static struct clk_lookup lookups[] = {
483 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), 510 CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
484 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), 511 CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
485 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), 512 CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
486 CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FSIA]), 513 CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FSIA]),
487 CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FSIB]), 514 CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FSIB]),
488 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), 515 CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
489 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), 516 CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
490 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), 517 CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
@@ -501,6 +528,8 @@ static struct clk_lookup lookups[] = {
501 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */ 528 CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
502 CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */ 529 CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */
503 CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */ 530 CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */
531 CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
532 CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
504 CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ 533 CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
505 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ 534 CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
506 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ 535 CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
@@ -516,7 +545,7 @@ static struct clk_lookup lookups[] = {
516 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ 545 CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
517 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ 546 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
518 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ 547 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
519 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ 548 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
520 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ 549 CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
521 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ 550 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
522 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */ 551 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */
@@ -531,7 +560,10 @@ static struct clk_lookup lookups[] = {
531 CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ 560 CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
532 CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ 561 CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
533 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ 562 CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
534 {.con_id = "ick", .dev_id = "sh-mobile-hdmi", .clk = &div6_reparent_clks[DIV6_HDMI]}, 563
564 CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
565 CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
566 CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
535}; 567};
536 568
537void __init sh7372_clock_init(void) 569void __init sh7372_clock_init(void)
@@ -548,7 +580,7 @@ void __init sh7372_clock_init(void)
548 ret = sh_clk_div6_register(div6_clks, DIV6_NR); 580 ret = sh_clk_div6_register(div6_clks, DIV6_NR);
549 581
550 if (!ret) 582 if (!ret)
551 ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_NR); 583 ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
552 584
553 if (!ret) 585 if (!ret)
554 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); 586 ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
index e007c28cf0a8..f91395aeb9ab 100644
--- a/arch/arm/mach-shmobile/clock-sh7377.c
+++ b/arch/arm/mach-shmobile/clock-sh7377.c
@@ -333,7 +333,7 @@ static struct clk_lookup lookups[] = {
333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ 333 CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ 334 CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ 335 CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
336 CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ 336 CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
337 CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */ 337 CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */
338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ 338 CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */ 339 CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 33e9700ded7e..147775a94bce 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -457,8 +457,12 @@ enum {
457 SHDMA_SLAVE_SDHI2_TX, 457 SHDMA_SLAVE_SDHI2_TX,
458}; 458};
459 459
460extern struct clk dv_clki_clk; 460extern struct clk sh7372_extal1_clk;
461extern struct clk dv_clki_div2_clk; 461extern struct clk sh7372_extal2_clk;
462extern struct clk pllc2_clk; 462extern struct clk sh7372_dv_clki_clk;
463extern struct clk sh7372_dv_clki_div2_clk;
464extern struct clk sh7372_pllc2_clk;
465extern struct clk sh7372_fsiack_clk;
466extern struct clk sh7372_fsibck_clk;
463 467
464#endif /* __ASM_SH7372_H__ */ 468#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index e3551b56cd03..4cd3cae38e72 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -369,9 +369,13 @@ enum {
369 INTCS, 369 INTCS,
370 370
371 /* interrupt sources INTCS */ 371 /* interrupt sources INTCS */
372
373 /* IRQ0S - IRQ31S */
372 VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3, 374 VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3,
373 RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3, 375 RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3,
374 CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2, 376 CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2,
377 /* MFI */
378 /* BBIF2 */
375 VPU, 379 VPU,
376 TSIF1, 380 TSIF1,
377 _3DG_SGX530, 381 _3DG_SGX530,
@@ -379,13 +383,17 @@ enum {
379 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2, 383 IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
380 IPMMU_IPMMUR, IPMMU_IPMMUR2, 384 IPMMU_IPMMUR, IPMMU_IPMMUR2,
381 RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR, 385 RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR,
386 /* KEYSC */
387 /* TTI20 */
382 MSIOF, 388 MSIOF,
383 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0, 389 IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
384 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2, 390 TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
385 CMT0, 391 CMT0,
386 TSIF0, 392 TSIF0,
393 /* CMT2 */
387 LMB, 394 LMB,
388 CTI, 395 CTI,
396 /* RWDT0 */
389 ICB, 397 ICB,
390 JPU_JPEG, 398 JPU_JPEG,
391 LCDC, 399 LCDC,
@@ -397,11 +405,17 @@ enum {
397 CSIRX, 405 CSIRX,
398 DSITX_DSITX0, 406 DSITX_DSITX0,
399 DSITX_DSITX1, 407 DSITX_DSITX1,
408 /* SPU2 */
409 /* FSI */
410 /* FMSI */
411 /* HDMI */
400 TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2, 412 TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
401 CMT4, 413 CMT4,
402 DSITX1_DSITX1_0, 414 DSITX1_DSITX1_0,
403 DSITX1_DSITX1_1, 415 DSITX1_DSITX1_1,
416 /* MFIS2 */
404 CPORTS2R, 417 CPORTS2R,
418 /* CEC */
405 JPU6E, 419 JPU6E,
406 420
407 /* interrupt groups INTCS */ 421 /* interrupt groups INTCS */
@@ -410,12 +424,15 @@ enum {
410}; 424};
411 425
412static struct intc_vect intcs_vectors[] = { 426static struct intc_vect intcs_vectors[] = {
427 /* IRQ0S - IRQ31S */
413 INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720), 428 INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720),
414 INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760), 429 INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760),
415 INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820), 430 INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820),
416 INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860), 431 INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860),
417 INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0), 432 INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0),
418 INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0), 433 INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0),
434 /* MFI */
435 /* BBIF2 */
419 INTCS_VECT(VPU, 0x980), 436 INTCS_VECT(VPU, 0x980),
420 INTCS_VECT(TSIF1, 0x9a0), 437 INTCS_VECT(TSIF1, 0x9a0),
421 INTCS_VECT(_3DG_SGX530, 0x9e0), 438 INTCS_VECT(_3DG_SGX530, 0x9e0),
@@ -425,14 +442,19 @@ static struct intc_vect intcs_vectors[] = {
425 INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20), 442 INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20),
426 INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0), 443 INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0),
427 INTCS_VECT(RTDMAC_2_DADERR, 0xbc0), 444 INTCS_VECT(RTDMAC_2_DADERR, 0xbc0),
445 /* KEYSC */
446 /* TTI20 */
447 INTCS_VECT(MSIOF, 0x0d20),
428 INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20), 448 INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20),
429 INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60), 449 INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60),
430 INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0), 450 INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0),
431 INTCS_VECT(TMU_TUNI2, 0xec0), 451 INTCS_VECT(TMU_TUNI2, 0xec0),
432 INTCS_VECT(CMT0, 0xf00), 452 INTCS_VECT(CMT0, 0xf00),
433 INTCS_VECT(TSIF0, 0xf20), 453 INTCS_VECT(TSIF0, 0xf20),
454 /* CMT2 */
434 INTCS_VECT(LMB, 0xf60), 455 INTCS_VECT(LMB, 0xf60),
435 INTCS_VECT(CTI, 0x400), 456 INTCS_VECT(CTI, 0x400),
457 /* RWDT0 */
436 INTCS_VECT(ICB, 0x480), 458 INTCS_VECT(ICB, 0x480),
437 INTCS_VECT(JPU_JPEG, 0x560), 459 INTCS_VECT(JPU_JPEG, 0x560),
438 INTCS_VECT(LCDC, 0x580), 460 INTCS_VECT(LCDC, 0x580),
@@ -446,12 +468,18 @@ static struct intc_vect intcs_vectors[] = {
446 INTCS_VECT(CSIRX, 0x17a0), 468 INTCS_VECT(CSIRX, 0x17a0),
447 INTCS_VECT(DSITX_DSITX0, 0x17c0), 469 INTCS_VECT(DSITX_DSITX0, 0x17c0),
448 INTCS_VECT(DSITX_DSITX1, 0x17e0), 470 INTCS_VECT(DSITX_DSITX1, 0x17e0),
471 /* SPU2 */
472 /* FSI */
473 /* FMSI */
474 /* HDMI */
449 INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920), 475 INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920),
450 INTCS_VECT(TMU1_TUNI2, 0x1940), 476 INTCS_VECT(TMU1_TUNI2, 0x1940),
451 INTCS_VECT(CMT4, 0x1980), 477 INTCS_VECT(CMT4, 0x1980),
452 INTCS_VECT(DSITX1_DSITX1_0, 0x19a0), 478 INTCS_VECT(DSITX1_DSITX1_0, 0x19a0),
453 INTCS_VECT(DSITX1_DSITX1_1, 0x19c0), 479 INTCS_VECT(DSITX1_DSITX1_1, 0x19c0),
480 /* MFIS2 */
454 INTCS_VECT(CPORTS2R, 0x1a20), 481 INTCS_VECT(CPORTS2R, 0x1a20),
482 /* CEC */
455 INTCS_VECT(JPU6E, 0x1a80), 483 INTCS_VECT(JPU6E, 0x1a80),
456 484
457 INTC_VECT(INTCS, 0xf80), 485 INTC_VECT(INTCS, 0xf80),
diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c
index ec420353f8e3..9c265dae138a 100644
--- a/arch/arm/mach-shmobile/pfc-sh7372.c
+++ b/arch/arm/mach-shmobile/pfc-sh7372.c
@@ -166,12 +166,12 @@ enum {
166 MSIOF2_TSYNC_MARK, MSIOF2_TSCK_MARK, MSIOF2_RXD_MARK, 166 MSIOF2_TSYNC_MARK, MSIOF2_TSCK_MARK, MSIOF2_RXD_MARK,
167 MSIOF2_TXD_MARK, 167 MSIOF2_TXD_MARK,
168 168
169 /* MSIOF3 */ 169 /* BBIF1 */
170 BBIF1_RXD_MARK, BBIF1_TSYNC_MARK, BBIF1_TSCK_MARK, 170 BBIF1_RXD_MARK, BBIF1_TSYNC_MARK, BBIF1_TSCK_MARK,
171 BBIF1_TXD_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK, 171 BBIF1_TXD_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK,
172 BBIF1_FLOW_MARK, BB_RX_FLOW_N_MARK, 172 BBIF1_FLOW_MARK, BB_RX_FLOW_N_MARK,
173 173
174 /* MSIOF4 */ 174 /* BBIF2 */
175 BBIF2_TSCK1_MARK, BBIF2_TSYNC1_MARK, 175 BBIF2_TSCK1_MARK, BBIF2_TSYNC1_MARK,
176 BBIF2_TXD1_MARK, BBIF2_RXD_MARK, 176 BBIF2_TXD1_MARK, BBIF2_RXD_MARK,
177 177
@@ -976,12 +976,12 @@ static struct pinmux_gpio pinmux_gpios[] = {
976 GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_TSCK), GPIO_FN(MSIOF2_RXD), 976 GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_TSCK), GPIO_FN(MSIOF2_RXD),
977 GPIO_FN(MSIOF2_TXD), 977 GPIO_FN(MSIOF2_TXD),
978 978
979 /* MSIOF3 */ 979 /* BBIF1 */
980 GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TSYNC), GPIO_FN(BBIF1_TSCK), 980 GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TSYNC), GPIO_FN(BBIF1_TSCK),
981 GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC), 981 GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC),
982 GPIO_FN(BBIF1_FLOW), GPIO_FN(BB_RX_FLOW_N), 982 GPIO_FN(BBIF1_FLOW), GPIO_FN(BB_RX_FLOW_N),
983 983
984 /* MSIOF4 */ 984 /* BBIF2 */
985 GPIO_FN(BBIF2_TSCK1), GPIO_FN(BBIF2_TSYNC1), 985 GPIO_FN(BBIF2_TSCK1), GPIO_FN(BBIF2_TSYNC1),
986 GPIO_FN(BBIF2_TXD1), GPIO_FN(BBIF2_RXD), 986 GPIO_FN(BBIF2_TXD1), GPIO_FN(BBIF2_RXD),
987 987
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c
index 3148c11a550e..003008c18360 100644
--- a/arch/arm/mach-shmobile/setup-sh7367.c
+++ b/arch/arm/mach-shmobile/setup-sh7367.c
@@ -154,7 +154,6 @@ static struct sh_timer_config cmt10_platform_data = {
154 .name = "CMT10", 154 .name = "CMT10",
155 .channel_offset = 0x10, 155 .channel_offset = 0x10,
156 .timer_bit = 0, 156 .timer_bit = 0,
157 .clk = "r_clk",
158 .clockevent_rating = 125, 157 .clockevent_rating = 125,
159 .clocksource_rating = 125, 158 .clocksource_rating = 125,
160}; 159};
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index e26686c9d0b6..564a6d0be473 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -158,7 +158,6 @@ static struct sh_timer_config cmt10_platform_data = {
158 .name = "CMT10", 158 .name = "CMT10",
159 .channel_offset = 0x10, 159 .channel_offset = 0x10,
160 .timer_bit = 0, 160 .timer_bit = 0,
161 .clk = "cmt1",
162 .clockevent_rating = 125, 161 .clockevent_rating = 125,
163 .clocksource_rating = 125, 162 .clocksource_rating = 125,
164}; 163};
@@ -186,6 +185,67 @@ static struct platform_device cmt10_device = {
186 .num_resources = ARRAY_SIZE(cmt10_resources), 185 .num_resources = ARRAY_SIZE(cmt10_resources),
187}; 186};
188 187
188/* TMU */
189static struct sh_timer_config tmu00_platform_data = {
190 .name = "TMU00",
191 .channel_offset = 0x4,
192 .timer_bit = 0,
193 .clockevent_rating = 200,
194};
195
196static struct resource tmu00_resources[] = {
197 [0] = {
198 .name = "TMU00",
199 .start = 0xfff60008,
200 .end = 0xfff60013,
201 .flags = IORESOURCE_MEM,
202 },
203 [1] = {
204 .start = intcs_evt2irq(0xe80), /* TMU_TUNI0 */
205 .flags = IORESOURCE_IRQ,
206 },
207};
208
209static struct platform_device tmu00_device = {
210 .name = "sh_tmu",
211 .id = 0,
212 .dev = {
213 .platform_data = &tmu00_platform_data,
214 },
215 .resource = tmu00_resources,
216 .num_resources = ARRAY_SIZE(tmu00_resources),
217};
218
219static struct sh_timer_config tmu01_platform_data = {
220 .name = "TMU01",
221 .channel_offset = 0x10,
222 .timer_bit = 1,
223 .clocksource_rating = 200,
224};
225
226static struct resource tmu01_resources[] = {
227 [0] = {
228 .name = "TMU01",
229 .start = 0xfff60014,
230 .end = 0xfff6001f,
231 .flags = IORESOURCE_MEM,
232 },
233 [1] = {
234 .start = intcs_evt2irq(0xea0), /* TMU_TUNI1 */
235 .flags = IORESOURCE_IRQ,
236 },
237};
238
239static struct platform_device tmu01_device = {
240 .name = "sh_tmu",
241 .id = 1,
242 .dev = {
243 .platform_data = &tmu01_platform_data,
244 },
245 .resource = tmu01_resources,
246 .num_resources = ARRAY_SIZE(tmu01_resources),
247};
248
189/* I2C */ 249/* I2C */
190static struct resource iic0_resources[] = { 250static struct resource iic0_resources[] = {
191 [0] = { 251 [0] = {
@@ -419,14 +479,14 @@ static struct resource sh7372_dmae0_resources[] = {
419 }, 479 },
420 { 480 {
421 /* DMA error IRQ */ 481 /* DMA error IRQ */
422 .start = 246, 482 .start = evt2irq(0x20c0),
423 .end = 246, 483 .end = evt2irq(0x20c0),
424 .flags = IORESOURCE_IRQ, 484 .flags = IORESOURCE_IRQ,
425 }, 485 },
426 { 486 {
427 /* IRQ for channels 0-5 */ 487 /* IRQ for channels 0-5 */
428 .start = 240, 488 .start = evt2irq(0x2000),
429 .end = 245, 489 .end = evt2irq(0x20a0),
430 .flags = IORESOURCE_IRQ, 490 .flags = IORESOURCE_IRQ,
431 }, 491 },
432}; 492};
@@ -447,14 +507,14 @@ static struct resource sh7372_dmae1_resources[] = {
447 }, 507 },
448 { 508 {
449 /* DMA error IRQ */ 509 /* DMA error IRQ */
450 .start = 254, 510 .start = evt2irq(0x21c0),
451 .end = 254, 511 .end = evt2irq(0x21c0),
452 .flags = IORESOURCE_IRQ, 512 .flags = IORESOURCE_IRQ,
453 }, 513 },
454 { 514 {
455 /* IRQ for channels 0-5 */ 515 /* IRQ for channels 0-5 */
456 .start = 248, 516 .start = evt2irq(0x2100),
457 .end = 253, 517 .end = evt2irq(0x21a0),
458 .flags = IORESOURCE_IRQ, 518 .flags = IORESOURCE_IRQ,
459 }, 519 },
460}; 520};
@@ -475,14 +535,14 @@ static struct resource sh7372_dmae2_resources[] = {
475 }, 535 },
476 { 536 {
477 /* DMA error IRQ */ 537 /* DMA error IRQ */
478 .start = 262, 538 .start = evt2irq(0x22c0),
479 .end = 262, 539 .end = evt2irq(0x22c0),
480 .flags = IORESOURCE_IRQ, 540 .flags = IORESOURCE_IRQ,
481 }, 541 },
482 { 542 {
483 /* IRQ for channels 0-5 */ 543 /* IRQ for channels 0-5 */
484 .start = 256, 544 .start = evt2irq(0x2200),
485 .end = 261, 545 .end = evt2irq(0x22a0),
486 .flags = IORESOURCE_IRQ, 546 .flags = IORESOURCE_IRQ,
487 }, 547 },
488}; 548};
@@ -526,6 +586,11 @@ static struct platform_device *sh7372_early_devices[] __initdata = {
526 &scif5_device, 586 &scif5_device,
527 &scif6_device, 587 &scif6_device,
528 &cmt10_device, 588 &cmt10_device,
589 &tmu00_device,
590 &tmu01_device,
591};
592
593static struct platform_device *sh7372_late_devices[] __initdata = {
529 &iic0_device, 594 &iic0_device,
530 &iic1_device, 595 &iic1_device,
531 &dma0_device, 596 &dma0_device,
@@ -537,6 +602,9 @@ void __init sh7372_add_standard_devices(void)
537{ 602{
538 platform_add_devices(sh7372_early_devices, 603 platform_add_devices(sh7372_early_devices,
539 ARRAY_SIZE(sh7372_early_devices)); 604 ARRAY_SIZE(sh7372_early_devices));
605
606 platform_add_devices(sh7372_late_devices,
607 ARRAY_SIZE(sh7372_late_devices));
540} 608}
541 609
542void __init sh7372_add_early_devices(void) 610void __init sh7372_add_early_devices(void)
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c
index bb4adf17dbf4..575dbd6c2f1d 100644
--- a/arch/arm/mach-shmobile/setup-sh7377.c
+++ b/arch/arm/mach-shmobile/setup-sh7377.c
@@ -172,7 +172,6 @@ static struct sh_timer_config cmt10_platform_data = {
172 .name = "CMT10", 172 .name = "CMT10",
173 .channel_offset = 0x10, 173 .channel_offset = 0x10,
174 .timer_bit = 0, 174 .timer_bit = 0,
175 .clk = "r_clk",
176 .clockevent_rating = 125, 175 .clockevent_rating = 125,
177 .clocksource_rating = 125, 176 .clocksource_rating = 125,
178}; 177};
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 3da116f47f01..00553233a7c5 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -176,6 +176,21 @@ static void ap320_wvga_power_off(void *board_data)
176 __raw_writew(0, FPGA_LCDREG); 176 __raw_writew(0, FPGA_LCDREG);
177} 177}
178 178
179const static struct fb_videomode ap325rxa_lcdc_modes[] = {
180 {
181 .name = "LB070WV1",
182 .xres = 800,
183 .yres = 480,
184 .left_margin = 32,
185 .right_margin = 160,
186 .hsync_len = 8,
187 .upper_margin = 63,
188 .lower_margin = 80,
189 .vsync_len = 1,
190 .sync = 0, /* hsync and vsync are active low */
191 },
192};
193
179static struct sh_mobile_lcdc_info lcdc_info = { 194static struct sh_mobile_lcdc_info lcdc_info = {
180 .clock_source = LCDC_CLK_EXTERNAL, 195 .clock_source = LCDC_CLK_EXTERNAL,
181 .ch[0] = { 196 .ch[0] = {
@@ -183,18 +198,8 @@ static struct sh_mobile_lcdc_info lcdc_info = {
183 .bpp = 16, 198 .bpp = 16,
184 .interface_type = RGB18, 199 .interface_type = RGB18,
185 .clock_divider = 1, 200 .clock_divider = 1,
186 .lcd_cfg = { 201 .lcd_cfg = ap325rxa_lcdc_modes,
187 .name = "LB070WV1", 202 .num_cfg = ARRAY_SIZE(ap325rxa_lcdc_modes),
188 .xres = 800,
189 .yres = 480,
190 .left_margin = 32,
191 .right_margin = 160,
192 .hsync_len = 8,
193 .upper_margin = 63,
194 .lower_margin = 80,
195 .vsync_len = 1,
196 .sync = 0, /* hsync and vsync are active low */
197 },
198 .lcd_size_cfg = { /* 7.0 inch */ 203 .lcd_size_cfg = { /* 7.0 inch */
199 .width = 152, 204 .width = 152,
200 .height = 91, 205 .height = 91,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 71a3368ab1fc..0161deb770cc 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -231,14 +231,41 @@ static struct platform_device usb1_common_device = {
231}; 231};
232 232
233/* LCDC */ 233/* LCDC */
234const static struct fb_videomode ecovec_lcd_modes[] = {
235 {
236 .name = "Panel",
237 .xres = 800,
238 .yres = 480,
239 .left_margin = 220,
240 .right_margin = 110,
241 .hsync_len = 70,
242 .upper_margin = 20,
243 .lower_margin = 5,
244 .vsync_len = 5,
245 .sync = 0, /* hsync and vsync are active low */
246 },
247};
248
249const static struct fb_videomode ecovec_dvi_modes[] = {
250 {
251 .name = "DVI",
252 .xres = 1280,
253 .yres = 720,
254 .left_margin = 220,
255 .right_margin = 110,
256 .hsync_len = 40,
257 .upper_margin = 20,
258 .lower_margin = 5,
259 .vsync_len = 5,
260 .sync = 0, /* hsync and vsync are active low */
261 },
262};
263
234static struct sh_mobile_lcdc_info lcdc_info = { 264static struct sh_mobile_lcdc_info lcdc_info = {
235 .ch[0] = { 265 .ch[0] = {
236 .interface_type = RGB18, 266 .interface_type = RGB18,
237 .chan = LCDC_CHAN_MAINLCD, 267 .chan = LCDC_CHAN_MAINLCD,
238 .bpp = 16, 268 .bpp = 16,
239 .lcd_cfg = {
240 .sync = 0, /* hsync and vsync are active low */
241 },
242 .lcd_size_cfg = { /* 7.0 inch */ 269 .lcd_size_cfg = { /* 7.0 inch */
243 .width = 152, 270 .width = 152,
244 .height = 91, 271 .height = 91,
@@ -1079,33 +1106,18 @@ static int __init arch_setup(void)
1079 if (gpio_get_value(GPIO_PTE6)) { 1106 if (gpio_get_value(GPIO_PTE6)) {
1080 /* DVI */ 1107 /* DVI */
1081 lcdc_info.clock_source = LCDC_CLK_EXTERNAL; 1108 lcdc_info.clock_source = LCDC_CLK_EXTERNAL;
1082 lcdc_info.ch[0].clock_divider = 1, 1109 lcdc_info.ch[0].clock_divider = 1;
1083 lcdc_info.ch[0].lcd_cfg.name = "DVI"; 1110 lcdc_info.ch[0].lcd_cfg = ecovec_dvi_modes;
1084 lcdc_info.ch[0].lcd_cfg.xres = 1280; 1111 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_dvi_modes);
1085 lcdc_info.ch[0].lcd_cfg.yres = 720;
1086 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1087 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1088 lcdc_info.ch[0].lcd_cfg.hsync_len = 40;
1089 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1090 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1091 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1092 1112
1093 gpio_set_value(GPIO_PTA2, 1); 1113 gpio_set_value(GPIO_PTA2, 1);
1094 gpio_set_value(GPIO_PTU1, 1); 1114 gpio_set_value(GPIO_PTU1, 1);
1095 } else { 1115 } else {
1096 /* Panel */ 1116 /* Panel */
1097
1098 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; 1117 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL;
1099 lcdc_info.ch[0].clock_divider = 2, 1118 lcdc_info.ch[0].clock_divider = 2;
1100 lcdc_info.ch[0].lcd_cfg.name = "Panel"; 1119 lcdc_info.ch[0].lcd_cfg = ecovec_lcd_modes;
1101 lcdc_info.ch[0].lcd_cfg.xres = 800; 1120 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_lcd_modes);
1102 lcdc_info.ch[0].lcd_cfg.yres = 480;
1103 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
1104 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
1105 lcdc_info.ch[0].lcd_cfg.hsync_len = 70;
1106 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
1107 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
1108 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
1109 1121
1110 gpio_set_value(GPIO_PTR1, 1); 1122 gpio_set_value(GPIO_PTR1, 1);
1111 1123
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 68994a163f6c..87d4b90e368c 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -126,6 +126,21 @@ static struct platform_device kfr2r09_sh_keysc_device = {
126 }, 126 },
127}; 127};
128 128
129const static struct fb_videomode kfr2r09_lcdc_modes[] = {
130 {
131 .name = "TX07D34VM0AAA",
132 .xres = 240,
133 .yres = 400,
134 .left_margin = 0,
135 .right_margin = 16,
136 .hsync_len = 8,
137 .upper_margin = 0,
138 .lower_margin = 1,
139 .vsync_len = 1,
140 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
141 },
142};
143
129static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = { 144static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
130 .clock_source = LCDC_CLK_BUS, 145 .clock_source = LCDC_CLK_BUS,
131 .ch[0] = { 146 .ch[0] = {
@@ -134,18 +149,8 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
134 .interface_type = SYS18, 149 .interface_type = SYS18,
135 .clock_divider = 6, 150 .clock_divider = 6,
136 .flags = LCDC_FLAGS_DWPOL, 151 .flags = LCDC_FLAGS_DWPOL,
137 .lcd_cfg = { 152 .lcd_cfg = kfr2r09_lcdc_modes,
138 .name = "TX07D34VM0AAA", 153 .num_cfg = ARRAY_SIZE(kfr2r09_lcdc_modes),
139 .xres = 240,
140 .yres = 400,
141 .left_margin = 0,
142 .right_margin = 16,
143 .hsync_len = 8,
144 .upper_margin = 0,
145 .lower_margin = 1,
146 .vsync_len = 1,
147 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
148 },
149 .lcd_size_cfg = { 154 .lcd_size_cfg = {
150 .width = 35, 155 .width = 35,
151 .height = 58, 156 .height = 58,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 662debe4ead2..9204cbb87147 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -213,51 +213,55 @@ static struct platform_device migor_nand_flash_device = {
213 } 213 }
214}; 214};
215 215
216const static struct fb_videomode migor_lcd_modes[] = {
217 {
218#if defined(CONFIG_SH_MIGOR_RTA_WVGA)
219 .name = "LB070WV1",
220 .xres = 800,
221 .yres = 480,
222 .left_margin = 64,
223 .right_margin = 16,
224 .hsync_len = 120,
225 .sync = 0,
226#elif defined(CONFIG_SH_MIGOR_QVGA)
227 .name = "PH240320T",
228 .xres = 320,
229 .yres = 240,
230 .left_margin = 0,
231 .right_margin = 16,
232 .hsync_len = 8,
233 .sync = FB_SYNC_HOR_HIGH_ACT,
234#endif
235 .upper_margin = 1,
236 .lower_margin = 17,
237 .vsync_len = 2,
238 },
239};
240
216static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { 241static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
217#ifdef CONFIG_SH_MIGOR_RTA_WVGA 242#if defined(CONFIG_SH_MIGOR_RTA_WVGA)
218 .clock_source = LCDC_CLK_BUS, 243 .clock_source = LCDC_CLK_BUS,
219 .ch[0] = { 244 .ch[0] = {
220 .chan = LCDC_CHAN_MAINLCD, 245 .chan = LCDC_CHAN_MAINLCD,
221 .bpp = 16, 246 .bpp = 16,
222 .interface_type = RGB16, 247 .interface_type = RGB16,
223 .clock_divider = 2, 248 .clock_divider = 2,
224 .lcd_cfg = { 249 .lcd_cfg = migor_lcd_modes,
225 .name = "LB070WV1", 250 .num_cfg = ARRAY_SIZE(migor_lcd_modes),
226 .xres = 800,
227 .yres = 480,
228 .left_margin = 64,
229 .right_margin = 16,
230 .hsync_len = 120,
231 .upper_margin = 1,
232 .lower_margin = 17,
233 .vsync_len = 2,
234 .sync = 0,
235 },
236 .lcd_size_cfg = { /* 7.0 inch */ 251 .lcd_size_cfg = { /* 7.0 inch */
237 .width = 152, 252 .width = 152,
238 .height = 91, 253 .height = 91,
239 }, 254 },
240 } 255 }
241#endif 256#elif defined(CONFIG_SH_MIGOR_QVGA)
242#ifdef CONFIG_SH_MIGOR_QVGA
243 .clock_source = LCDC_CLK_PERIPHERAL, 257 .clock_source = LCDC_CLK_PERIPHERAL,
244 .ch[0] = { 258 .ch[0] = {
245 .chan = LCDC_CHAN_MAINLCD, 259 .chan = LCDC_CHAN_MAINLCD,
246 .bpp = 16, 260 .bpp = 16,
247 .interface_type = SYS16A, 261 .interface_type = SYS16A,
248 .clock_divider = 10, 262 .clock_divider = 10,
249 .lcd_cfg = { 263 .lcd_cfg = migor_lcd_modes,
250 .name = "PH240320T", 264 .num_cfg = ARRAY_SIZE(migor_lcd_modes),
251 .xres = 320,
252 .yres = 240,
253 .left_margin = 0,
254 .right_margin = 16,
255 .hsync_len = 8,
256 .upper_margin = 1,
257 .lower_margin = 17,
258 .vsync_len = 2,
259 .sync = FB_SYNC_HOR_HIGH_ACT,
260 },
261 .lcd_size_cfg = { /* 2.4 inch */ 265 .lcd_size_cfg = { /* 2.4 inch */
262 .width = 49, 266 .width = 49,
263 .height = 37, 267 .height = 37,
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 552ebd9ba82b..fe208d6c8ed0 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -144,16 +144,42 @@ static struct platform_device nor_flash_device = {
144}; 144};
145 145
146/* LCDC */ 146/* LCDC */
147const static struct fb_videomode lcdc_720p_modes[] = {
148 {
149 .name = "LB070WV1",
150 .sync = 0, /* hsync and vsync are active low */
151 .xres = 1280,
152 .yres = 720,
153 .left_margin = 220,
154 .right_margin = 110,
155 .hsync_len = 40,
156 .upper_margin = 20,
157 .lower_margin = 5,
158 .vsync_len = 5,
159 },
160};
161
162const static struct fb_videomode lcdc_vga_modes[] = {
163 {
164 .name = "LB070WV1",
165 .sync = 0, /* hsync and vsync are active low */
166 .xres = 640,
167 .yres = 480,
168 .left_margin = 105,
169 .right_margin = 50,
170 .hsync_len = 96,
171 .upper_margin = 33,
172 .lower_margin = 10,
173 .vsync_len = 2,
174 },
175};
176
147static struct sh_mobile_lcdc_info lcdc_info = { 177static struct sh_mobile_lcdc_info lcdc_info = {
148 .clock_source = LCDC_CLK_EXTERNAL, 178 .clock_source = LCDC_CLK_EXTERNAL,
149 .ch[0] = { 179 .ch[0] = {
150 .chan = LCDC_CHAN_MAINLCD, 180 .chan = LCDC_CHAN_MAINLCD,
151 .bpp = 16, 181 .bpp = 16,
152 .clock_divider = 1, 182 .clock_divider = 1,
153 .lcd_cfg = {
154 .name = "LB070WV1",
155 .sync = 0, /* hsync and vsync are active low */
156 },
157 .lcd_size_cfg = { /* 7.0 inch */ 183 .lcd_size_cfg = { /* 7.0 inch */
158 .width = 152, 184 .width = 152,
159 .height = 91, 185 .height = 91,
@@ -909,24 +935,12 @@ static int __init devices_setup(void)
909 935
910 if (sw & SW41_B) { 936 if (sw & SW41_B) {
911 /* 720p */ 937 /* 720p */
912 lcdc_info.ch[0].lcd_cfg.xres = 1280; 938 lcdc_info.ch[0].lcd_cfg = lcdc_720p_modes;
913 lcdc_info.ch[0].lcd_cfg.yres = 720; 939 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_720p_modes);
914 lcdc_info.ch[0].lcd_cfg.left_margin = 220;
915 lcdc_info.ch[0].lcd_cfg.right_margin = 110;
916 lcdc_info.ch[0].lcd_cfg.hsync_len = 40;
917 lcdc_info.ch[0].lcd_cfg.upper_margin = 20;
918 lcdc_info.ch[0].lcd_cfg.lower_margin = 5;
919 lcdc_info.ch[0].lcd_cfg.vsync_len = 5;
920 } else { 940 } else {
921 /* VGA */ 941 /* VGA */
922 lcdc_info.ch[0].lcd_cfg.xres = 640; 942 lcdc_info.ch[0].lcd_cfg = lcdc_vga_modes;
923 lcdc_info.ch[0].lcd_cfg.yres = 480; 943 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_vga_modes);
924 lcdc_info.ch[0].lcd_cfg.left_margin = 105;
925 lcdc_info.ch[0].lcd_cfg.right_margin = 50;
926 lcdc_info.ch[0].lcd_cfg.hsync_len = 96;
927 lcdc_info.ch[0].lcd_cfg.upper_margin = 33;
928 lcdc_info.ch[0].lcd_cfg.lower_margin = 10;
929 lcdc_info.ch[0].lcd_cfg.vsync_len = 2;
930 } 944 }
931 945
932 if (sw & SW41_A) { 946 if (sw & SW41_A) {
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 5699ce0c1780..3f3d431033ca 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -123,83 +123,87 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
123 u32 linelength; 123 u32 linelength;
124 bool yuv; 124 bool yuv;
125 125
126 /* Select data format */ 126 /*
127 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
128 * the default videomode. If this ever becomes a problem, We'll have to
129 * move this to mipi_display_on() above and use info->var.xres
130 */
127 switch (pdata->data_format) { 131 switch (pdata->data_format) {
128 case MIPI_RGB888: 132 case MIPI_RGB888:
129 pctype = 0; 133 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 134 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 135 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3; 136 linelength = ch->lcd_cfg[0].xres * 3;
133 yuv = false; 137 yuv = false;
134 break; 138 break;
135 case MIPI_RGB565: 139 case MIPI_RGB565:
136 pctype = 1; 140 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 141 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 142 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2; 143 linelength = ch->lcd_cfg[0].xres * 2;
140 yuv = false; 144 yuv = false;
141 break; 145 break;
142 case MIPI_RGB666_LP: 146 case MIPI_RGB666_LP:
143 pctype = 2; 147 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 148 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 149 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3; 150 linelength = ch->lcd_cfg[0].xres * 3;
147 yuv = false; 151 yuv = false;
148 break; 152 break;
149 case MIPI_RGB666: 153 case MIPI_RGB666:
150 pctype = 3; 154 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 155 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 156 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 157 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
154 yuv = false; 158 yuv = false;
155 break; 159 break;
156 case MIPI_BGR888: 160 case MIPI_BGR888:
157 pctype = 8; 161 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 162 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 163 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3; 164 linelength = ch->lcd_cfg[0].xres * 3;
161 yuv = false; 165 yuv = false;
162 break; 166 break;
163 case MIPI_BGR565: 167 case MIPI_BGR565:
164 pctype = 9; 168 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 169 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 170 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2; 171 linelength = ch->lcd_cfg[0].xres * 2;
168 yuv = false; 172 yuv = false;
169 break; 173 break;
170 case MIPI_BGR666_LP: 174 case MIPI_BGR666_LP:
171 pctype = 0xa; 175 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 176 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 177 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3; 178 linelength = ch->lcd_cfg[0].xres * 3;
175 yuv = false; 179 yuv = false;
176 break; 180 break;
177 case MIPI_BGR666: 181 case MIPI_BGR666:
178 pctype = 0xb; 182 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 183 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 184 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 185 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
182 yuv = false; 186 yuv = false;
183 break; 187 break;
184 case MIPI_YUYV: 188 case MIPI_YUYV:
185 pctype = 4; 189 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 190 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 191 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2; 192 linelength = ch->lcd_cfg[0].xres * 2;
189 yuv = true; 193 yuv = true;
190 break; 194 break;
191 case MIPI_UYVY: 195 case MIPI_UYVY:
192 pctype = 5; 196 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 197 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 198 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2; 199 linelength = ch->lcd_cfg[0].xres * 2;
196 yuv = true; 200 yuv = true;
197 break; 201 break;
198 case MIPI_YUV420_L: 202 case MIPI_YUV420_L:
199 pctype = 6; 203 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 204 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 205 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; 206 linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8;
203 yuv = true; 207 yuv = true;
204 break; 208 break;
205 case MIPI_YUV420: 209 case MIPI_YUV420:
@@ -207,7 +211,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 211 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 212 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */ 213 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2; 214 linelength = (ch->lcd_cfg[0].xres + 1) / 2;
211 yuv = true; 215 yuv = true;
212 break; 216 break;
213 default: 217 default:
@@ -281,7 +285,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ 285 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
282 /* 286 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 287 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default 288 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0) 289 * (unused, since VMCTR2[HSABM] = 0)
286 */ 290 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ 291 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index ef989d94511c..55b3077ff6ff 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -28,6 +28,8 @@
28#include <video/sh_mobile_hdmi.h> 28#include <video/sh_mobile_hdmi.h>
29#include <video/sh_mobile_lcdc.h> 29#include <video/sh_mobile_lcdc.h>
30 30
31#include "sh_mobile_lcdcfb.h"
32
31#define HDMI_SYSTEM_CTRL 0x00 /* System control */ 33#define HDMI_SYSTEM_CTRL 0x00 /* System control */
32#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, 34#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
33 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ 35 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
@@ -206,12 +208,15 @@ enum hotplug_state {
206 208
207struct sh_hdmi { 209struct sh_hdmi {
208 void __iomem *base; 210 void __iomem *base;
209 enum hotplug_state hp_state; 211 enum hotplug_state hp_state; /* hot-plug status */
212 bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */
210 struct clk *hdmi_clk; 213 struct clk *hdmi_clk;
211 struct device *dev; 214 struct device *dev;
212 struct fb_info *info; 215 struct fb_info *info;
216 struct mutex mutex; /* Protect the info pointer */
213 struct delayed_work edid_work; 217 struct delayed_work edid_work;
214 struct fb_var_screeninfo var; 218 struct fb_var_screeninfo var;
219 struct fb_monspecs monspec;
215}; 220};
216 221
217static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 222static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@ -277,7 +282,7 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
277 */ 282 */
278 283
279/* External video parameter settings */ 284/* External video parameter settings */
280static void hdmi_external_video_param(struct sh_hdmi *hdmi) 285static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
281{ 286{
282 struct fb_var_screeninfo *var = &hdmi->var; 287 struct fb_var_screeninfo *var = &hdmi->var;
283 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 288 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
@@ -309,9 +314,9 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
309 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 314 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
310 sync |= 8; 315 sync |= 8;
311 316
312 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 317 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
313 htotal, hblank, hdelay, var->hsync_len, 318 htotal, hblank, hdelay, var->hsync_len,
314 vtotal, vblank, vdelay, var->vsync_len, sync); 319 vtotal, vblank, vdelay, var->vsync_len, sync);
315 320
316 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 321 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
317 322
@@ -336,7 +341,10 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
336 341
337 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 342 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
338 343
339 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ 344 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
345 if (!hdmi->preprogrammed_mode)
346 hdmi_write(hdmi, sync | 1 | (voffset << 4),
347 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
340} 348}
341 349
342/** 350/**
@@ -454,21 +462,61 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
454} 462}
455 463
456/** 464/**
457 * sh_hdmi_phy_config() 465 * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
458 */ 466 */
459static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 467static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
460{ 468{
461 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 469 if (hdmi->var.yres > 480) {
462 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 470 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
463 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 471 /*
464 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); 472 * [1:0] Speed_A
465 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ 473 * [3:2] Speed_B
466 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); 474 * [4] PLLA_Bypass
467 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); 475 * [6] DRV_TEST_EN
468 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); 476 * [7] DRV_TEST_IN
469 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 477 */
470 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 478 hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
471 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 479 /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
480 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
481 /*
482 * [2:0] BGR_I_OFFSET
483 * [6:4] BGR_V_OFFSET
484 */
485 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
486 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
487 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
488 /*
489 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
490 * LPF capacitance, LPF resistance[1]
491 */
492 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
493 /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
494 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
495 /*
496 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
497 * LPF capacitance, LPF resistance[1]
498 */
499 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
500 /* DRV_CONFIG, PE_CONFIG */
501 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
502 /*
503 * [2:0] AMON_SEL (4 == LPF voltage)
504 * [4] PLLA_CONFIG[16]
505 * [5] PLLB_CONFIG[16]
506 */
507 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
508 } else {
509 /* for 480p8bit 27MHz */
510 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
511 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
512 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
513 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
514 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
515 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
516 hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
517 hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
518 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
519 }
472} 520}
473 521
474/** 522/**
@@ -476,6 +524,8 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
476 */ 524 */
477static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) 525static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
478{ 526{
527 u8 vic;
528
479 /* AVI InfoFrame */ 529 /* AVI InfoFrame */
480 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); 530 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
481 531
@@ -500,9 +550,9 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
500 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); 550 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
501 551
502 /* 552 /*
503 * C = No Data 553 * [7:6] C = Colorimetry: no data
504 * M = 16:9 Picture Aspect Ratio 554 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
505 * R = Same as picture aspect ratio 555 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
506 */ 556 */
507 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); 557 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
508 558
@@ -516,9 +566,15 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
516 566
517 /* 567 /*
518 * VIC = 1280 x 720p: ignored if external config is used 568 * VIC = 1280 x 720p: ignored if external config is used
519 * Send 2 for 720 x 480p, 16 for 1080p 569 * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode
520 */ 570 */
521 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); 571 if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920)
572 vic = 16;
573 else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
574 vic = 2;
575 else
576 vic = 4;
577 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
522 578
523 /* PR = No Repetition */ 579 /* PR = No Repetition */
524 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); 580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
@@ -592,100 +648,6 @@ static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
592} 648}
593 649
594/** 650/**
595 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
596 */
597static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
598{
599 int i;
600
601 /* Gamut Metadata Packet */
602 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
603
604 /* Packet Type = 0x0A */
605 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
606 /* Gamut Packet is not used, so default value */
607 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
608 /* Gamut Packet is not used, so default value */
609 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
610
611 /* GBD bytes 0 through 27 */
612 for (i = 0; i <= 27; i++)
613 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
614 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
615}
616
617/**
618 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
619 */
620static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
621{
622 int i;
623
624 /* Audio Content Protection Packet (ACP) */
625 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
626
627 /* Packet Type = 0x04 */
628 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
629 /* ACP_Type */
630 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
631 /* Reserved (0) */
632 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
633
634 /* GBD bytes 0 through 27 */
635 for (i = 0; i <= 27; i++)
636 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
637 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
638}
639
640/**
641 * sh_hdmi_isrc1_setup() - ISRC1 Packet
642 */
643static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
644{
645 int i;
646
647 /* ISRC1 Packet */
648 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
649
650 /* Packet Type = 0x05 */
651 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
652 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
653 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
654 /* Reserved (0) */
655 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
656
657 /* PB0 UPC_EAN_ISRC_0-15 */
658 /* Bytes PB16-PB27 shall be set to a value of 0. */
659 for (i = 0; i <= 27; i++)
660 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
661 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
662}
663
664/**
665 * sh_hdmi_isrc2_setup() - ISRC2 Packet
666 */
667static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
668{
669 int i;
670
671 /* ISRC2 Packet */
672 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
673
674 /* HB0 Packet Type = 0x06 */
675 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
676 /* Reserved (0) */
677 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
678 /* Reserved (0) */
679 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
680
681 /* PB0 UPC_EAN_ISRC_16-31 */
682 /* Bytes PB16-PB27 shall be set to a value of 0. */
683 for (i = 0; i <= 27; i++)
684 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
685 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
686}
687
688/**
689 * sh_hdmi_configure() - Initialise HDMI for output 651 * sh_hdmi_configure() - Initialise HDMI for output
690 */ 652 */
691static void sh_hdmi_configure(struct sh_hdmi *hdmi) 653static void sh_hdmi_configure(struct sh_hdmi *hdmi)
@@ -705,18 +667,6 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
705 /* Audio InfoFrame */ 667 /* Audio InfoFrame */
706 sh_hdmi_audio_infoframe_setup(hdmi); 668 sh_hdmi_audio_infoframe_setup(hdmi);
707 669
708 /* Gamut Metadata packet */
709 sh_hdmi_gamut_metadata_setup(hdmi);
710
711 /* Audio Content Protection (ACP) Packet */
712 sh_hdmi_acp_setup(hdmi);
713
714 /* ISRC1 Packet */
715 sh_hdmi_isrc1_setup(hdmi);
716
717 /* ISRC2 Packet */
718 sh_hdmi_isrc2_setup(hdmi);
719
720 /* 670 /*
721 * Control packet auto send with VSYNC control: auto send 671 * Control packet auto send with VSYNC control: auto send
722 * General control, Gamut metadata, ISRC, and ACP packets 672 * General control, Gamut metadata, ISRC, and ACP packets
@@ -734,17 +684,42 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
734 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); 684 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
735} 685}
736 686
737static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) 687static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
688 const struct fb_videomode *mode)
738{ 689{
739 struct fb_var_screeninfo *var = &hdmi->var; 690 long target = PICOS2KHZ(mode->pixclock) * 1000,
740 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 691 rate = clk_round_rate(hdmi->hdmi_clk, target);
741 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; 692 unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
742 unsigned long height = var->height, width = var->width; 693
743 int i; 694 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
695 mode->left_margin, mode->xres,
696 mode->right_margin, mode->hsync_len,
697 mode->upper_margin, mode->yres,
698 mode->lower_margin, mode->vsync_len);
699
700 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
701 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
702 mode->refresh);
703
704 return rate_error;
705}
706
707static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
708{
709 struct fb_var_screeninfo tmpvar;
710 struct fb_var_screeninfo *var = &tmpvar;
711 const struct fb_videomode *mode, *found = NULL;
712 struct fb_info *info = hdmi->info;
713 struct fb_modelist *modelist = NULL;
714 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
715 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
716 bool exact_match = false;
744 u8 edid[128]; 717 u8 edid[128];
718 char *forced;
719 int i;
745 720
746 /* Read EDID */ 721 /* Read EDID */
747 pr_debug("Read back EDID code:"); 722 dev_dbg(hdmi->dev, "Read back EDID code:");
748 for (i = 0; i < 128; i++) { 723 for (i = 0; i < 128; i++) {
749 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); 724 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
750#ifdef DEBUG 725#ifdef DEBUG
@@ -759,29 +734,97 @@ static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
759#ifdef DEBUG 734#ifdef DEBUG
760 printk(KERN_CONT "\n"); 735 printk(KERN_CONT "\n");
761#endif 736#endif
762 fb_parse_edid(edid, var); 737
763 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", 738 fb_edid_to_monspecs(edid, &hdmi->monspec);
764 var->left_margin, var->xres, var->right_margin, var->hsync_len, 739
765 var->upper_margin, var->yres, var->lower_margin, var->vsync_len, 740 fb_get_options("sh_mobile_lcdc", &forced);
766 PICOS2KHZ(var->pixclock)); 741 if (forced && *forced) {
767 742 /* Only primitive parsing so far */
768 /* FIXME: Use user-provided configuration instead of EDID */ 743 i = sscanf(forced, "%ux%u@%u",
769 var->width = width; 744 &f_width, &f_height, &f_refresh);
770 var->xres = lcd_cfg->xres; 745 if (i < 2) {
771 var->xres_virtual = lcd_cfg->xres; 746 f_width = 0;
772 var->left_margin = lcd_cfg->left_margin; 747 f_height = 0;
773 var->right_margin = lcd_cfg->right_margin; 748 }
774 var->hsync_len = lcd_cfg->hsync_len; 749 dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
775 var->height = height; 750 f_width, f_height, f_refresh);
776 var->yres = lcd_cfg->yres; 751 }
777 var->yres_virtual = lcd_cfg->yres * 2; 752
778 var->upper_margin = lcd_cfg->upper_margin; 753 /* Walk monitor modes to find the best or the exact match */
779 var->lower_margin = lcd_cfg->lower_margin; 754 for (i = 0, mode = hdmi->monspec.modedb;
780 var->vsync_len = lcd_cfg->vsync_len; 755 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
781 var->sync = lcd_cfg->sync; 756 i++, mode++) {
782 var->pixclock = lcd_cfg->pixclock; 757 unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
783 758
784 hdmi_external_video_param(hdmi); 759 /* No interest in unmatching modes */
760 if (f_width != mode->xres || f_height != mode->yres)
761 continue;
762 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
763 /*
764 * Exact match if either the refresh rate matches or it
765 * hasn't been specified and we've found a mode, for
766 * which we can configure the clock precisely
767 */
768 exact_match = true;
769 else if (found && found_rate_error <= rate_error)
770 /*
771 * We otherwise search for the closest matching clock
772 * rate - either if no refresh rate has been specified
773 * or we cannot find an exactly matching one
774 */
775 continue;
776
777 /* Check if supported: sufficient fb memory, supported clock-rate */
778 fb_videomode_to_var(var, mode);
779
780 if (info && info->fbops->fb_check_var &&
781 info->fbops->fb_check_var(var, info)) {
782 exact_match = false;
783 continue;
784 }
785
786 found = mode;
787 found_rate_error = rate_error;
788 }
789
790 /*
791 * TODO 1: if no ->info is present, postpone running the config until
792 * after ->info first gets registered.
793 * TODO 2: consider registering the HDMI platform device from the LCDC
794 * driver, and passing ->info with HDMI platform data.
795 */
796 if (info && !found) {
797 modelist = hdmi->info->modelist.next &&
798 !list_empty(&hdmi->info->modelist) ?
799 list_entry(hdmi->info->modelist.next,
800 struct fb_modelist, list) :
801 NULL;
802
803 if (modelist) {
804 found = &modelist->mode;
805 found_rate_error = sh_hdmi_rate_error(hdmi, found);
806 }
807 }
808
809 /* No cookie today */
810 if (!found)
811 return -ENXIO;
812
813 dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
814 modelist ? "default" : "EDID", found->xres, found->yres,
815 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
816
817 if ((found->xres == 720 && found->yres == 480) ||
818 (found->xres == 1280 && found->yres == 720) ||
819 (found->xres == 1920 && found->yres == 1080))
820 hdmi->preprogrammed_mode = true;
821 else
822 hdmi->preprogrammed_mode = false;
823
824 fb_videomode_to_var(&hdmi->var, found);
825 sh_hdmi_external_video_param(hdmi);
826
827 return 0;
785} 828}
786 829
787static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) 830static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
@@ -809,8 +852,8 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
809 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); 852 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
810 853
811 if (printk_ratelimit()) 854 if (printk_ratelimit())
812 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", 855 dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
813 irq, status1, mask1, status2, mask2); 856 irq, status1, mask1, status2, mask2);
814 857
815 if (!((status1 & mask1) | (status2 & mask2))) { 858 if (!((status1 & mask1) | (status2 & mask2))) {
816 return IRQ_NONE; 859 return IRQ_NONE;
@@ -821,7 +864,7 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
821 udelay(500); 864 udelay(500);
822 865
823 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); 866 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
824 pr_debug("MSENS 0x%x\n", msens); 867 dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
825 /* Check, if hot plug & MSENS pin status are both high */ 868 /* Check, if hot plug & MSENS pin status are both high */
826 if ((msens & 0xC0) == 0xC0) { 869 if ((msens & 0xC0) == 0xC0) {
827 /* Display plug in */ 870 /* Display plug in */
@@ -857,83 +900,176 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
857 return IRQ_HANDLED; 900 return IRQ_HANDLED;
858} 901}
859 902
860static void hdmi_display_on(void *arg, struct fb_info *info) 903/* locking: called with info->lock held, or before register_framebuffer() */
904static void sh_hdmi_display_on(void *arg, struct fb_info *info)
861{ 905{
906 /*
907 * info is guaranteed to be valid, when we are called, because our
908 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
909 */
862 struct sh_hdmi *hdmi = arg; 910 struct sh_hdmi *hdmi = arg;
863 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 911 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
912 struct sh_mobile_lcdc_chan *ch = info->par;
864 913
865 if (info->var.xres != 1280 || info->var.yres != 720) { 914 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__,
866 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", 915 pdata->lcd_dev, info->state);
867 info->var.xres, info->var.yres); 916
868 return; 917 /* No need to lock */
869 } 918 hdmi->info = info;
870 919
871 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
872 /* 920 /*
873 * FIXME: not a good place to store fb_info. And we cannot nullify it 921 * hp_state can be set to
874 * even on monitor disconnect. What should the lifecycle be? 922 * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug
923 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
924 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
875 */ 925 */
876 hdmi->info = info;
877 switch (hdmi->hp_state) { 926 switch (hdmi->hp_state) {
878 case HDMI_HOTPLUG_EDID_DONE: 927 case HDMI_HOTPLUG_EDID_DONE:
879 /* PS mode d->e. All functions are active */ 928 /* PS mode d->e. All functions are active */
880 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 929 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
881 pr_debug("HDMI running\n"); 930 dev_dbg(hdmi->dev, "HDMI running\n");
882 break; 931 break;
883 case HDMI_HOTPLUG_DISCONNECTED: 932 case HDMI_HOTPLUG_DISCONNECTED:
884 info->state = FBINFO_STATE_SUSPENDED; 933 info->state = FBINFO_STATE_SUSPENDED;
885 default: 934 default:
886 hdmi->var = info->var; 935 hdmi->var = ch->display_var;
887 } 936 }
888} 937}
889 938
890static void hdmi_display_off(void *arg) 939/* locking: called with info->lock held */
940static void sh_hdmi_display_off(void *arg)
891{ 941{
892 struct sh_hdmi *hdmi = arg; 942 struct sh_hdmi *hdmi = arg;
893 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 943 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
894 944
895 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); 945 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev);
896 /* PS mode e->a */ 946 /* PS mode e->a */
897 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 947 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
898} 948}
899 949
950static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
951{
952 struct fb_info *info = hdmi->info;
953 struct sh_mobile_lcdc_chan *ch = info->par;
954 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
955 struct fb_videomode mode1, mode2;
956
957 fb_var_to_videomode(&mode1, old_var);
958 fb_var_to_videomode(&mode2, new_var);
959
960 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
961 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
962
963 if (fb_mode_is_equal(&mode1, &mode2))
964 return false;
965
966 dev_dbg(info->dev, "Switching %u -> %u lines\n",
967 mode1.yres, mode2.yres);
968 *old_var = *new_var;
969
970 return true;
971}
972
973/**
974 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
975 * @hdmi: driver context
976 * @pixclock: pixel clock period in picoseconds
977 * return: configured positive rate if successful
978 * 0 if couldn't set the rate, but managed to enable the clock
979 * negative error, if couldn't enable the clock
980 */
981static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock)
982{
983 long rate;
984 int ret;
985
986 rate = PICOS2KHZ(pixclock) * 1000;
987 rate = clk_round_rate(hdmi->hdmi_clk, rate);
988 if (rate > 0) {
989 ret = clk_set_rate(hdmi->hdmi_clk, rate);
990 if (ret < 0) {
991 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret);
992 rate = 0;
993 } else {
994 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate);
995 }
996 } else {
997 rate = 0;
998 dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
999 }
1000
1001 ret = clk_enable(hdmi->hdmi_clk);
1002 if (ret < 0) {
1003 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
1004 return ret;
1005 }
1006
1007 return rate;
1008}
1009
900/* Hotplug interrupt occurred, read EDID */ 1010/* Hotplug interrupt occurred, read EDID */
901static void edid_work_fn(struct work_struct *work) 1011static void sh_hdmi_edid_work_fn(struct work_struct *work)
902{ 1012{
903 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1013 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
904 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1014 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1015 struct sh_mobile_lcdc_chan *ch;
1016 int ret;
905 1017
906 pr_debug("%s(%p): begin, hotplug status %d\n", __func__, 1018 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__,
907 pdata->lcd_dev, hdmi->hp_state); 1019 pdata->lcd_dev, hdmi->hp_state);
908 1020
909 if (!pdata->lcd_dev) 1021 if (!pdata->lcd_dev)
910 return; 1022 return;
911 1023
1024 mutex_lock(&hdmi->mutex);
1025
912 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { 1026 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
913 pm_runtime_get_sync(hdmi->dev);
914 /* A device has been plugged in */ 1027 /* A device has been plugged in */
915 sh_hdmi_read_edid(hdmi); 1028 pm_runtime_get_sync(hdmi->dev);
1029
1030 ret = sh_hdmi_read_edid(hdmi);
1031 if (ret < 0)
1032 goto out;
1033
1034 /* Reconfigure the clock */
1035 clk_disable(hdmi->hdmi_clk);
1036 ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
1037 if (ret < 0)
1038 goto out;
1039
916 msleep(10); 1040 msleep(10);
917 sh_hdmi_configure(hdmi); 1041 sh_hdmi_configure(hdmi);
918 /* Switched to another (d) power-save mode */ 1042 /* Switched to another (d) power-save mode */
919 msleep(10); 1043 msleep(10);
920 1044
921 if (!hdmi->info) 1045 if (!hdmi->info)
922 return; 1046 goto out;
1047
1048 ch = hdmi->info->par;
923 1049
924 acquire_console_sem(); 1050 acquire_console_sem();
925 1051
926 /* HDMI plug in */ 1052 /* HDMI plug in */
927 hdmi->info->var = hdmi->var; 1053 if (!sh_hdmi_must_reconfigure(hdmi) &&
928 if (hdmi->info->state != FBINFO_STATE_RUNNING) 1054 hdmi->info->state == FBINFO_STATE_RUNNING) {
1055 /*
1056 * First activation with the default monitor - just turn
1057 * on, if we run a resume here, the logo disappears
1058 */
1059 if (lock_fb_info(hdmi->info)) {
1060 sh_hdmi_display_on(hdmi, hdmi->info);
1061 unlock_fb_info(hdmi->info);
1062 }
1063 } else {
1064 /* New monitor or have to wake up */
929 fb_set_suspend(hdmi->info, 0); 1065 fb_set_suspend(hdmi->info, 0);
930 else 1066 }
931 hdmi_display_on(hdmi, hdmi->info);
932 1067
933 release_console_sem(); 1068 release_console_sem();
934 } else { 1069 } else {
1070 ret = 0;
935 if (!hdmi->info) 1071 if (!hdmi->info)
936 return; 1072 goto out;
937 1073
938 acquire_console_sem(); 1074 acquire_console_sem();
939 1075
@@ -942,15 +1078,67 @@ static void edid_work_fn(struct work_struct *work)
942 1078
943 release_console_sem(); 1079 release_console_sem();
944 pm_runtime_put(hdmi->dev); 1080 pm_runtime_put(hdmi->dev);
1081 fb_destroy_modedb(hdmi->monspec.modedb);
945 } 1082 }
946 1083
947 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); 1084out:
1085 if (ret < 0)
1086 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1087 mutex_unlock(&hdmi->mutex);
1088
1089 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev);
1090}
1091
1092static int sh_hdmi_notify(struct notifier_block *nb,
1093 unsigned long action, void *data);
1094
1095static struct notifier_block sh_hdmi_notifier = {
1096 .notifier_call = sh_hdmi_notify,
1097};
1098
1099static int sh_hdmi_notify(struct notifier_block *nb,
1100 unsigned long action, void *data)
1101{
1102 struct fb_event *event = data;
1103 struct fb_info *info = event->info;
1104 struct sh_mobile_lcdc_chan *ch = info->par;
1105 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1106 struct sh_hdmi *hdmi = board_cfg->board_data;
1107
1108 if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info)
1109 return NOTIFY_DONE;
1110
1111 switch(action) {
1112 case FB_EVENT_FB_REGISTERED:
1113 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1114 break;
1115 case FB_EVENT_FB_UNREGISTERED:
1116 /*
1117 * We are called from unregister_framebuffer() with the
1118 * info->lock held. This is bad for us, because we can race with
1119 * the scheduled work, which has to call fb_set_suspend(), which
1120 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1121 * cannot take and hold info->lock for the whole function
1122 * duration. Using an additional lock creates a classical AB-BA
1123 * lock up. Therefore, we have to release the info->lock
1124 * temporarily, synchronise with the work queue and re-acquire
1125 * the info->lock.
1126 */
1127 unlock_fb_info(hdmi->info);
1128 mutex_lock(&hdmi->mutex);
1129 hdmi->info = NULL;
1130 mutex_unlock(&hdmi->mutex);
1131 lock_fb_info(hdmi->info);
1132 return NOTIFY_OK;
1133 }
1134 return NOTIFY_DONE;
948} 1135}
949 1136
950static int __init sh_hdmi_probe(struct platform_device *pdev) 1137static int __init sh_hdmi_probe(struct platform_device *pdev)
951{ 1138{
952 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1139 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
953 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1140 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1141 struct sh_mobile_lcdc_board_cfg *board_cfg;
954 int irq = platform_get_irq(pdev, 0), ret; 1142 int irq = platform_get_irq(pdev, 0), ret;
955 struct sh_hdmi *hdmi; 1143 struct sh_hdmi *hdmi;
956 long rate; 1144 long rate;
@@ -964,10 +1152,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
964 return -ENOMEM; 1152 return -ENOMEM;
965 } 1153 }
966 1154
967 ret = snd_soc_register_codec(&pdev->dev, 1155 mutex_init(&hdmi->mutex);
968 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
969 if (ret < 0)
970 goto esndreg;
971 1156
972 hdmi->dev = &pdev->dev; 1157 hdmi->dev = &pdev->dev;
973 1158
@@ -978,30 +1163,14 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
978 goto egetclk; 1163 goto egetclk;
979 } 1164 }
980 1165
981 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; 1166 /* Some arbitrary relaxed pixclock just to get things started */
982 1167 rate = sh_hdmi_clk_configure(hdmi, 37037);
983 rate = clk_round_rate(hdmi->hdmi_clk, rate);
984 if (rate < 0) { 1168 if (rate < 0) {
985 ret = rate; 1169 ret = rate;
986 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
987 goto erate; 1170 goto erate;
988 } 1171 }
989 1172
990 ret = clk_set_rate(hdmi->hdmi_clk, rate); 1173 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
991 if (ret < 0) {
992 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
993 goto erate;
994 }
995
996 pr_debug("HDMI set frequency %lu\n", rate);
997
998 ret = clk_enable(hdmi->hdmi_clk);
999 if (ret < 0) {
1000 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
1001 goto eclkenable;
1002 }
1003
1004 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
1005 1174
1006 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { 1175 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
1007 dev_err(&pdev->dev, "HDMI register region already claimed\n"); 1176 dev_err(&pdev->dev, "HDMI register region already claimed\n");
@@ -1018,18 +1187,18 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1018 1187
1019 platform_set_drvdata(pdev, hdmi); 1188 platform_set_drvdata(pdev, hdmi);
1020 1189
1021#if 1
1022 /* Product and revision IDs are 0 in sh-mobile version */ 1190 /* Product and revision IDs are 0 in sh-mobile version */
1023 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", 1191 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1024 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); 1192 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1025#endif
1026 1193
1027 /* Set up LCDC callbacks */ 1194 /* Set up LCDC callbacks */
1028 pdata->lcd_chan->board_cfg.board_data = hdmi; 1195 board_cfg = &pdata->lcd_chan->board_cfg;
1029 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; 1196 board_cfg->owner = THIS_MODULE;
1030 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; 1197 board_cfg->board_data = hdmi;
1198 board_cfg->display_on = sh_hdmi_display_on;
1199 board_cfg->display_off = sh_hdmi_display_off;
1031 1200
1032 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); 1201 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
1033 1202
1034 pm_runtime_enable(&pdev->dev); 1203 pm_runtime_enable(&pdev->dev);
1035 pm_runtime_resume(&pdev->dev); 1204 pm_runtime_resume(&pdev->dev);
@@ -1041,8 +1210,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1041 goto ereqirq; 1210 goto ereqirq;
1042 } 1211 }
1043 1212
1213 ret = snd_soc_register_codec(&pdev->dev,
1214 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
1215 if (ret < 0) {
1216 dev_err(&pdev->dev, "codec registration failed\n");
1217 goto ecodec;
1218 }
1219
1044 return 0; 1220 return 0;
1045 1221
1222ecodec:
1223 free_irq(irq, hdmi);
1046ereqirq: 1224ereqirq:
1047 pm_runtime_disable(&pdev->dev); 1225 pm_runtime_disable(&pdev->dev);
1048 iounmap(hdmi->base); 1226 iounmap(hdmi->base);
@@ -1050,12 +1228,10 @@ emap:
1050 release_mem_region(res->start, resource_size(res)); 1228 release_mem_region(res->start, resource_size(res));
1051ereqreg: 1229ereqreg:
1052 clk_disable(hdmi->hdmi_clk); 1230 clk_disable(hdmi->hdmi_clk);
1053eclkenable:
1054erate: 1231erate:
1055 clk_put(hdmi->hdmi_clk); 1232 clk_put(hdmi->hdmi_clk);
1056egetclk: 1233egetclk:
1057 snd_soc_unregister_codec(&pdev->dev); 1234 mutex_destroy(&hdmi->mutex);
1058esndreg:
1059 kfree(hdmi); 1235 kfree(hdmi);
1060 1236
1061 return ret; 1237 return ret;
@@ -1066,21 +1242,26 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
1066 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1242 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1067 struct sh_hdmi *hdmi = platform_get_drvdata(pdev); 1243 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1068 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1244 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1245 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
1069 int irq = platform_get_irq(pdev, 0); 1246 int irq = platform_get_irq(pdev, 0);
1070 1247
1071 snd_soc_unregister_codec(&pdev->dev); 1248 snd_soc_unregister_codec(&pdev->dev);
1072 1249
1073 pdata->lcd_chan->board_cfg.display_on = NULL; 1250 board_cfg->display_on = NULL;
1074 pdata->lcd_chan->board_cfg.display_off = NULL; 1251 board_cfg->display_off = NULL;
1075 pdata->lcd_chan->board_cfg.board_data = NULL; 1252 board_cfg->board_data = NULL;
1253 board_cfg->owner = NULL;
1076 1254
1255 /* No new work will be scheduled, wait for running ISR */
1077 free_irq(irq, hdmi); 1256 free_irq(irq, hdmi);
1078 pm_runtime_disable(&pdev->dev); 1257 /* Wait for already scheduled work */
1079 cancel_delayed_work_sync(&hdmi->edid_work); 1258 cancel_delayed_work_sync(&hdmi->edid_work);
1259 pm_runtime_disable(&pdev->dev);
1080 clk_disable(hdmi->hdmi_clk); 1260 clk_disable(hdmi->hdmi_clk);
1081 clk_put(hdmi->hdmi_clk); 1261 clk_put(hdmi->hdmi_clk);
1082 iounmap(hdmi->base); 1262 iounmap(hdmi->base);
1083 release_mem_region(res->start, resource_size(res)); 1263 release_mem_region(res->start, resource_size(res));
1264 mutex_destroy(&hdmi->mutex);
1084 kfree(hdmi); 1265 kfree(hdmi);
1085 1266
1086 return 0; 1267 return 0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 7a1419279c8f..50963739a409 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -12,7 +12,6 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/fb.h>
16#include <linux/clk.h> 15#include <linux/clk.h>
17#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
18#include <linux/platform_device.h> 17#include <linux/platform_device.h>
@@ -21,10 +20,12 @@
21#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
22#include <linux/ioctl.h> 21#include <linux/ioctl.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/console.h>
24#include <video/sh_mobile_lcdc.h> 24#include <video/sh_mobile_lcdc.h>
25#include <asm/atomic.h> 25#include <asm/atomic.h>
26 26
27#define PALETTE_NR 16 27#include "sh_mobile_lcdcfb.h"
28
28#define SIDE_B_OFFSET 0x1000 29#define SIDE_B_OFFSET 0x1000
29#define MIRROR_OFFSET 0x2000 30#define MIRROR_OFFSET 0x2000
30 31
@@ -53,11 +54,8 @@ static int lcdc_shared_regs[] = {
53}; 54};
54#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) 55#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
55 56
56/* per-channel registers */ 57#define DEFAULT_XRES 1280
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 58#define DEFAULT_YRES 1024
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
60 NR_CH_REGS };
61 59
62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 60static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
63 [LDDCKPAT1R] = 0x400, 61 [LDDCKPAT1R] = 0x400,
@@ -112,23 +110,21 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
112#define LDRCNTR_MRC 0x00000001 110#define LDRCNTR_MRC 0x00000001
113#define LDSR_MRS 0x00000100 111#define LDSR_MRS 0x00000100
114 112
115struct sh_mobile_lcdc_priv; 113static const struct fb_videomode default_720p = {
116struct sh_mobile_lcdc_chan { 114 .name = "HDMI 720p",
117 struct sh_mobile_lcdc_priv *lcdc; 115 .xres = 1280,
118 unsigned long *reg_offs; 116 .yres = 720,
119 unsigned long ldmt1r_value; 117
120 unsigned long enabled; /* ME and SE in LDCNT2R */ 118 .left_margin = 200,
121 struct sh_mobile_lcdc_chan_cfg cfg; 119 .right_margin = 88,
122 u32 pseudo_palette[PALETTE_NR]; 120 .hsync_len = 48,
123 unsigned long saved_ch_regs[NR_CH_REGS]; 121
124 struct fb_info *info; 122 .upper_margin = 20,
125 dma_addr_t dma_handle; 123 .lower_margin = 5,
126 struct fb_deferred_io defio; 124 .vsync_len = 5,
127 struct scatterlist *sglist; 125
128 unsigned long frame_end; 126 .pixclock = 13468,
129 unsigned long pan_offset; 127 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
130 wait_queue_head_t frame_end_wait;
131 struct completion vsync_completion;
132}; 128};
133 129
134struct sh_mobile_lcdc_priv { 130struct sh_mobile_lcdc_priv {
@@ -409,8 +405,8 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
409 405
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 406static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{ 407{
412 struct fb_var_screeninfo *var = &ch->info->var; 408 struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var;
413 unsigned long h_total, hsync_pos; 409 unsigned long h_total, hsync_pos, display_h_total;
414 u32 tmp; 410 u32 tmp;
415 411
416 tmp = ch->ldmt1r_value; 412 tmp = ch->ldmt1r_value;
@@ -428,31 +424,33 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); 424 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429 425
430 /* horizontal configuration */ 426 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len + 427 h_total = display_var->xres + display_var->hsync_len +
432 var->left_margin + var->right_margin; 428 display_var->left_margin + display_var->right_margin;
433 tmp = h_total / 8; /* HTCN */ 429 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */ 430 tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp); 431 lcdc_write_chan(ch, LDHCNR, tmp);
436 432
437 hsync_pos = var->xres + var->right_margin; 433 hsync_pos = display_var->xres + display_var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */ 434 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */ 435 tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp); 436 lcdc_write_chan(ch, LDHSYNR, tmp);
441 437
442 /* vertical configuration */ 438 /* vertical configuration */
443 tmp = var->yres + var->vsync_len + 439 tmp = display_var->yres + display_var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */ 440 display_var->upper_margin + display_var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */ 441 tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp); 442 lcdc_write_chan(ch, LDVLNR, tmp);
447 443
448 tmp = var->yres + var->lower_margin; /* VSYNP */ 444 tmp = display_var->yres + display_var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */ 445 tmp |= display_var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp); 446 lcdc_write_chan(ch, LDVSYNR, tmp);
451 447
452 /* Adjust horizontal synchronisation for HDMI */ 448 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) | 449 display_h_total = display_var->xres + display_var->hsync_len +
454 ((h_total & 7) << 16) | 450 display_var->left_margin + display_var->right_margin;
455 ((var->hsync_len & 7) << 8) | 451 tmp = ((display_var->xres & 7) << 24) |
452 ((display_h_total & 7) << 16) |
453 ((display_var->hsync_len & 7) << 8) |
456 hsync_pos; 454 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp); 455 lcdc_write_chan(ch, LDHAJR, tmp);
458} 456}
@@ -460,7 +458,6 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 458static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
461{ 459{
462 struct sh_mobile_lcdc_chan *ch; 460 struct sh_mobile_lcdc_chan *ch;
463 struct fb_videomode *lcd_cfg;
464 struct sh_mobile_lcdc_board_cfg *board_cfg; 461 struct sh_mobile_lcdc_board_cfg *board_cfg;
465 unsigned long tmp; 462 unsigned long tmp;
466 int k, m; 463 int k, m;
@@ -503,7 +500,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
503 m = 1 << 6; 500 m = 1 << 6;
504 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 501 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
505 502
506 lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000); 503 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
504 lcdc_write_chan(ch, LDDCKPAT1R, 0);
507 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 505 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
508 } 506 }
509 507
@@ -518,7 +516,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
518 516
519 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 517 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
520 ch = &priv->ch[k]; 518 ch = &priv->ch[k];
521 lcd_cfg = &ch->cfg.lcd_cfg;
522 519
523 if (!ch->enabled) 520 if (!ch->enabled)
524 continue; 521 continue;
@@ -547,7 +544,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
547 544
548 /* set bpp format in PKF[4:0] */ 545 /* set bpp format in PKF[4:0] */
549 tmp = lcdc_read_chan(ch, LDDFR); 546 tmp = lcdc_read_chan(ch, LDDFR);
550 tmp &= ~(0x0001001f); 547 tmp &= ~0x0001001f;
551 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; 548 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
552 lcdc_write_chan(ch, LDDFR, tmp); 549 lcdc_write_chan(ch, LDDFR, tmp);
553 550
@@ -591,8 +588,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
591 continue; 588 continue;
592 589
593 board_cfg = &ch->cfg.board_cfg; 590 board_cfg = &ch->cfg.board_cfg;
594 if (board_cfg->display_on) 591 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
595 board_cfg->display_on(board_cfg->board_data, ch->info); 592 board_cfg->display_on(board_cfg->board_data, ch->info);
593 module_put(board_cfg->owner);
594 }
596 } 595 }
597 596
598 return 0; 597 return 0;
@@ -614,7 +613,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
614 * flush frame, and wait for frame end interrupt 613 * flush frame, and wait for frame end interrupt
615 * clean up deferred io and enable clock 614 * clean up deferred io and enable clock
616 */ 615 */
617 if (ch->info->fbdefio) { 616 if (ch->info && ch->info->fbdefio) {
618 ch->frame_end = 0; 617 ch->frame_end = 0;
619 schedule_delayed_work(&ch->info->deferred_work, 0); 618 schedule_delayed_work(&ch->info->deferred_work, 0);
620 wait_event(ch->frame_end_wait, ch->frame_end); 619 wait_event(ch->frame_end_wait, ch->frame_end);
@@ -624,8 +623,10 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
624 } 623 }
625 624
626 board_cfg = &ch->cfg.board_cfg; 625 board_cfg = &ch->cfg.board_cfg;
627 if (board_cfg->display_off) 626 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
628 board_cfg->display_off(board_cfg->board_data); 627 board_cfg->display_off(board_cfg->board_data);
628 module_put(board_cfg->owner);
629 }
629 } 630 }
630 631
631 /* stop the lcdc */ 632 /* stop the lcdc */
@@ -704,7 +705,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
704 return PTR_ERR(priv->dot_clk); 705 return PTR_ERR(priv->dot_clk);
705 } 706 }
706 } 707 }
707 atomic_set(&priv->hw_usecnt, -1);
708 708
709 /* Runtime PM support involves two step for this driver: 709 /* Runtime PM support involves two step for this driver:
710 * 1) Enable Runtime PM 710 * 1) Enable Runtime PM
@@ -837,6 +837,102 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
837 return retval; 837 return retval;
838} 838}
839 839
840static void sh_mobile_fb_reconfig(struct fb_info *info)
841{
842 struct sh_mobile_lcdc_chan *ch = info->par;
843 struct fb_videomode mode1, mode2;
844 struct fb_event event;
845 int evnt = FB_EVENT_MODE_CHANGE_ALL;
846
847 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
848 /* More framebuffer users are active */
849 return;
850
851 fb_var_to_videomode(&mode1, &ch->display_var);
852 fb_var_to_videomode(&mode2, &info->var);
853
854 if (fb_mode_is_equal(&mode1, &mode2))
855 return;
856
857 /* Display has been re-plugged, framebuffer is free now, reconfigure */
858 if (fb_set_var(info, &ch->display_var) < 0)
859 /* Couldn't reconfigure, hopefully, can continue as before */
860 return;
861
862 info->fix.line_length = mode2.xres * (ch->cfg.bpp / 8);
863
864 /*
865 * fb_set_var() calls the notifier change internally, only if
866 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
867 * user event, we have to call the chain ourselves.
868 */
869 event.info = info;
870 event.data = &mode2;
871 fb_notifier_call_chain(evnt, &event);
872}
873
874/*
875 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
876 * user == 1, or with console sem held, if user == 0.
877 */
878static int sh_mobile_release(struct fb_info *info, int user)
879{
880 struct sh_mobile_lcdc_chan *ch = info->par;
881
882 mutex_lock(&ch->open_lock);
883 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
884
885 ch->use_count--;
886
887 /* Nothing to reconfigure, when called from fbcon */
888 if (user) {
889 acquire_console_sem();
890 sh_mobile_fb_reconfig(info);
891 release_console_sem();
892 }
893
894 mutex_unlock(&ch->open_lock);
895
896 return 0;
897}
898
899static int sh_mobile_open(struct fb_info *info, int user)
900{
901 struct sh_mobile_lcdc_chan *ch = info->par;
902
903 mutex_lock(&ch->open_lock);
904 ch->use_count++;
905
906 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
907 mutex_unlock(&ch->open_lock);
908
909 return 0;
910}
911
912static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
913{
914 struct sh_mobile_lcdc_chan *ch = info->par;
915
916 if (var->xres < 160 || var->xres > 1920 ||
917 var->yres < 120 || var->yres > 1080 ||
918 var->left_margin < 32 || var->left_margin > 320 ||
919 var->right_margin < 12 || var->right_margin > 240 ||
920 var->upper_margin < 12 || var->upper_margin > 120 ||
921 var->lower_margin < 1 || var->lower_margin > 64 ||
922 var->hsync_len < 32 || var->hsync_len > 240 ||
923 var->vsync_len < 2 || var->vsync_len > 64 ||
924 var->pixclock < 6000 || var->pixclock > 40000 ||
925 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
926 dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n",
927 var->xres, var->yres,
928 var->left_margin, var->right_margin,
929 var->upper_margin, var->lower_margin,
930 var->hsync_len, var->vsync_len,
931 var->pixclock);
932 return -EINVAL;
933 }
934 return 0;
935}
840 936
841static struct fb_ops sh_mobile_lcdc_ops = { 937static struct fb_ops sh_mobile_lcdc_ops = {
842 .owner = THIS_MODULE, 938 .owner = THIS_MODULE,
@@ -848,6 +944,9 @@ static struct fb_ops sh_mobile_lcdc_ops = {
848 .fb_imageblit = sh_mobile_lcdc_imageblit, 944 .fb_imageblit = sh_mobile_lcdc_imageblit,
849 .fb_pan_display = sh_mobile_fb_pan_display, 945 .fb_pan_display = sh_mobile_fb_pan_display,
850 .fb_ioctl = sh_mobile_ioctl, 946 .fb_ioctl = sh_mobile_ioctl,
947 .fb_open = sh_mobile_open,
948 .fb_release = sh_mobile_release,
949 .fb_check_var = sh_mobile_check_var,
851}; 950};
852 951
853static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 952static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -958,6 +1057,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
958 .runtime_resume = sh_mobile_lcdc_runtime_resume, 1057 .runtime_resume = sh_mobile_lcdc_runtime_resume,
959}; 1058};
960 1059
1060/* locking: called with info->lock held */
961static int sh_mobile_lcdc_notify(struct notifier_block *nb, 1061static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data) 1062 unsigned long action, void *data)
963{ 1063{
@@ -965,53 +1065,40 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
965 struct fb_info *info = event->info; 1065 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par; 1066 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; 1067 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var; 1068 int ret;
969 1069
970 if (&ch->lcdc->notifier != nb) 1070 if (&ch->lcdc->notifier != nb)
971 return 0; 1071 return NOTIFY_DONE;
972 1072
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 1073 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data); 1074 __func__, action, event->data);
975 1075
976 switch(action) { 1076 switch(action) {
977 case FB_EVENT_SUSPEND: 1077 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off) 1078 if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
979 board_cfg->display_off(board_cfg->board_data); 1079 board_cfg->display_off(board_cfg->board_data);
1080 module_put(board_cfg->owner);
1081 }
980 pm_runtime_put(info->device); 1082 pm_runtime_put(info->device);
1083 sh_mobile_lcdc_stop(ch->lcdc);
981 break; 1084 break;
982 case FB_EVENT_RESUME: 1085 case FB_EVENT_RESUME:
983 var = &info->var; 1086 mutex_lock(&ch->open_lock);
1087 sh_mobile_fb_reconfig(info);
1088 mutex_unlock(&ch->open_lock);
984 1089
985 /* HDMI must be enabled before LCDC configuration */ 1090 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on) 1091 if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
987 board_cfg->display_on(board_cfg->board_data, ch->info); 1092 board_cfg->display_on(board_cfg->board_data, info);
988 1093 module_put(board_cfg->owner);
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 } 1094 }
1006 1095
1007 pm_runtime_get_sync(info->device); 1096 ret = sh_mobile_lcdc_start(ch->lcdc);
1008 1097 if (!ret)
1009 sh_mobile_lcdc_geometry(ch); 1098 pm_runtime_get_sync(info->device);
1010
1011 break;
1012 } 1099 }
1013 1100
1014 return 0; 1101 return NOTIFY_OK;
1015} 1102}
1016 1103
1017static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1104static int sh_mobile_lcdc_remove(struct platform_device *pdev);
@@ -1020,14 +1107,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020{ 1107{
1021 struct fb_info *info; 1108 struct fb_info *info;
1022 struct sh_mobile_lcdc_priv *priv; 1109 struct sh_mobile_lcdc_priv *priv;
1023 struct sh_mobile_lcdc_info *pdata; 1110 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
1024 struct sh_mobile_lcdc_chan_cfg *cfg;
1025 struct resource *res; 1111 struct resource *res;
1026 int error; 1112 int error;
1027 void *buf; 1113 void *buf;
1028 int i, j; 1114 int i, j;
1029 1115
1030 if (!pdev->dev.platform_data) { 1116 if (!pdata) {
1031 dev_err(&pdev->dev, "no platform data defined\n"); 1117 dev_err(&pdev->dev, "no platform data defined\n");
1032 return -EINVAL; 1118 return -EINVAL;
1033 } 1119 }
@@ -1055,31 +1141,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1055 } 1141 }
1056 1142
1057 priv->irq = i; 1143 priv->irq = i;
1058 pdata = pdev->dev.platform_data; 1144 atomic_set(&priv->hw_usecnt, -1);
1059 1145
1060 j = 0; 1146 j = 0;
1061 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { 1147 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
1062 priv->ch[j].lcdc = priv; 1148 struct sh_mobile_lcdc_chan *ch = priv->ch + j;
1063 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1149
1150 ch->lcdc = priv;
1151 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
1064 1152
1065 error = sh_mobile_lcdc_check_interface(&priv->ch[j]); 1153 error = sh_mobile_lcdc_check_interface(ch);
1066 if (error) { 1154 if (error) {
1067 dev_err(&pdev->dev, "unsupported interface type\n"); 1155 dev_err(&pdev->dev, "unsupported interface type\n");
1068 goto err1; 1156 goto err1;
1069 } 1157 }
1070 init_waitqueue_head(&priv->ch[j].frame_end_wait); 1158 init_waitqueue_head(&ch->frame_end_wait);
1071 init_completion(&priv->ch[j].vsync_completion); 1159 init_completion(&ch->vsync_completion);
1072 priv->ch[j].pan_offset = 0; 1160 ch->pan_offset = 0;
1073 1161
1074 switch (pdata->ch[i].chan) { 1162 switch (pdata->ch[i].chan) {
1075 case LCDC_CHAN_MAINLCD: 1163 case LCDC_CHAN_MAINLCD:
1076 priv->ch[j].enabled = 1 << 1; 1164 ch->enabled = 1 << 1;
1077 priv->ch[j].reg_offs = lcdc_offs_mainlcd; 1165 ch->reg_offs = lcdc_offs_mainlcd;
1078 j++; 1166 j++;
1079 break; 1167 break;
1080 case LCDC_CHAN_SUBLCD: 1168 case LCDC_CHAN_SUBLCD:
1081 priv->ch[j].enabled = 1 << 2; 1169 ch->enabled = 1 << 2;
1082 priv->ch[j].reg_offs = lcdc_offs_sublcd; 1170 ch->reg_offs = lcdc_offs_sublcd;
1083 j++; 1171 j++;
1084 break; 1172 break;
1085 } 1173 }
@@ -1103,69 +1191,83 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1103 1191
1104 for (i = 0; i < j; i++) { 1192 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var; 1193 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg; 1194 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
1107 cfg = &priv->ch[i].cfg; 1195 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1196 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1197 const struct fb_videomode *mode = cfg->lcd_cfg;
1198 unsigned long max_size = 0;
1199 int k;
1108 1200
1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1201 ch->info = framebuffer_alloc(0, &pdev->dev);
1110 if (!priv->ch[i].info) { 1202 if (!ch->info) {
1111 dev_err(&pdev->dev, "unable to allocate fb_info\n"); 1203 dev_err(&pdev->dev, "unable to allocate fb_info\n");
1112 error = -ENOMEM; 1204 error = -ENOMEM;
1113 break; 1205 break;
1114 } 1206 }
1115 1207
1116 info = priv->ch[i].info; 1208 info = ch->info;
1117 var = &info->var; 1209 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1119 info->fbops = &sh_mobile_lcdc_ops; 1210 info->fbops = &sh_mobile_lcdc_ops;
1120 var->xres = var->xres_virtual = lcd_cfg->xres; 1211 info->par = ch;
1121 var->yres = lcd_cfg->yres; 1212
1213 mutex_init(&ch->open_lock);
1214
1215 for (k = 0, lcd_cfg = mode;
1216 k < cfg->num_cfg && lcd_cfg;
1217 k++, lcd_cfg++) {
1218 unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
1219
1220 if (size > max_size) {
1221 max_cfg = lcd_cfg;
1222 max_size = size;
1223 }
1224 }
1225
1226 if (!mode)
1227 max_size = DEFAULT_XRES * DEFAULT_YRES;
1228 else if (max_cfg)
1229 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1230 max_cfg->xres, max_cfg->yres);
1231
1232 info->fix = sh_mobile_lcdc_fix;
1233 info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
1234
1235 if (!mode)
1236 mode = &default_720p;
1237
1238 fb_videomode_to_var(var, mode);
1122 /* Default Y virtual resolution is 2x panel size */ 1239 /* Default Y virtual resolution is 2x panel size */
1123 var->yres_virtual = var->yres * 2; 1240 var->yres_virtual = var->yres * 2;
1124 var->width = cfg->lcd_size_cfg.width;
1125 var->height = cfg->lcd_size_cfg.height;
1126 var->activate = FB_ACTIVATE_NOW; 1241 var->activate = FB_ACTIVATE_NOW;
1127 var->left_margin = lcd_cfg->left_margin;
1128 var->right_margin = lcd_cfg->right_margin;
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135 1242
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); 1243 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1137 if (error) 1244 if (error)
1138 break; 1245 break;
1139 1246
1140 info->fix = sh_mobile_lcdc_fix;
1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1142 info->fix.smem_len = info->fix.line_length *
1143 var->yres_virtual;
1144
1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1247 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1146 &priv->ch[i].dma_handle, GFP_KERNEL); 1248 &ch->dma_handle, GFP_KERNEL);
1147 if (!buf) { 1249 if (!buf) {
1148 dev_err(&pdev->dev, "unable to allocate buffer\n"); 1250 dev_err(&pdev->dev, "unable to allocate buffer\n");
1149 error = -ENOMEM; 1251 error = -ENOMEM;
1150 break; 1252 break;
1151 } 1253 }
1152 1254
1153 info->pseudo_palette = &priv->ch[i].pseudo_palette; 1255 info->pseudo_palette = &ch->pseudo_palette;
1154 info->flags = FBINFO_FLAG_DEFAULT; 1256 info->flags = FBINFO_FLAG_DEFAULT;
1155 1257
1156 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1258 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1157 if (error < 0) { 1259 if (error < 0) {
1158 dev_err(&pdev->dev, "unable to allocate cmap\n"); 1260 dev_err(&pdev->dev, "unable to allocate cmap\n");
1159 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1261 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1160 buf, priv->ch[i].dma_handle); 1262 buf, ch->dma_handle);
1161 break; 1263 break;
1162 } 1264 }
1163 1265
1164 memset(buf, 0, info->fix.smem_len); 1266 info->fix.smem_start = ch->dma_handle;
1165 info->fix.smem_start = priv->ch[i].dma_handle; 1267 info->fix.line_length = var->xres * (cfg->bpp / 8);
1166 info->screen_base = buf; 1268 info->screen_base = buf;
1167 info->device = &pdev->dev; 1269 info->device = &pdev->dev;
1168 info->par = &priv->ch[i]; 1270 ch->display_var = *var;
1169 } 1271 }
1170 1272
1171 if (error) 1273 if (error)
@@ -1179,6 +1281,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1179 1281
1180 for (i = 0; i < j; i++) { 1282 for (i = 0; i < j; i++) {
1181 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1283 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1284 const struct fb_videomode *mode = ch->cfg.lcd_cfg;
1285
1286 if (!mode)
1287 mode = &default_720p;
1182 1288
1183 info = ch->info; 1289 info = ch->info;
1184 1290
@@ -1191,6 +1297,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1191 } 1297 }
1192 } 1298 }
1193 1299
1300 fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist);
1194 error = register_framebuffer(info); 1301 error = register_framebuffer(info);
1195 if (error < 0) 1302 if (error < 0)
1196 goto err1; 1303 goto err1;
@@ -1200,8 +1307,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1200 pdev->name, 1307 pdev->name,
1201 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1308 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1202 "mainlcd" : "sublcd", 1309 "mainlcd" : "sublcd",
1203 (int) ch->cfg.lcd_cfg.xres, 1310 info->var.xres, info->var.yres,
1204 (int) ch->cfg.lcd_cfg.yres,
1205 ch->cfg.bpp); 1311 ch->cfg.bpp);
1206 1312
1207 /* deferred io mode: disable clock to save power */ 1313 /* deferred io mode: disable clock to save power */
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
new file mode 100644
index 000000000000..9ecee2fba1d7
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -0,0 +1,41 @@
1#ifndef SH_MOBILE_LCDCFB_H
2#define SH_MOBILE_LCDCFB_H
3
4#include <linux/completion.h>
5#include <linux/fb.h>
6#include <linux/mutex.h>
7#include <linux/wait.h>
8
9/* per-channel registers */
10enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
11 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
12 LDHAJR,
13 NR_CH_REGS };
14
15#define PALETTE_NR 16
16
17struct sh_mobile_lcdc_priv;
18struct fb_info;
19
20struct sh_mobile_lcdc_chan {
21 struct sh_mobile_lcdc_priv *lcdc;
22 unsigned long *reg_offs;
23 unsigned long ldmt1r_value;
24 unsigned long enabled; /* ME and SE in LDCNT2R */
25 struct sh_mobile_lcdc_chan_cfg cfg;
26 u32 pseudo_palette[PALETTE_NR];
27 unsigned long saved_ch_regs[NR_CH_REGS];
28 struct fb_info *info;
29 dma_addr_t dma_handle;
30 struct fb_deferred_io defio;
31 struct scatterlist *sglist;
32 unsigned long frame_end;
33 unsigned long pan_offset;
34 wait_queue_head_t frame_end_wait;
35 struct completion vsync_completion;
36 struct fb_var_screeninfo display_var;
37 int use_count;
38 struct mutex open_lock; /* protects the use counter */
39};
40
41#endif
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 55d700e8566e..daabae5817c6 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -49,7 +49,9 @@ struct sh_mobile_lcdc_sys_bus_ops {
49 unsigned long (*read_data)(void *handle); 49 unsigned long (*read_data)(void *handle);
50}; 50};
51 51
52struct module;
52struct sh_mobile_lcdc_board_cfg { 53struct sh_mobile_lcdc_board_cfg {
54 struct module *owner;
53 void *board_data; 55 void *board_data;
54 int (*setup_sys)(void *board_data, void *sys_ops_handle, 56 int (*setup_sys)(void *board_data, void *sys_ops_handle,
55 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 57 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
@@ -70,7 +72,8 @@ struct sh_mobile_lcdc_chan_cfg {
70 int interface_type; /* selects RGBn or SYSn I/F, see above */ 72 int interface_type; /* selects RGBn or SYSn I/F, see above */
71 int clock_divider; 73 int clock_divider;
72 unsigned long flags; /* LCDC_FLAGS_... */ 74 unsigned long flags; /* LCDC_FLAGS_... */
73 struct fb_videomode lcd_cfg; 75 const struct fb_videomode *lcd_cfg;
76 int num_cfg;
74 struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; 77 struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg;
75 struct sh_mobile_lcdc_board_cfg board_cfg; 78 struct sh_mobile_lcdc_board_cfg board_cfg;
76 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ 79 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */