diff options
author | Chris Conley <cconley@phytec.com> | 2013-08-06 15:57:43 -0700 |
---|---|---|
committer | Anthony Felice <tony.felice@timesys.com> | 2013-09-17 14:22:14 -0400 |
commit | c3f595da0584c68148623af8cb1d4b2f769305a7 (patch) | |
tree | e416622a7cfc09f5fe2a4d2604ca9b34af23bfb2 | |
parent | 145626078f6ed903c95fbbf1883d4d3d70433c92 (diff) |
pcl052: Cosmic board init and configuration support
Signed-off-by: Chris Conley <cconley@phytec.com>
Signed-off-by: Russell Robinson <rrobinson@phytec.com>
-rw-r--r-- | arch/arm/mach-mvf/Kconfig | 33 | ||||
-rw-r--r-- | arch/arm/mach-mvf/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-mvf/board-pcl052.c | 548 | ||||
-rw-r--r-- | arch/arm/mach-mvf/clock.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-mvf/devices-mvf.h | 8 | ||||
-rw-r--r-- | arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-mxc/devices/platform-mxc-ehci.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/iomux-mvf.h | 8 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/irqs.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h | 6 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/mvf.h | 2 | ||||
-rw-r--r-- | arch/arm/tools/mach-types | 1 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 4 | ||||
-rw-r--r-- | drivers/video/Kconfig | 7 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/mvf-tda1998x.c | 221 | ||||
-rw-r--r-- | drivers/video/mvf-tda1998x.h | 268 | ||||
-rw-r--r-- | drivers/video/mvf_dcu.c | 85 |
19 files changed, 1182 insertions, 32 deletions
diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig index 0ef1f8a09d37..24490ccb45d8 100644 --- a/arch/arm/mach-mvf/Kconfig +++ b/arch/arm/mach-mvf/Kconfig @@ -92,4 +92,37 @@ config MACH_PCM052 Include support for PHYTEC phyCORE-Vybrid platform. This includes specific configurations for the board and its peripherals. +config MACH_PCL052 + bool "Support Phytec Cosmic (MVF Cortex-A5) platform" + select ARCH_MVFA5 + select SOC_MVFA5 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_DMA + select IMX_HAVE_PLATFORM_FEC + select IMX_HAVE_PLATFORM_GPMI_NFC + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_VIV_GPU + select IMX_HAVE_PLATFORM_IMX_VPU + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_FSL_OTG + select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP + select IMX_HAVE_PLATFORM_AHCI + select IMX_HAVE_PLATFORM_IMX_OCOTP + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_SNVS_RTC + select IMX_HAVE_PLATFORM_IMX_PM + select IMX_HAVE_PLATFORM_MXC_HDMI + select IMX_HAVE_PLATFORM_IMX_ASRC + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_MVF_SPI + select IMX_HAVE_PLATFORM_MVF_DCU + select IMX_HAVE_PLATFORM_MVF_SAI + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for PHYTEC Cosmic platform. This includes + specific configurations for the board and its peripherals. + endif diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile index 3128d4288c3d..ee2b9597c339 100644 --- a/arch/arm/mach-mvf/Makefile +++ b/arch/arm/mach-mvf/Makefile @@ -9,3 +9,4 @@ obj-y += l2switch.o obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o obj-$(CONFIG_MACH_MVFA5_TWR_VF700) += board-twr-vf700.o obj-$(CONFIG_MACH_PCM052) += board-pcm052.o +obj-$(CONFIG_MACH_PCL052) += board-pcl052.o diff --git a/arch/arm/mach-mvf/board-pcl052.c b/arch/arm/mach-mvf/board-pcl052.c new file mode 100644 index 000000000000..5e715df8a876 --- /dev/null +++ b/arch/arm/mach-mvf/board-pcl052.c @@ -0,0 +1,548 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/smsc911x.h> +#include <linux/spi/spi.h> +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +#include <linux/spi/flash.h> +#else +#include <linux/mtd/physmap.h> +#endif +#include <linux/i2c.h> +#include <linux/i2c/at24.h> +#include <linux/i2c/pca953x.h> +#include <linux/mfd/stmpe.h> +#include <linux/ata.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/pmic_external.h> +#include <linux/pmic_status.h> +#include <linux/ipu.h> +#include <linux/mxcfb.h> +#include <linux/phy.h> // SP: added for reference to phy_ functions, ex. phy_register_fixup +#include <linux/pwm_backlight.h> +#include <linux/leds_pwm.h> +#include <linux/fec.h> +#include <linux/memblock.h> +#include <linux/gpio.h> +#include <linux/etherdevice.h> +#include <linux/regulator/anatop-regulator.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/fixed.h> +#include <sound/pcm.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/mxc_dvfs.h> +#include <mach/memory.h> +#include <mach/iomux-mvf.h> +#include <mach/imx-uart.h> +#include <mach/spi-mvf.h> +#include <mach/viv_gpu.h> +#include <mach/ahci_sata.h> +#include <mach/ipu-v3.h> +#include <mach/mxc_hdmi.h> +#include <mach/mxc_asrc.h> +#include <mach/mipi_dsi.h> +#include <mach/mipi_csi2.h> +#include <mach/fsl_l2_switch.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> + +#include "devices-mvf.h" +#include "usb.h" +#include "crm_regs.h" + +#define PCL052_SD1_CD 98 +#define PCL052_TS_IRQ 32 + +/* FEC1 definitions */ +#define FEC1_BUS_ID "2:01" // SP: BUS_ID - required to use phy-fixup specifically for the ETH1 PHY + +#define KSZ8051_PHY_CTRL2 0x1F // SP: PHY Control 2 register address +#define KSZ8051_50MHZ_CLK_MODE (1 << 7) // SP: PHY Control 2 register setting for 50 MHz clock mode + +#ifdef PCM952_REV0 +#undef PCM952_REV0 +#endif + +static iomux_v3_cfg_t pcl052_pads[] = { + + /*SDHC1*/ + MVF600_PAD14_PTA24__SDHC1_CLK, + MVF600_PAD15_PTA25__SDHC1_CMD, + MVF600_PAD16_PTA26__SDHC1_DAT0, + MVF600_PAD17_PTA27__SDHC1_DAT1, + MVF600_PAD18_PTA28__SDHC1_DAT2, + MVF600_PAD19_PTA29__SDHC1_DAT3, + /*set PTB28 as GPIO for sdhc card detecting*/ + // GPIO[98] + MVF600_PAD98_PTB28__SDHC1_SW_CD, + /*I2C2*/ + MVF600_PAD12_PTA22__I2C2_SCL, + MVF600_PAD13_PTA23__I2C2_SDA, + + /*CAN0*/ + MVF600_PAD36_PTB14__CAN0_RX, + MVF600_PAD37_PTB15__CAN0_TX, + + /*CAN1*/ + MVF600_PAD38_PTB16__CAN1_RX, + MVF600_PAD39_PTB17__CAN1_TX, + + /*DSPI0*/ + MVF600_PAD41_PTB19__DSPI0_PCS0, + MVF600_PAD42_PTB20__DSPI0_SIN, + MVF600_PAD43_PTB21__DSPI0_SOUT, + MVF600_PAD44_PTB22__DSPI0_SCK, + + /*FEC0 not supported*/ +#if defined(CONFIG_FEC1) || defined(CONFIG_FSL_L2_SWITCH) + /*FEC1*/ + MVF600_PAD54_PTC9__RMII1_MDC, + MVF600_PAD55_PTC10__RMII1_MDIO, + MVF600_PAD56_PTC11__RMII1_CRS_DV, + MVF600_PAD57_PTC12__RMII1_RXD1, + MVF600_PAD58_PTC13__RMII1_RXD0, + MVF600_PAD59_PTC14__RMII1_RXER, + MVF600_PAD60_PTC15__RMII1_TXD1, + MVF600_PAD61_PTC16__RMII1_TXD0, + MVF600_PAD62_PTC17__RMII1_TXEN, +#endif + /*TDA19988x HDMI Encoder*/ + /***Video*/ + MVF600_PAD108_PTE3_LCD_ENABLE, + MVF600_PAD105_PTE0_DCU0_HSYNC, + MVF600_PAD106_PTE1_DCU0_VSYNC, + MVF600_PAD107_PTE2_DCU0_PCLK, + MVF600_PAD109_PTE4_DCU0_DE, + MVF600_PAD110_PTE5_DCU0_R0, + MVF600_PAD111_PTE6_DCU0_R1, + MVF600_PAD112_PTE7_DCU0_R2, + MVF600_PAD113_PTE8_DCU0_R3, + MVF600_PAD114_PTE9_DCU0_R4, + MVF600_PAD115_PTE10_DCU0_R5, + MVF600_PAD116_PTE11_DCU0_R6, + MVF600_PAD117_PTE12_DCU0_R7, + MVF600_PAD118_PTE13_DCU0_G0, + MVF600_PAD119_PTE14_DCU0_G1, + MVF600_PAD120_PTE15_DCU0_G2, + MVF600_PAD121_PTE16_DCU0_G3, + MVF600_PAD122_PTE17_DCU0_G4, + MVF600_PAD123_PTE18_DCU0_G5, + MVF600_PAD124_PTE19_DCU0_G6, + MVF600_PAD125_PTE20_DCU0_G7, + MVF600_PAD126_PTE21_DCU0_B0, + MVF600_PAD127_PTE22_DCU0_B1, + MVF600_PAD128_PTE23_DCU0_B2, + MVF600_PAD129_PTE24_DCU0_B3, + MVF600_PAD130_PTE25_DCU0_B4, + MVF600_PAD131_PTE26_DCU0_B5, + MVF600_PAD132_PTE27_DCU0_B6, + MVF600_PAD133_PTE28_DCU0_B7, + /* MVF600_PAD53_PTC8__GPIO_TDA_INT*/ + IOMUX_PAD(0x00D4, 0x00D4, IOMUX_CONFIG_ALT0, 0x0000, 0, + PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SPEED_MED + | PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_25ohm + | PAD_CTL_ODE | PAD_CTL_IBE_ENABLE), + + /***Audio*/ + /* BCLK ACLK*/ + MVF600_PAD6_PTA16_SAI2_TX_BCLK, + /* SYNC WS/AP0 */ + MVF600_PAD9_PTA19_SAI2_TX_SYNC, + /* DATA AXR0/AP1 */ + MVF600_PAD8_PTA18_SAI2_TX_DATA, + /* PTB10 MCLK OSC_IN/AP3 CKIO1 */ + IOMUX_PAD(0x0080, 0x0080, 6, 0x0000, 0, \ + MVF600_SAI_PAD_CTRL | PAD_CTL_IBE_ENABLE), + + /*UART1*/ + MVF600_PAD26_PTB4_UART1_TX, + MVF600_PAD27_PTB5_UART1_RX, + + /*USB0/1 VBUS_EN*/ +#ifdef PCM952_REV0 + MVF600_PAD6_PTA16__USB0_VBUS_EN, +#else + MVF600_PAD134_PTA7__USB_VBUS_EN, +#endif + MVF600_PAD7_PTA17__USB_OC_N, + + /* Quad SPI */ + MVF600_PAD79_PTD0_QSPI0_A_SCK, + MVF600_PAD80_PTD1_QSPI0_A_CS0, + MVF600_PAD81_PTD2_QSPI0_A_D3, + MVF600_PAD82_PTD3_QSPI0_A_D2, + MVF600_PAD83_PTD4_QSPI0_A_D1, + MVF600_PAD84_PTD5_QSPI0_A_D0, + MVF600_PAD86_PTD7_QSPI0_B_SCK, + MVF600_PAD87_PTD8_QSPI0_B_CS0, + MVF600_PAD88_PTD9_QSPI0_B_D3, + MVF600_PAD89_PTD10_QSPI0_B_D2, + MVF600_PAD90_PTD11_QSPI0_B_D1, + MVF600_PAD91_PTD12_QSPI0_B_D0, +}; + +/* TODO: HDMI Audio Initialization */ +static struct mxc_audio_platform_data pcl052_audio_data; + +static int pcl052_hdmiA_init(void) +{ + pcl052_audio_data.sysclk = 12288000; + return 0; +} + +static struct mvf_sai_platform_data mvf_sai_pdata = { + .flags = MVF_SAI_DMA | MVF_SAI_TRA_SYN | MVF_SAI_USE_I2S_SLAVE, +}; + +static struct mxc_audio_platform_data pcl052_audio_data = { + .sai_num = 1, + .src_port = 2, + .ext_port = 2, + .init = pcl052_hdmiA_init, +}; + +static struct platform_device pcl052_audio_device = { + .name = "mvf-hdmiaudiocodec", +}; + +static struct imxuart_platform_data mvf_uart1_pdata = { + .flags = IMXUART_FIFO | IMXUART_EDMA, + .dma_req_rx = DMA_MUX03_UART1_RX, + .dma_req_tx = DMA_MUX03_UART1_TX, +}; + +static inline void pcl052_init_uart(void) +{ + mvf_add_imx_uart(1, &mvf_uart1_pdata); +} + +static struct fec_platform_data fec_data __initdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static struct switch_platform_data switch_data __initdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +/* SP: Added function - mvf_fec1_phy_fixup + * Additional configuration is required to setup ETH1 on the phyCORE-Vybrid + * (1) Set to 50 MHz (enable bit 7 in the PHY control 2 register) + - Write: reg - 0x1F; data - (0x1 << 7) +*/ + +static int mvf_fec1_phy_fixup(struct phy_device *phydev) +{ + int regval; + regval = phy_read(phydev, KSZ8051_PHY_CTRL2); // read current value of PHY Control 2 register + regval |= KSZ8051_50MHZ_CLK_MODE; // enable 50MHz clock mode + phy_write(phydev, KSZ8051_PHY_CTRL2, regval); // write to PHY Control 2 register + + return 0; +} + +static int pcl052_spi_cs[] = { + 41, +}; + +static const struct spi_mvf_master pcl052_spi_data __initconst = { + .bus_num = 0, + .chipselect = pcl052_spi_cs, + .num_chipselect = ARRAY_SIZE(pcl052_spi_cs), + .cs_control = NULL, +}; + +static int pcl052_qspi_cs[] = { + 80, + 87, +}; + +static const struct spi_mvf_master pcl052_qspi_data __initconst = { + .bus_num = 0, + .chipselect = pcl052_qspi_cs, + .num_chipselect = ARRAY_SIZE(pcl052_qspi_cs), + .cs_control = NULL, +}; + +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition at26df081a_partitions[] = { + { + .name = "at26df081a", + .size = (1024 * 64 * 16), + .offset = 0x00000000, + .mask_flags = 0, + } +}; + +static struct flash_platform_data at26df081a_platform_data = { + .name = "Atmel at26df081a SPI Flash chip", + .parts = at26df081a_partitions, + .nr_parts = ARRAY_SIZE(at26df081a_partitions), + .type = "at26df081a", +}; + +static struct spi_mvf_chip at26df081a_chip_info = { + .mode = SPI_MODE_3, + .bits_per_word = 8, + .void_write_data = 0, + .dbr = 0, + .pbr = 0, + .br = 0, + .pcssck = 0, + .pasc = 0, + .pdt = 0, + .cssck = 0, + .asc = 0, + .dt = 0, +}; + +static struct mtd_partition s25fl256s_partitions[] = { + { + .name = "s25fl256s", + .size = (1024 * 64 * 256), + .offset = 0x00000000, + .mask_flags = 0, + } +}; + +static struct flash_platform_data s25fl256s_spi_flash_data = { + .name = "Spansion s25fl128s SPI Flash chip", + .parts = s25fl256s_partitions, + .nr_parts = ARRAY_SIZE(s25fl256s_partitions), + .type = "s25fl128s", +}; +#endif + +static struct spi_board_info mvf_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) +#if defined(CONFIG_SPI_MVF_QSPI) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &s25fl256s_spi_flash_data, + }, +#endif +#if defined(CONFIG_SPI_MVF) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 16000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &at26df081a_platform_data, + .controller_data = &at26df081a_chip_info + }, +#endif +#endif +}; + +static void spi_device_init(void) +{ + spi_register_board_info(mvf_spi_board_info, + ARRAY_SIZE(mvf_spi_board_info)); +} + +#if 1 +static void pcl052_suspend_enter(void) +{ + /* suspend preparation */ +} + +static void pcl052_suspend_exit(void) +{ + /* resmue resore */ +} +static const struct pm_platform_data pcl052_pm_data __initconst = { + .name = "mvf_pm", + .suspend_enter = pcl052_suspend_enter, + .suspend_exit = pcl052_suspend_exit, +}; +#endif + +static struct mvf_dcu_platform_data mvf_dcu_pdata = { + .mode_str = "640x480p_min", /* works with HDMI PC, not HDMI TV */ + // .mode_str = "720x480p", + .default_bpp = 24, +}; + +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ +} +/* + * Not defined the cd/wp so far, set it always present for debug*/ +static const struct esdhc_platform_data pcl052_sd1_data __initconst = { + .cd_gpio = PCL052_SD1_CD, + .wp_gpio = -1, +}; + +/* SP: Replicate the AM335x solution for phy_fixup + * - Call a phy_register_fixup to make the required changes for FEC1/ETH1 - see 'mvf_fec1_phy_fixup' + * - 'pcl052_setup' will be assigned to .setup in EEPROM platform data (board_eeprom) + */ +static void pcl052_setup(struct memory_accessor *mem_acc, void *context) +{ + phy_register_fixup_for_id(FEC1_BUS_ID, mvf_fec1_phy_fixup); // SP: run mvf_fec1_phy_fixup to setup ETH1 + return; +} + +static struct at24_platform_data board_eeprom = { + .byte_len = 4096, + .page_size = 32, + .flags = AT24_FLAG_ADDR16, + .setup = pcl052_setup, // SP: added to replicate the am335x board file + .context = (void *)NULL, // SP: added to replicate the am335x board file +}; + +static struct imxi2c_platform_data pcl052_i2c_data = { + .bitrate = 100000, +}; + +static struct i2c_board_info pcl052_i2c2_board_info[] __initdata = { + { + I2C_BOARD_INFO("tda998x", 0x70), + }, + { + I2C_BOARD_INFO("tda99Xcec", 0x34), + }, +}; + +static struct mxc_nand_platform_data mvf_data __initdata = { + .width = 2, +}; + +static struct led_pwm mvf_led __initdata = { + .name = "mvf_leds", + .pwm_id = 1, + .active_low = 0, + .max_brightness = 6, + .pwm_period_ns = 100000000, +}; + +static struct led_pwm_platform_data mvf_led_data __initdata = { + .num_leds = 1, + .leds = &mvf_led, +}; + +#define USB_VBUS_ENABLE_PIN 134 +static void __init pcl052_init_usb(void) +{ + gpio_request_one(USB_VBUS_ENABLE_PIN, GPIOF_OUT_INIT_LOW, "VBUS_EN"); + msleep(2); + gpio_set_value(USB_VBUS_ENABLE_PIN, 1); + +#ifdef CONFIG_USB_EHCI_ARC + mvf_usb_dr_init(); + mvf_usb_dr2_init(); +#endif +} + +/*! + * Board specific initialization. + */ +static void __init pcl052_board_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(pcl052_pads, + ARRAY_SIZE(pcl052_pads)); + pcl052_init_uart(); + +#ifdef CONFIG_FEC + mvf_init_fec(fec_data); +#endif + +#ifdef CONFIG_FSL_L2_SWITCH + mvf_init_switch(switch_data); +#endif + + mvf_add_snvs_rtc(); + + mvf_add_sdhci_esdhc_imx(1, &pcl052_sd1_data); + + mvf_add_imx_i2c(2, &pcl052_i2c_data); + i2c_register_board_info(2, pcl052_i2c2_board_info, + ARRAY_SIZE(pcl052_i2c2_board_info)); + + + mvf_add_dspi(0, &pcl052_spi_data); + mvf_add_qspi(0, &pcl052_qspi_data); + spi_device_init(); + + mvfa5_add_dcu(0, &mvf_dcu_pdata); + + mxc_register_device(&pcl052_audio_device, &pcl052_audio_data); + mvfa5_add_sai(2, &mvf_sai_pdata); + +// mvf_add_wdt(0); + + pcl052_init_usb(); + + mvf_add_nand(&mvf_data); + +// mvf_add_mxc_pwm(0); +// mvf_add_pwm_leds(&mvf_led_data); + +} + +static void __init mvf_timer_init(void) +{ +#if 0 + struct clk *uart_clk; + uart_clk = clk_get_sys("mvf-uart.0", NULL); + early_console_setup(MVF_UART1_BASE_ADDR, uart_clk); +#endif + mvf_clocks_init(32768, 24000000, 0, 0); +} + +static struct sys_timer pcl052_timer = { + .init = mvf_timer_init, +}; + +/* + * initialize __mach_desc_ data structure. + */ +MACHINE_START(PCL052, "PHYTEC Cosmic Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .boot_params = MVF_PHYS_OFFSET + 0x100, + .fixup = fixup_mxc_board, + .map_io = mvf_map_io, + .init_irq = mvf_init_irq, + .init_machine = pcl052_board_init, + .timer = &pcl052_timer, +MACHINE_END diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c index 49645099cdc8..bab52e75b600 100644 --- a/arch/arm/mach-mvf/clock.c +++ b/arch/arm/mach-mvf/clock.c @@ -670,7 +670,7 @@ static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate) else return -EINVAL; -#ifndef CONFIG_MACH_PCM052 +#if !(defined CONFIG_MACH_PCM052 && defined CONFIG_MACH_PCL052) reg = __raw_readl(PLL3_480_USB1_BASE_ADDR); reg &= ~ANADIG_PLL_480_DIV_SELECT_MASK; reg |= div; @@ -1344,7 +1344,7 @@ static int _clk_dcu0_set_rate(struct clk *clk, unsigned long rate) div = (parent_rate + rate - 1) / rate; if (div == 0) div++; - if (((parent_rate / div) != rate) || (div > 8)) + if (((parent_rate / div) > rate) || (div > 8)) return -EINVAL; reg = __raw_readl(MXC_CCM_CSCDR3); @@ -2028,7 +2028,14 @@ int __init mvf_clocks_init(unsigned long ckil, unsigned long osc, clk_set_rate(&esdhc1_clk, 200000000); clk_set_parent(&dcu0_clk, &pll1_pfd2_452M); - clk_set_rate(&dcu0_clk, 90400000); + +#ifdef CONFIG_MACH_PCL052 + /* setting to 226MHz */ + clk_set_rate(&dcu0_clk, 227000000); +#else + /* setting to 150.667MHz */ + clk_set_rate(&dcu0_clk, 151000000); +#endif clk_set_parent(&sai2_clk, &pll4_audio_main_clk); clk_set_rate(&sai2_clk, 24567000); diff --git a/arch/arm/mach-mvf/devices-mvf.h b/arch/arm/mach-mvf/devices-mvf.h index f04630cd0a9b..c9b4929be5d9 100644 --- a/arch/arm/mach-mvf/devices-mvf.h +++ b/arch/arm/mach-mvf/devices-mvf.h @@ -52,7 +52,7 @@ extern const struct imx_mxc_nand_data mvf_nand_data __initconst; #define mvf_add_nand(pdata) \ imx_add_mxc_nand(&mvf_nand_data, pdata) -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) extern const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data[] __initconst; #define mvf_add_fsl_usb2_udc(id, pdata) \ imx_add_fsl_usb2_udc(&mvf_fsl_usb2_udc_data[id], pdata) @@ -71,7 +71,7 @@ extern const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data __initconst; #endif extern const struct imx_mxc_ehci_data mvf_mxc_ehci_hs_data[] __initconst; -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) #define mvf_add_fsl_ehci_hs(id, pdata) \ imx_add_fsl_ehci(&mvf_mxc_ehci_hs_data[id], pdata) #else @@ -85,7 +85,7 @@ extern const struct imx_fsl_usb2_otg_data mvf_fsl_usb2_otg_data __initconst; extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst; -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) #define mvf_add_fsl_usb2_ehci_otg_wakeup(id, pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_otg_wakeup_data[id], pdata) #define mvf_add_fsl_usb2_udc_wakeup(id, pdata) \ @@ -99,7 +99,7 @@ const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst; extern const struct imx_fsl_usb2_wakeup_data mvf_fsl_hs_wakeup_data[] __initconst; -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) #define mvf_add_fsl_usb2_hs_wakeup(id, pdata) \ imx_add_fsl_usb2_wakeup(&mvf_fsl_hs_wakeup_data[id], pdata) #else diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c index 5d7605421294..3dfebf4aba6f 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c @@ -50,7 +50,7 @@ const struct imx_fsl_usb2_udc_data imx6q_fsl_usb2_udc_data __initconst = #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_ARCH_MVF -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) const struct imx_fsl_usb2_udc_data mvf_fsl_usb2_udc_data[] __initconst = { mvf_fsl_usb2_udc_data_entry_single(MVF, 0), mvf_fsl_usb2_udc_data_entry_single(MVF, 1), diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c index 80c44f48393d..d66983335d00 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c @@ -35,7 +35,7 @@ const struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] __initconst = { #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_SOC_MVFA5 const struct imx_fsl_usb2_wakeup_data mvf_fsl_otg_wakeup_data[] __initconst = { -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) mvf_fsl_usb2_wakeup_data_entry_single(MVF, 0), mvf_fsl_usb2_wakeup_data_entry_single(MVF, 1), #else diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c index 928f3b792e0f..688aebb5858c 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c @@ -66,7 +66,7 @@ const struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] __initconst = { #endif /* ifdef CONFIG_SOC_IMX6Q */ #ifdef CONFIG_ARCH_MVF -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) const struct imx_mxc_ehci_data mvf_mxc_ehci_otg_data[] __initconst = { mvf_mxc_ehci_data_entry_single(MVF, 0), mvf_mxc_ehci_data_entry_single(MVF, 1), diff --git a/arch/arm/plat-mxc/include/mach/iomux-mvf.h b/arch/arm/plat-mxc/include/mach/iomux-mvf.h index 89eb0a87f21c..6b3c12171480 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mvf.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mvf.h @@ -87,6 +87,12 @@ typedef enum iomux_config { IOMUX_PAD(0x0048, 0x0048, 5, 0x0000, 0, MVF600_SDHC_PAD_CTRL) #define MVF600_PAD19_PTA29__SDHC1_DAT3 \ IOMUX_PAD(0x004C, 0x004C, 5, 0x0000, 0, MVF600_SDHC_PAD_CTRL) + +/*set PTB28 as GPIO for sdhc card detecting on PCL052*/ +#define MVF600_PAD98_PTB28__SDHC1_SW_CD \ + IOMUX_PAD(0x0188, 0x0188, 0, 0x0000, 0, \ + MVF600_GPIO_GENERAL_CTRL | PAD_CTL_IBE_ENABLE) + /*set PTD6 as GPIO for sdhc card detecting*/ #define MVF600_PAD85_PTD6__SDHC1_SW_CD \ IOMUX_PAD(0x0154, 0x0154, 0, 0x0000, 0, \ @@ -265,6 +271,8 @@ typedef enum iomux_config { /*DCU0*/ #define MVF600_PAD25_PTB3_LCD_ENABLE \ IOMUX_PAD(0x64, 0x64, 0, 0x0000, 0, MVF600_DCU_PAD_CTRL) +#define MVF600_PAD108_PTE3_LCD_ENABLE \ + IOMUX_PAD(0x01B0, 0x01B0, 0, 0x0000, 0, MVF600_DCU_PAD_CTRL) #define MVF600_PAD105_PTE0_DCU0_HSYNC \ IOMUX_PAD(0x01A4, 0x01A4, 1, 0x0000, 0, MVF600_DCU_PAD_CTRL) #define MVF600_PAD106_PTE1_DCU0_VSYNC \ diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h index 4edd8d91c57d..add1b0250483 100644 --- a/arch/arm/plat-mxc/include/mach/irqs.h +++ b/arch/arm/plat-mxc/include/mach/irqs.h @@ -74,7 +74,7 @@ #define MX5_IPU_IRQS 0 #endif -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) #define STMPE_IRQ_BASE (MXC_IPU_IRQ_START) #define STMPE_MAX_GPIOS 24 #define STMPE_IRQ_END (STMPE_IRQ_BASE + STMPE_MAX_GPIOS) diff --git a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h index d4364f1bdd8b..1aba4dc8d73e 100644 --- a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h +++ b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h @@ -35,6 +35,12 @@ struct dfb_chroma_key { __u8 blue_min; }; +#if (defined CONFIG_MACH_PCL052) +#define DCU_LCD_ENABLE_PIN 108 +#else +#define DCU_LCD_ENABLE_PIN 25 +#endif + #define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key) #define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8) diff --git a/arch/arm/plat-mxc/include/mach/mvf.h b/arch/arm/plat-mxc/include/mach/mvf.h index fb0e5eb69704..a7827137d538 100644 --- a/arch/arm/plat-mxc/include/mach/mvf.h +++ b/arch/arm/plat-mxc/include/mach/mvf.h @@ -555,7 +555,7 @@ #define MVF_INT_I2C2 105 #define MVF_INT_I2C3 106 -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) #define MVF_INT_USB0 107 #define MVF_INT_USB1 108 #else diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 15ea8529057b..d25545dd0d06 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -1122,3 +1122,4 @@ mvf_twr_vf500 MACH_MVFA5_TWR_VF500 MVFA5_TWR_VF500 4147 mvf_twr_vf600 MACH_MVFA5_TWR_VF600 MVFA5_TWR_VF600 4146 mvf_twr_vf700 MACH_MVFA5_TWR_VF700 MVFA5_TWR_VF700 2125 pcm052 MACH_PCM052 PCM052 4391 +pcl052 MACH_PCL052 PCL052 4693
\ No newline at end of file diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f056707d0986..5fa3206886df 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1674,7 +1674,7 @@ void usb_disconnect(struct usb_device **pdev) udev->devnum); #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) { fsl_platform_set_usb0_phy_dis(NULL, 0); fsl_platform_set_usb1_phy_dis(NULL, 0); @@ -2929,7 +2929,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } #ifdef MVF_USB_HOST_HACK if (udev->speed == USB_SPEED_HIGH && udev->level == 1) -#ifdef CONFIG_MACH_PCM052 +#if (defined CONFIG_MACH_PCM052 || defined CONFIG_MACH_PCL052) { fsl_platform_set_usb0_phy_dis(NULL, 1); fsl_platform_set_usb1_phy_dis(NULL, 1); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ca65437de427..fefbd85e97a0 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1961,6 +1961,13 @@ config FB_MVF_DCU ---help--- Framebuffer driver for the Faraday SoC DCU +config MVF_TDA_998X + depends on FB_MVF_DCU && I2C + tristate "TDA998X HDMI Support" + default n + ---help--- + TDA1998x HDMI Encoder support for MVF FB + config MVF_DCU_BLANKING_TEST bool "DCU framebuffer blanking support" depends on FB && ARCH_MVF && FB_MVF_DCU diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ed2fa59a726e..d420d828ee14 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -123,6 +123,7 @@ obj-$(CONFIG_FB_S3C) += s3c-fb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o obj-$(CONFIG_FB_MVF_DCU) += mvf_dcu.o +obj-$(CONFIG_MVF_TDA_998X) += mvf-tda1998x.o obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ diff --git a/drivers/video/mvf-tda1998x.c b/drivers/video/mvf-tda1998x.c new file mode 100644 index 000000000000..79f92250f215 --- /dev/null +++ b/drivers/video/mvf-tda1998x.c @@ -0,0 +1,221 @@ +/* + * File: dvf-tda1998x.c + * + * Description: This file contains condensed support for the TDA1998X HDMI codec required for display + * from the Freescale Vybrid DCU4 output. It assumes the i2c adapter access routines are available. + */ +// CNC TODO Header? + +//TODO Pare this down CNC +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <asm/mach-types.h> +#include <mach/mvf.h> +#include <mach/mvf-dcu-fb.h> + +//Required +#include <linux/i2c.h> +#include "mvf-tda1998x.h" + + +/* Global Data */ +static struct i2c_adapter *g_i2c_adapter = NULL; +static u8 g_u8_curr_page = 0; + +/* Static Functions */ +static void +set_page(uint16_t reg) +{ + if (REG2PAGE(reg) != g_u8_curr_page) { + uint8_t buf[2] = { REG_CURPAGE, REG2PAGE(reg) }; + struct i2c_msg msg = {TDA1998X_I2C_HDMI_SA, 0, sizeof(buf), buf}; + int ret; + + ret = i2c_transfer(g_i2c_adapter, &msg, 1); + if (ret < 0) + { + printk(KERN_ERR "Error %d writing to REG_CURPAGE\n", ret); + } + else + { + g_u8_curr_page = REG2PAGE(reg); + } + } +} + +static void +reg_write(uint16_t reg, uint8_t val) +{ + uint8_t buf[2] = {REG2ADDR(reg), val}; + int ret; + struct i2c_msg msg = {TDA1998X_I2C_HDMI_SA, 0, sizeof(buf), buf}; + + set_page(reg); + + ret = i2c_transfer(g_i2c_adapter, &msg, 1); + if (ret < 0) + printk(KERN_ERR "Error %d writing to 0x%x\n", ret, reg); +} + +static uint8_t +reg_read(uint16_t reg) +{ + uint8_t u8addr = REG2ADDR(reg); + uint8_t u8ret = 0; + int ret; + struct i2c_msg rgMsg[] = {/* slaveaddr, flags, len, buf */ + {TDA1998X_I2C_HDMI_SA, 0, sizeof(u8addr), &u8addr}, + {TDA1998X_I2C_HDMI_SA, I2C_M_RD, sizeof(u8ret), &u8ret}}; + + /* Change the register page to the one we want */ + set_page(reg); + + ret = i2c_transfer(g_i2c_adapter, rgMsg, 2); + if (ret < 0) + { + printk(KERN_ERR "<%s> Error %d reading from 0x%x\n", __func__, ret, reg); + return 0; + } + else + { + return u8ret; + } +} + +static void +reg_set(uint16_t reg, uint8_t val) +{ + reg_write(reg, reg_read(reg) | val); +} + +static void +reg_clear(uint16_t reg, uint8_t val) +{ + reg_write(reg, reg_read(reg) & ~val); +} + +static bool +tda1998x_init_encoder(void) +{ + int ret; + uint8_t rgBuf[][2] = { /* Register Address, Register Value */ + {REG_CEC_ENAMODS, (CEC_ENAMODS_EN_RXSENS + | CEC_ENAMODS_EN_HDMI)}, + {REG_CEC_FRO_IM_CLK_CTRL, (CEC_FRO_IM_CLK_CTRL_GHOST_DIS + | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL)}, + {REG_CEC_ENAMODS, (CEC_ENAMODS_EN_CEC_CLK + | CEC_ENAMODS_EN_RXSENS + | CEC_ENAMODS_EN_HDMI + | CEC_ENAMODS_EN_CEC)} + }; + struct i2c_msg rgMsg[] = + { + /* slaveaddr,flags,len,buf */ + {TDA1998X_I2C_CEC_SA, 0, sizeof(rgBuf[0]), rgBuf[0]}, + {TDA1998X_I2C_CEC_SA, 0, sizeof(rgBuf[1]), rgBuf[1]}, + {TDA1998X_I2C_CEC_SA, 0, sizeof(rgBuf[2]), rgBuf[2]}, + }; + + /* Initialize the HDMI interface, otherwise the HDMI I2C I/F is off */ + ret = i2c_transfer(g_i2c_adapter, &rgMsg[0], 1); + if (ret < 0) + goto ret_error; + + /* + * Begin Reset Sequence + */ + /* reset audio and i2c master: */ + reg_set(REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); + msleep(50); + reg_clear(REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); + msleep(50); + + /* reset transmitter */ + reg_set(REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); + reg_clear(REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); + + /* PLL registers common configuration */ + reg_write(REG_PLL_SERIAL_1, 0x00); + reg_write(REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1)); + reg_write(REG_PLL_SERIAL_3, 0x00); + reg_write(REG_SERIALIZER, 0x00); + reg_write(REG_BUFFER_OUT, 0x00); + reg_write(REG_PLL_SCG1, 0x00); + reg_write(REG_AUDIO_DIV, 0x03); + reg_write(REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); + reg_write(REG_PLL_SCGN1, 0xfa); + reg_write(REG_PLL_SCGN2, 0x00); + reg_write(REG_PLL_SCGR1, 0x5b); + reg_write(REG_PLL_SCGR2, 0x00); + reg_write(REG_PLL_SCG2, 0x10); + /* + * End Reset Sequence + */ + + /* Enable DDC */ + reg_write(REG_DDC_DISABLE, 0x00); + + /* Set clock on DDC channel */ + reg_write(REG_TX3, 39); + + /* Initialize CEC Interface */ + ret = i2c_transfer(g_i2c_adapter, &rgMsg[1], 1); + if (ret < 0) + goto ret_error; + + /* Enable DPMS */ + /* enable video ports */ + reg_write(REG_ENA_VP_0, 0xff); + reg_write(REG_ENA_VP_1, 0xff); + reg_write(REG_ENA_VP_2, 0xff); + /* set muxing after enabling ports: */ + /* Set to RGB 3x 8-bit per 7.2.3 mappings */ + reg_write(REG_VIP_CNTRL_0, 0x23); + reg_write(REG_VIP_CNTRL_1, 0x01); + reg_write(REG_VIP_CNTRL_2, 0x45); + + /* Enable HDMI Encoding */ + ret = i2c_transfer(g_i2c_adapter, &rgMsg[2], 1); + if (ret < 0) + goto ret_error; + + reg_write(REG_TX33, TX33_HDMI); + reg_write(REG_TBG_CNTRL_1, 0x7c); + + return true; + +ret_error: + printk(KERN_ERR "<%s> HDMI I2C I/F failed (%d)\n", __func__, ret); + return false; +} /* tda1998x_init_encoder */ + +/* Public Functions */ +bool init_tda19988(void) +{ + /* Get the handle to the i2c channel */ + g_i2c_adapter = i2c_get_adapter(TDA1998X_I2C_BUS); + if (g_i2c_adapter == NULL) + { + printk(KERN_ERR "<%s> CEC I2C Adapter not found\n", __func__); + return false; + } + return tda1998x_init_encoder(); +} + diff --git a/drivers/video/mvf-tda1998x.h b/drivers/video/mvf-tda1998x.h new file mode 100644 index 000000000000..5a1ebf397c39 --- /dev/null +++ b/drivers/video/mvf-tda1998x.h @@ -0,0 +1,268 @@ +/* + * File: dvf-tda1998x.h + * + * Description: This file contains condensed TDA register defines required to support the + * TDA1998X HDMI codec required for display from the Freescale Vybrid DCU4 output. + * + */ +//CNC TODO: Which header for this? +#ifndef _MVF_TDA1998X_H_ +#define _MVF_TDA1998X_H_ + +/* Public Functions */ +bool init_tda19988(void); + +/* Platform Settings */ +#define EDID_LENGTH 0x80 +#define TDA1998X_I2C_BUS 2 +#define TDA1998X_I2C_CEC_SA 0x34 +#define TDA1998X_I2C_HDMI_SA 0x70 + +/* Device versions: */ +#define TDA9989N2 0x0101 +#define TDA19989 0x0201 +#define TDA19989N2 0x0202 +#define TDA19988 0x0301 + +/* The TDA9988 series of devices use a paged register scheme.. to simplify + * things we encode the page # in upper bits of the register #. To read/ + * write a given register, we need to make sure CURPAGE register is set + * appropriately. Which implies reads/writes are not atomic. Fun! + */ + +#define REG(page, addr) (((page) << 8) | (addr)) +#define REG2ADDR(reg) ((reg) & 0xff) +#define REG2PAGE(reg) (((reg) >> 8) & 0xff) + +#define REG_CURPAGE 0xff /* write */ + +/* Page 00h: General Control */ +#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ +#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ +# define MAIN_CNTRL0_SR (1 << 0) +# define MAIN_CNTRL0_DECS (1 << 1) +# define MAIN_CNTRL0_DEHS (1 << 2) +# define MAIN_CNTRL0_CECS (1 << 3) +# define MAIN_CNTRL0_CEHS (1 << 4) +# define MAIN_CNTRL0_SCALER (1 << 7) +#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ +#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ +# define SOFTRESET_AUDIO (1 << 0) +# define SOFTRESET_I2C_MASTER (1 << 1) +#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ +#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ +#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */ +# define I2C_MASTER_DIS_MM (1 << 0) +# define I2C_MASTER_DIS_FILT (1 << 1) +# define I2C_MASTER_APP_STRT_LAT (1 << 2) +#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ +#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ +#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ +# define INT_FLAGS_2_EDID_BLK_RD (1 << 1) +#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ +#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ +#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ +#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */ +#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ +# define VIP_CNTRL_0_MIRR_A (1 << 7) +# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4) +# define VIP_CNTRL_0_MIRR_B (1 << 3) +# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0) +#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */ +# define VIP_CNTRL_1_MIRR_C (1 << 7) +# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4) +# define VIP_CNTRL_1_MIRR_D (1 << 3) +# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0) +#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */ +# define VIP_CNTRL_2_MIRR_E (1 << 7) +# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4) +# define VIP_CNTRL_2_MIRR_F (1 << 3) +# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0) +#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */ +# define VIP_CNTRL_3_X_TGL (1 << 0) +# define VIP_CNTRL_3_H_TGL (1 << 1) +# define VIP_CNTRL_3_V_TGL (1 << 2) +# define VIP_CNTRL_3_EMB (1 << 3) +# define VIP_CNTRL_3_SYNC_DE (1 << 4) +# define VIP_CNTRL_3_SYNC_HS (1 << 5) +# define VIP_CNTRL_3_DE_INT (1 << 6) +# define VIP_CNTRL_3_EDGE (1 << 7) +#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */ +# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0) +# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2) +# define VIP_CNTRL_4_CCIR656 (1 << 4) +# define VIP_CNTRL_4_656_ALT (1 << 5) +# define VIP_CNTRL_4_TST_656 (1 << 6) +# define VIP_CNTRL_4_TST_PAT (1 << 7) +#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */ +# define VIP_CNTRL_5_CKCASE (1 << 0) +# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1) + +#define REG_MUX_AP REG(0x00, 0x26) +# define MUX_AP_SELECT_I2S (0x64) +#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */ +# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0) +# define MAT_CONTRL_MAT_BP (1 << 2) +#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */ +#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */ +#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */ +#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */ +#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */ +#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */ +#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */ +#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */ +#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */ +#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */ +#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */ +#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */ +#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */ +#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */ +#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */ +#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */ +#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */ +#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */ +#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */ +#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */ +#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */ +#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */ +#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */ +#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */ +#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */ +#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */ +#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */ +#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */ +#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */ +#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */ +#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */ +#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */ +#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */ +#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */ +# define TBG_CNTRL_0_FRAME_DIS (1 << 5) +# define TBG_CNTRL_0_SYNC_MTHD (1 << 6) +# define TBG_CNTRL_0_SYNC_ONCE (1 << 7) +#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */ +# define TBG_CNTRL_1_VH_TGL_0 (1 << 0) +# define TBG_CNTRL_1_VH_TGL_1 (1 << 1) +# define TBG_CNTRL_1_VH_TGL_2 (1 << 2) +# define TBG_CNTRL_1_VHX_EXT_DE (1 << 3) +# define TBG_CNTRL_1_VHX_EXT_HS (1 << 4) +# define TBG_CNTRL_1_VHX_EXT_VS (1 << 5) +# define TBG_CNTRL_1_DWIN_DIS (1 << 6) +#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */ +#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */ +# define HVF_CNTRL_0_SM (1 << 7) +# define HVF_CNTRL_0_RWB (1 << 6) +# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2) +# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0) +#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */ +# define HVF_CNTRL_1_FOR (1 << 0) +# define HVF_CNTRL_1_YUVBLK (1 << 1) +# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2) +# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4) +# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6) +#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */ +#define REG_I2S_FORMAT REG(0x00, 0xfc) +#define REG_AIP_CLKSEL REG(0x00, 0xfd) +# define SEL_AIP_I2S (1 << 3) /* I2S Clk */ + +/* Page 02h: PLL settings */ +#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */ +# define PLL_SERIAL_1_SRL_FDN (1 << 0) +# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1) +# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6) +#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */ +# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0) +# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) +#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */ +# define PLL_SERIAL_3_SRL_CCIR (1 << 0) +# define PLL_SERIAL_3_SRL_DE (1 << 2) +# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4) +#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */ +#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */ +#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */ +#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */ +#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */ +#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */ +#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */ +#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */ +#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */ +#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */ +# define SEL_CLK_SEL_CLK1 (1 << 0) +# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1) +# define SEL_CLK_ENA_SC_CLK (1 << 3) +#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */ + + +/* Page 09h: EDID Control */ +#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */ +/* next 127 successive registers are the EDID block */ +#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */ +#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */ +#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */ +#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */ +#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */ + +/* Page 10h: information frames and packets */ +#define REG_AVI_IF REG(0x10, 0x40) /* AVI Infoframe packet */ +#define REG_AUDIO_IF REG(0x10, 0x80) /* AVI Infoframe packet */ + +/* Page 11h: audio settings and content info packets */ +#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */ +# define AIP_CNTRL_0_RST_FIFO (1 << 0) +# define AIP_CNTRL_0_SWAP (1 << 1) +# define AIP_CNTRL_0_LAYOUT (1 << 2) +# define AIP_CNTRL_0_ACR_MAN (1 << 5) +# define AIP_CNTRL_0_RST_CTS (1 << 6) +#define REG_ACR_CTS_0 REG(0x11, 0x05) +#define REG_ACR_CTS_1 REG(0x11, 0x06) +#define REG_ACR_CTS_2 REG(0x11, 0x07) +#define REG_ACR_N_0 REG(0x11, 0x08) +#define REG_ACR_N_1 REG(0x11, 0x09) +#define REG_ACR_N_2 REG(0x11, 0x0a) +#define REG_GC_AVMUTE REG(0x11, 0x0b) +# define GC_AVMUTE_CLRMUTE (1 << 0) +# define GC_AVMUTE_SETMUTE (1 << 1) +#define REG_CTS_N REG(0x11, 0x0c) +#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */ +# define ENC_CNTRL_RST_ENC (1 << 0) +# define ENC_CNTRL_RST_SEL (1 << 1) +# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2) +#define REG_DIP_FLAGS REG(0x11, 0x0e) +# define DIP_FLAGS_ACR (1 << 0) +#define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */ +#define DIP_IF_FLAGS_IF1 (1 << 1) +#define DIP_IF_FLAGS_IF2 (1 << 2) +#define DIP_IF_FLAGS_IF3 (1 << 3) +#define DIP_IF_FLAGS_IF4 (1 << 4) +#define DIP_IF_FLAGS_IF5 (1 << 5) + +/* Page 12h: HDCP and OTP */ +#define REG_TX3 REG(0x12, 0x9a) /* read/write */ +#define REG_TX33 REG(0x12, 0xb8) /* read/write */ +# define TX33_HDMI (1 << 1) + + +/* Page 13h: Gamut related metadata packets */ + +/* CEC registers: (not paged) + */ +#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */ +# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) +# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6) +# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) +# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0) +#define REG_CEC_RXSHPDLEV 0xfe /* read */ +# define CEC_RXSHPDLEV_RXSENS (1 << 0) +# define CEC_RXSHPDLEV_HPD (1 << 1) + +#define REG_CEC_ENAMODS 0xff /* read/write */ +# define CEC_ENAMODS_EN_CEC_CLK (1 << 7) +# define CEC_ENAMODS_DIS_FRO (1 << 6) +# define CEC_ENAMODS_DIS_CCLK (1 << 5) +# define CEC_ENAMODS_EN_WD (1 << 4) +# define CEC_ENAMODS_CEC_INV (1 << 3) +# define CEC_ENAMODS_EN_RXSENS (1 << 2) +# define CEC_ENAMODS_EN_HDMI (1 << 1) +# define CEC_ENAMODS_EN_CEC (1 << 0) + +#endif /*_MVF_TDA1998X_H_*/ diff --git a/drivers/video/mvf_dcu.c b/drivers/video/mvf_dcu.c index 71c271278bce..34661beb5b8a 100644 --- a/drivers/video/mvf_dcu.c +++ b/drivers/video/mvf_dcu.c @@ -32,10 +32,12 @@ #include <asm/mach-types.h> #include <mach/mvf.h> #include <mach/mvf-dcu-fb.h> +#include "mvf-tda1998x.h" - +#define DCU_MASTER_CLOCK_FREQ 226000000 #define DRIVER_NAME "mvf-dcu" + static struct fb_videomode __devinitdata mvf_dcu_default_mode = { .xres = 800, .yres = 480, @@ -52,19 +54,6 @@ static struct fb_videomode __devinitdata mvf_dcu_default_mode = { static struct fb_videomode __devinitdata mvf_dcu_mode_db[] = { { - .name = "480x272", - .xres = 480, - .yres = 272, - .left_margin = 2, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 41, - .vsync_len = 2, - .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - .vmode = FB_VMODE_NONINTERLACED, - }, - { .name = "pm070wl4", .xres = 800, .yres = 480, @@ -77,6 +66,41 @@ static struct fb_videomode __devinitdata mvf_dcu_mode_db[] = { .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED, +#if (defined CONFIG_MACH_PCL052) + },{ + /* HDMI */ + .name = "640x480p_hdmipc", + .pixclock = 25111, /* From TDA Doc */ + .xres = 640, + .yres = 480, + .left_margin = 1, + .right_margin = 1, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 158, + .vsync_len = 36, + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | + FB_SYNC_HOR_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + },{ + /* HDMI 480p */ /* NOTE: Sync isn't valid on this config */ + .name = "720x480p", + .pixclock = 28250, /* VESA is 27.027MHz, DCU docs say 28.250, actual is 28.282MHz*/ + .xres = 720, + .yres = 480, + /* 178 total for 31500Hz hsync */ + .left_margin = 96, /*hbp*/ + .right_margin = 9, /*hfp*/ + .hsync_len = 73, /*hsw*/ + /* 45 total for 59.98 Hz vsync */ + .upper_margin = 1, /*vbp*/ + .lower_margin = 1, /*vfp*/ + .vsync_len = 43, /*vsw*/ + + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT + | FB_SYNC_HOR_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, +#endif /* CONFIG_MACH_PCL052 */ }, }; @@ -395,6 +419,7 @@ static void update_lcdc(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; struct mfb_info *mfbi = info->par; struct mvf_dcu_fb_data *dcu = mfbi->parent; + uint8_t div_val = 0; if (mfbi->type == DCU_TYPE_OFF) { mvf_dcu_disable_panel(info); @@ -429,10 +454,31 @@ static void update_lcdc(struct fb_info *info) DCU_VSYN_PARA_FP(var->lower_margin), dcu->base + DCU_VSYN_PARA); + + /* Setup Default Colorbars RGB format */ + writel(0xFFFF0000, dcu->base + DCU_COLBAR_1); /* red */ + writel(0xFF00FF00, dcu->base + DCU_COLBAR_2); /* green */ + writel(0xFF0000FF, dcu->base + DCU_COLBAR_3); /* blue */ + writel(0xFF00FFFF, dcu->base + DCU_COLBAR_4); /* cyan */ + writel(0xFFFF00FF, dcu->base + DCU_COLBAR_5); /* magenta */ + writel(0xFFFFFF00, dcu->base + DCU_COLBAR_6); /* yellow */ + writel(0xFF000000, dcu->base + DCU_COLBAR_7); /* black */ + writel(0xFFFFFFFF, dcu->base + DCU_COLBAR_8); /* white */ writel(DCU_MODE_BLEND_ITER(3) | DCU_MODE_RASTER_EN(1), dcu->base + DCU_DCU_MODE); - writel(2, dcu->base + DCU_DIV_RATIO); + /* PCLK output calculation */ + if ((var->pixclock == 0) || (DCU_MASTER_CLOCK_FREQ / (var->pixclock<<12) > 0x100)) + { + /* default value */ + div_val = 0x10; + } + else + { + div_val = DCU_MASTER_CLOCK_FREQ / var->pixclock; + } + + writel(div_val, dcu->base + DCU_DIV_RATIO); writel(DCU_SYN_POL_INV_PXCK(0) | DCU_SYN_POL_NEG(0) | DCU_SYN_POL_INV_VS(1) | DCU_SYN_POL_INV_HS(1), @@ -636,9 +682,9 @@ static int mvf_dcu_pan_display(struct fb_var_screeninfo *var, static int mvf_dcu_blank(int blank_mode, struct fb_info *info) { +#ifdef CONFIG_MVF_DCU_BLANKING_TEST struct mfb_info *mfbi = info->par; -#ifdef CONFIG_MVF_DCU_BLANKING_TEST mfbi->blank = blank_mode; switch (blank_mode) { @@ -952,7 +998,8 @@ static int mvf_dcu_resume(struct platform_device *pdev) #else #define mvf_dcu_suspend NULL #define mvf_dcu_resume NULL -#endif +#endif /* CONFIG_PM */ + static int __devinit mvf_dcu_probe(struct platform_device *pdev) { @@ -1043,7 +1090,9 @@ static int __devinit mvf_dcu_probe(struct platform_device *pdev) goto failed_install_fb; } } - +#if (defined CONFIG_MVF_TDA_998X) + init_tda19988(); +#endif /* CONFIG_MVF_TDA_998X */ dev_set_drvdata(&pdev->dev, dcu); return 0; |