diff options
author | Xinyu Chen <b03824@freescale.com> | 2011-12-06 17:19:12 +0800 |
---|---|---|
committer | Xinyu Chen <b03824@freescale.com> | 2011-12-06 17:19:12 +0800 |
commit | 4eb99c5e5be396410fa62178e94b8fca62abf7d5 (patch) | |
tree | 17670f1e0ffb20a1aaa48a72a7312c1ee4a036cb | |
parent | 73c089abb36b98866bbfbaec0f9a2dafbfe73ed5 (diff) | |
parent | b92265a274f0fec27567e86b995424ef8823499f (diff) |
Merge remote branch 'fsl-linux-sdk/imx_2.6.38' into imx_2.6.38_android
Conflicts:
arch/arm/mach-mx6/system.c
drivers/media/video/mxc/capture/mxc_v4l2_capture.c
80 files changed, 5481 insertions, 755 deletions
diff --git a/arch/arm/configs/imx6_android_defconfig b/arch/arm/configs/imx6_android_defconfig index 8d353c494ddb..e2e8c5489b4d 100644 --- a/arch/arm/configs/imx6_android_defconfig +++ b/arch/arm/configs/imx6_android_defconfig @@ -1680,7 +1680,6 @@ CONFIG_VIDEO_MXC_IPU_CAMERA=y # CONFIG_MXC_CAMERA_OV3640 is not set CONFIG_MXC_CAMERA_OV5642=y # CONFIG_MXC_CAMERA_OV5640_MIPI is not set -# CONFIG_MXC_CAMERA_OV5642 is not set CONFIG_MXC_IPU_PRP_VF_SDC=y CONFIG_MXC_IPU_PRP_ENC=y CONFIG_MXC_IPU_CSI_ENC=y diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig index 06ee86f5e0b7..0f2c0e802856 100644 --- a/arch/arm/configs/imx6_defconfig +++ b/arch/arm/configs/imx6_defconfig @@ -304,6 +304,7 @@ CONFIG_ARCH_MX6Q=y CONFIG_SOC_IMX6Q=y CONFIG_MACH_MX6Q_ARM2=y CONFIG_MACH_MX6Q_SABRELITE=y +CONFIG_MACH_MX6Q_SABREAUTO=y # # MX6 Options: @@ -768,7 +769,8 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +CONFIG_MXS_PERFMON=m CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -815,7 +817,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DH is not set # CONFIG_SCSI_OSD_INITIATOR is not set -CONFIG_ATA=m +CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y # CONFIG_SATA_PMP is not set @@ -823,7 +825,7 @@ CONFIG_ATA_VERBOSE_ERROR=y # # Controllers with non-SFF native interface # -CONFIG_SATA_AHCI_PLATFORM=m +CONFIG_SATA_AHCI_PLATFORM=y CONFIG_ATA_SFF=y # diff --git a/arch/arm/configs/imx6_updater_defconfig b/arch/arm/configs/imx6_updater_defconfig index f9ab9462dacc..d8d9eae1b8b9 100644 --- a/arch/arm/configs/imx6_updater_defconfig +++ b/arch/arm/configs/imx6_updater_defconfig @@ -310,6 +310,7 @@ CONFIG_ARCH_MX6Q=y CONFIG_SOC_IMX6Q=y CONFIG_MACH_MX6Q_ARM2=y CONFIG_MACH_MX6Q_SABRELITE=y +CONFIG_MACH_MX6Q_SABREAUTO=y # # MX6 Options: diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index 6a1a99dd7d17..e28be210c654 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -54,6 +54,7 @@ config MACH_MX6Q_ARM2 select IMX_HAVE_PLATFORM_IMX_MIPI_DSI select IMX_HAVE_PLATFORM_FLEXCAN select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2 + select IMX_HAVE_PLATFORM_PERFMON help Include support for i.MX 6Quad Armadillo2 platform. This includes specific configurations for the board and its peripherals. @@ -85,10 +86,47 @@ config MACH_MX6Q_SABRELITE select IMX_HAVE_PLATFORM_IMX_PM select IMX_HAVE_PLATFORM_MXC_HDMI select IMX_HAVE_PLATFORM_IMX_ASRC + select IMX_HAVE_PLATFORM_FLEXCAN help Include support for i.MX 6Quad SABRE Lite platform. This includes specific configurations for the board and its peripherals. +config MACH_MX6Q_SABREAUTO + bool "Support i.MX 6Quad SABRE Auto platform" + select ARCH_MX6Q + select SOC_IMX6Q + 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_SPI_IMX + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_VIV_GPU + select IMX_HAVE_PLATFORM_IMX_VPU + select IMX_HAVE_PLATFORM_IMX_DVFS + select IMX_HAVE_PLATFORM_IMX_ESAI + select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL + 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_IMX_VIIM + 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_IMX_SPDIF + select IMX_HAVE_PLATFORM_IMX_MIPI_DSI + select IMX_HAVE_PLATFORM_FLEXCAN + select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2 + help + Include support for i.MX 6Quad SABRE Auto platform. This includes specific + configurations for the board and its peripherals. + comment "MX6 Options:" endif diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile index d0fe1f4e3410..bd55b5ba9c3f 100644 --- a/arch/arm/mach-mx6/Makefile +++ b/arch/arm/mach-mx6/Makefile @@ -8,5 +8,6 @@ obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o obj-$(CONFIG_ARCH_MX6) += clock.o mx6q_suspend.o obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o obj-$(CONFIG_MACH_MX6Q_SABRELITE) += board-mx6q_sabrelite.o +obj-$(CONFIG_MACH_MX6Q_SABREAUTO) += board-mx6q_sabreauto.o obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index 2b93fb95dd15..218a202bd75f 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -106,11 +106,13 @@ #define MX6Q_SMD_CSI0_RST IMX_GPIO_NR(4, 5) #define MX6Q_SMD_CSI0_PWN IMX_GPIO_NR(5, 23) +#define BMCR_PDOWN 0x0800 /* PHY Powerdown */ + void __init early_console_setup(unsigned long base, struct clk *clk); static struct clk *sata_clk; static int esai_record; static int spdif_en; -static int mipi_sensor; +static int flexcan_en; extern struct regulator *(*get_cpu_regulator)(void); extern void (*put_cpu_regulator)(void); @@ -256,23 +258,6 @@ static iomux_v3_cfg_t mx6q_arm2_pads[] = { MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, - /* ipu1 csi0 */ - MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, - MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, - MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, - MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, - MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, - MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, - MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, - MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, - MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, - MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, - MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, - /* camera reset */ - MX6Q_PAD_GPIO_19__GPIO_4_5, - /* camera powerdown */ - MX6Q_PAD_CSI0_DAT5__GPIO_5_23, - MX6Q_PAD_EIM_D24__GPIO_3_24, /* UART2 */ @@ -329,6 +314,26 @@ static iomux_v3_cfg_t mx6q_arm2_esai_record_pads[] = { MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR, }; +static iomux_v3_cfg_t mx6q_arm2_csi0_sensor_pads[] = { + MX6Q_PAD_GPIO_0__CCM_CLKO, + /* ipu1 csi0 */ + MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, + MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, + MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, + MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, + MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, + MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, + MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, + MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, + MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, + MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, + MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, + /* camera reset */ + MX6Q_PAD_GPIO_19__GPIO_4_5, + /* camera powerdown */ + MX6Q_PAD_CSI0_DAT5__GPIO_5_23, +}; + static iomux_v3_cfg_t mx6q_arm2_mipi_sensor_pads[] = { MX6Q_PAD_CSI0_MCLK__CCM_CLKO, }; @@ -421,6 +426,7 @@ static const struct esdhc_platform_data mx6q_arm2_sd3_data __initconst = { .wp_gpio = MX6Q_ARM2_SD3_WP, .support_18v = 1, .support_8bit = 1, + .keep_power_at_suspend = 1, .delay_line = 0, .platform_pad_change = plt_sd3_pad_change, }; @@ -429,6 +435,7 @@ static const struct esdhc_platform_data mx6q_arm2_sd3_data __initconst = { static const struct esdhc_platform_data mx6q_arm2_sd4_data __initconst = { .always_present = 1, .support_8bit = 1, + .keep_power_at_suspend = 1, .platform_pad_change = plt_sd4_pad_change, }; @@ -475,14 +482,15 @@ static const struct anatop_thermal_platform_data }; static const struct imxuart_platform_data mx6q_uart1_data __initconst = { - .flags = IMXUART_HAVE_RTSCTS | IMXUART_USE_DCEDTE, + .flags = IMXUART_HAVE_RTSCTS | IMXUART_USE_DCEDTE | IMXUART_SDMA, + .dma_req_rx = MX6Q_DMA_REQ_UART2_RX, + .dma_req_tx = MX6Q_DMA_REQ_UART2_TX, }; static inline void mx6q_arm2_init_uart(void) { imx6q_add_imx_uart(0, NULL); imx6q_add_imx_uart(1, &mx6q_uart1_data); - imx6q_add_imx_uart(3, NULL); } static int mx6q_arm2_fec_phy_init(struct phy_device *phydev) @@ -505,6 +513,10 @@ static int mx6q_arm2_fec_phy_init(struct phy_device *phydev) val |= 0x0100; phy_write(phydev, 0x1e, val); + /*check phy power*/ + val = phy_read(phydev, 0x0); + if (val & BMCR_PDOWN) + phy_write(phydev, 0x0, (val & ~BMCR_PDOWN)); return 0; } @@ -659,19 +671,58 @@ static struct fsl_mxc_dvi_platform_data sabr_ddc_dvi_data = { .update = ddc_dvi_update, }; +static void mx6q_csi0_io_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_csi0_sensor_pads, + ARRAY_SIZE(mx6q_arm2_csi0_sensor_pads)); + + /* Camera reset */ + gpio_request(MX6Q_SMD_CSI0_RST, "cam-reset"); + gpio_direction_output(MX6Q_SMD_CSI0_RST, 1); + + /* Camera power down */ + gpio_request(MX6Q_SMD_CSI0_PWN, "cam-pwdn"); + gpio_direction_output(MX6Q_SMD_CSI0_PWN, 1); + msleep(1); + gpio_set_value(MX6Q_SMD_CSI0_PWN, 0); + + /* For MX6Q GPR1 bit19 and bit20 meaning: + * Bit19: 0 - Enable mipi to IPU1 CSI0 + * virtual channel is fixed to 0 + * 1 - Enable parallel interface to IPU1 CSI0 + * Bit20: 0 - Enable mipi to IPU2 CSI1 + * virtual channel is fixed to 3 + * 1 - Enable parallel interface to IPU2 CSI1 + * IPU1 CSI1 directly connect to mipi csi2, + * virtual channel is fixed to 1 + * IPU2 CSI0 directly connect to mipi csi2, + * virtual channel is fixed to 2 + */ + mxc_iomux_set_gpr_register(1, 19, 1, 1); +} + static struct fsl_mxc_camera_platform_data camera_data = { .analog_regulator = "DA9052_LDO7", .core_regulator = "DA9052_LDO9", .mclk = 24000000, .csi = 0, + .io_init = mx6q_csi0_io_init, }; +static void mx6q_mipi_sensor_io_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_mipi_sensor_pads, + ARRAY_SIZE(mx6q_arm2_mipi_sensor_pads)); + + mxc_iomux_set_gpr_register(1, 19, 1, 0); +} + static struct fsl_mxc_camera_platform_data ov5640_mipi_data = { .mclk = 24000000, .csi = 0, + .io_init = mx6q_mipi_sensor_io_init, }; - static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { { I2C_BOARD_INFO("cs42888", 0x48), @@ -768,7 +819,7 @@ static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = { static int mx6q_arm2_sata_init(struct device *dev, void __iomem *addr) { u32 tmpdata; - int ret = 0; + int ret = 0, iterations = 20; struct clk *clk; /* Enable SATA PWR CTRL_0 of MAX7310 */ @@ -819,12 +870,29 @@ static int mx6q_arm2_sata_init(struct device *dev, void __iomem *addr) sata_init(addr, tmpdata); + /* Release resources when there is no device on the port */ + do { + if ((readl(addr + PORT_SATA_SR) & 0xF) == 0) + msleep(25); + else + break; + + if (iterations == 0) { + dev_info(dev, "NO sata disk.\n"); + ret = -ENODEV; + goto release_sata_clk; + } + } while (iterations-- > 0); + return ret; release_sata_clk: clk_disable(sata_clk); put_sata_clk: clk_put(sata_clk); + /* Disable SATA PWR CTRL_0 of MAX7310 */ + gpio_request(MX6Q_ARM2_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); + gpio_direction_output(MX6Q_ARM2_MAX7310_1_BASE_ADDR, 0); return ret; } @@ -1352,34 +1420,21 @@ static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, set_cpu_voltage = mx6_arm2_set_cpu_voltage; } -static int __init early_enable_mipi_sensor(char *p) +static int __init early_enable_spdif(char *p) { - mipi_sensor = 1; + spdif_en = 1; return 0; } -early_param("mipi_sensor", early_enable_mipi_sensor); -static inline void __init mx6q_csi0_io_init(void) -{ - /* Camera reset */ - gpio_request(MX6Q_SMD_CSI0_RST, "cam-reset"); - gpio_direction_output(MX6Q_SMD_CSI0_RST, 1); - - /* Camera power down */ - gpio_request(MX6Q_SMD_CSI0_PWN, "cam-pwdn"); - gpio_direction_output(MX6Q_SMD_CSI0_PWN, 1); - msleep(1); - gpio_set_value(MX6Q_SMD_CSI0_PWN, 0); - mxc_iomux_set_gpr_register(1, 19, 1, 1); -} +early_param("spdif", early_enable_spdif); -static int __init early_enable_spdif(char *p) +static int __init early_enable_can(char *p) { - spdif_en = 1; + flexcan_en = 1; return 0; } -early_param("spdif", early_enable_spdif); +early_param("flexcan", early_enable_can); static int spdif_clk_set_rate(struct clk *clk, unsigned long rate) { @@ -1436,14 +1491,11 @@ static void __init mx6_board_init(void) } else { mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_i2c3_pads, ARRAY_SIZE(mx6q_arm2_i2c3_pads)); - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_can_pads, - ARRAY_SIZE(mx6q_arm2_can_pads)); + if (flexcan_en) + mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_can_pads, + ARRAY_SIZE(mx6q_arm2_can_pads)); } - if (mipi_sensor) - mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_mipi_sensor_pads, - ARRAY_SIZE(mx6q_arm2_mipi_sensor_pads)); - gp_reg_id = arm2_dvfscore_data.reg_id; mx6q_arm2_init_uart(); imx6q_add_mipi_csi2(&mipi_csi2_pdata); @@ -1499,9 +1551,6 @@ static void __init mx6_board_init(void) imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); imx6q_add_asrc(&imx_asrc_data); - if (!mipi_sensor) - mx6q_csi0_io_init(); - /* DISP0 Detect */ /* gpio_request(MX6Q_ARM2_DISP0_DET_INT, "disp0-detect"); */ /* gpio_direction_input(MX6Q_ARM2_DISP0_DET_INT); */ @@ -1541,7 +1590,7 @@ static void __init mx6_board_init(void) imx6q_add_spdif(&mxc_spdif_data); imx6q_add_spdif_dai(); imx6q_add_spdif_audio_device(); - } else { + } else if (flexcan_en) { ret = gpio_request_array(mx6q_flexcan_gpios, ARRAY_SIZE(mx6q_flexcan_gpios)); if (ret) { @@ -1554,6 +1603,9 @@ static void __init mx6_board_init(void) imx6q_add_hdmi_soc(); imx6q_add_hdmi_soc_dai(); + imx6q_add_perfmon(0); + imx6q_add_perfmon(1); + imx6q_add_perfmon(2); } extern void __iomem *twd_base; diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c new file mode 100644 index 000000000000..063b8276605f --- /dev/null +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c @@ -0,0 +1,1560 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * 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> +#include <linux/spi/flash.h> +#include <linux/i2c.h> +#include <linux/i2c/pca953x.h> +#include <linux/ata.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/regulator/consumer.h> +#include <linux/pmic_external.h> +#include <linux/pmic_status.h> +#include <linux/ipu.h> +#include <linux/mxcfb.h> +#include <linux/pwm_backlight.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 <mach/common.h> +#include <mach/hardware.h> +#include <mach/mxc_dvfs.h> +#include <mach/memory.h> +#include <mach/iomux-mx6q.h> +#include <mach/imx-uart.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 <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> + +#include "usb.h" +#include "devices-imx6q.h" +#include "crm_regs.h" +#include "cpu_op-mx6.h" + +#define MX6Q_SABREAUTO_LDB_BACKLIGHT IMX_GPIO_NR(1, 9) +#define MX6Q_SABREAUTO_ECSPI1_CS0 IMX_GPIO_NR(2, 30) +#define MX6Q_SABREAUTO_ECSPI1_CS1 IMX_GPIO_NR(3, 19) +#define MX6Q_SABREAUTO_DISP0_PWR IMX_GPIO_NR(3, 24) +#define MX6Q_SABREAUTO_DISP0_I2C_EN IMX_GPIO_NR(3, 28) +#define MX6Q_SABREAUTO_DISP0_DET_INT IMX_GPIO_NR(3, 31) +#define MX6Q_SABREAUTO_DISP0_RESET IMX_GPIO_NR(5, 0) +#define MX6Q_SABREAUTO_SD3_CD IMX_GPIO_NR(6, 15) +#define MX6Q_SABREAUTO_SD3_WP IMX_GPIO_NR(1, 13) +#define MX6Q_SABREAUTO_USB_OTG_PWR IMX_GPIO_NR(3, 22) +#define MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR IMX_GPIO_NR(8, 0) +#define MX6Q_SABREAUTO_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8) +#define MX6Q_SABREAUTO_CAP_TCH_INT IMX_GPIO_NR(3, 31) + +#define MX6Q_SABREAUTO_IO_EXP_GPIO1(x) \ + (MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR + (x)) +#define MX6Q_SABREAUTO_IO_EXP_GPIO2(x) \ + (MX6Q_SABREAUTO_MAX7310_2_BASE_ADDR + (x)) + +#define MX6Q_SABREAUTO_CAN1_STBY IMX_GPIO_NR(7, 12) +#define MX6Q_SABREAUTO_CAN1_EN IMX_GPIO_NR(7, 13) +#define MX6Q_SABREAUTO_CAN2_STBY MX6Q_SABREAUTO_IO_EXP_GPIO2(1) +#define MX6Q_SABREAUTO_CAN2_EN IMX_GPIO_NR(5, 24) + +#define MX6Q_SMD_CSI0_RST IMX_GPIO_NR(4, 5) +#define MX6Q_SMD_CSI0_PWN IMX_GPIO_NR(5, 23) + +void __init early_console_setup(unsigned long base, struct clk *clk); +static struct clk *sata_clk; +static int esai_record; +static int spdif_en; +static int mipi_sensor; + +extern struct regulator *(*get_cpu_regulator)(void); +extern void (*put_cpu_regulator)(void); +extern int (*set_cpu_voltage)(u32 volt); +extern int mx6_set_cpu_voltage(u32 cpu_volt); +static struct regulator *cpu_regulator; +static char *gp_reg_id; + +static iomux_v3_cfg_t mx6q_sabreauto_pads[] = { + + /* UART4 for debug */ + MX6Q_PAD_KEY_COL0__UART4_TXD, + MX6Q_PAD_KEY_ROW0__UART4_RXD, + /* USB HSIC ports use the same pin with ENET */ +#ifdef CONFIG_USB_EHCI_ARC_HSIC + /* USB H2 strobe/data pin */ + MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE, + MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA, + + /* USB H3 strobe/data pin */ + MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE, + MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA, + /* ENET */ +#else + MX6Q_PAD_KEY_COL1__ENET_MDIO, + MX6Q_PAD_KEY_COL2__ENET_MDC, + MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC, + MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0, + MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1, + MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2, + MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3, + MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL, + MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK, + MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC, + MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0, + MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1, + MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2, + MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3, + MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL, +#endif + /* MCLK for csi0 */ + MX6Q_PAD_GPIO_0__CCM_CLKO, + MX6Q_PAD_GPIO_3__CCM_CLKO2, + + /* SD1 */ + MX6Q_PAD_SD1_CLK__USDHC1_CLK, + MX6Q_PAD_SD1_CMD__USDHC1_CMD, + MX6Q_PAD_SD1_DAT0__USDHC1_DAT0, + MX6Q_PAD_SD1_DAT1__USDHC1_DAT1, + MX6Q_PAD_SD1_DAT2__USDHC1_DAT2, + MX6Q_PAD_SD1_DAT3__USDHC1_DAT3, + /* SD2 */ + MX6Q_PAD_SD2_CLK__USDHC2_CLK, + MX6Q_PAD_SD2_CMD__USDHC2_CMD, + MX6Q_PAD_SD2_DAT0__USDHC2_DAT0, + MX6Q_PAD_SD2_DAT1__USDHC2_DAT1, + MX6Q_PAD_SD2_DAT2__USDHC2_DAT2, + MX6Q_PAD_SD2_DAT3__USDHC2_DAT3, + /* SD3 */ + MX6Q_PAD_SD3_CLK__USDHC3_CLK_50MHZ, + MX6Q_PAD_SD3_CMD__USDHC3_CMD_50MHZ, + MX6Q_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ, + MX6Q_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ, + MX6Q_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ, + MX6Q_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ, + MX6Q_PAD_SD3_DAT4__USDHC3_DAT4_50MHZ, + MX6Q_PAD_SD3_DAT5__USDHC3_DAT5_50MHZ, + MX6Q_PAD_SD3_DAT6__USDHC3_DAT6_50MHZ, + MX6Q_PAD_SD3_DAT7__USDHC3_DAT7_50MHZ, + /* MX6Q_PAD_SD3_RST__USDHC3_RST, */ + /* SD3 VSelect */ + MX6Q_PAD_GPIO_18__USDHC3_VSELECT, + /* SD3_CD and SD3_WP */ + MX6Q_PAD_NANDF_CS2__GPIO_6_15, + MX6Q_PAD_SD2_DAT2__GPIO_1_13, + /* SD4 */ + MX6Q_PAD_SD4_CLK__USDHC4_CLK_50MHZ, + MX6Q_PAD_SD4_CMD__USDHC4_CMD_50MHZ, + MX6Q_PAD_SD4_DAT0__USDHC4_DAT0_50MHZ, + MX6Q_PAD_SD4_DAT1__USDHC4_DAT1_50MHZ, + MX6Q_PAD_SD4_DAT2__USDHC4_DAT2_50MHZ, + MX6Q_PAD_SD4_DAT3__USDHC4_DAT3_50MHZ, + MX6Q_PAD_SD4_DAT4__USDHC4_DAT4_50MHZ, + MX6Q_PAD_SD4_DAT5__USDHC4_DAT5_50MHZ, + MX6Q_PAD_SD4_DAT6__USDHC4_DAT6_50MHZ, + MX6Q_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ, + MX6Q_PAD_NANDF_ALE__USDHC4_RST, + /* eCSPI1 */ + MX6Q_PAD_EIM_EB2__ECSPI1_SS0, + MX6Q_PAD_EIM_D16__ECSPI1_SCLK, + MX6Q_PAD_EIM_D17__ECSPI1_MISO, + MX6Q_PAD_EIM_D18__ECSPI1_MOSI, + MX6Q_PAD_EIM_D19__ECSPI1_SS1, + MX6Q_PAD_EIM_EB2__GPIO_2_30, /*SS0*/ + MX6Q_PAD_EIM_D19__GPIO_3_19, /*SS1*/ + + /* ESAI */ + MX6Q_PAD_ENET_RXD0__ESAI1_HCKT, + MX6Q_PAD_ENET_CRS_DV__ESAI1_SCKT, + MX6Q_PAD_ENET_RXD1__ESAI1_FST, + MX6Q_PAD_ENET_TX_EN__ESAI1_TX3_RX2, + MX6Q_PAD_ENET_TXD1__ESAI1_TX2_RX3, + MX6Q_PAD_ENET_TXD0__ESAI1_TX4_RX1, + MX6Q_PAD_ENET_MDC__ESAI1_TX5_RX0, + MX6Q_PAD_NANDF_CS2__ESAI1_TX0, + MX6Q_PAD_NANDF_CS3__ESAI1_TX1, + + /* I2C1 */ + MX6Q_PAD_CSI0_DAT8__I2C1_SDA, + MX6Q_PAD_CSI0_DAT9__I2C1_SCL, + + /* I2C2 */ + MX6Q_PAD_KEY_COL3__I2C2_SCL, + MX6Q_PAD_KEY_ROW3__I2C2_SDA, + + /* DISPLAY */ + MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, + MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, + MX6Q_PAD_DI0_PIN2__IPU1_DI0_PIN2, + MX6Q_PAD_DI0_PIN3__IPU1_DI0_PIN3, + MX6Q_PAD_DISP0_DAT0__IPU1_DISP0_DAT_0, + MX6Q_PAD_DISP0_DAT1__IPU1_DISP0_DAT_1, + MX6Q_PAD_DISP0_DAT2__IPU1_DISP0_DAT_2, + MX6Q_PAD_DISP0_DAT3__IPU1_DISP0_DAT_3, + MX6Q_PAD_DISP0_DAT4__IPU1_DISP0_DAT_4, + MX6Q_PAD_DISP0_DAT5__IPU1_DISP0_DAT_5, + MX6Q_PAD_DISP0_DAT6__IPU1_DISP0_DAT_6, + MX6Q_PAD_DISP0_DAT7__IPU1_DISP0_DAT_7, + MX6Q_PAD_DISP0_DAT8__IPU1_DISP0_DAT_8, + MX6Q_PAD_DISP0_DAT9__IPU1_DISP0_DAT_9, + MX6Q_PAD_DISP0_DAT10__IPU1_DISP0_DAT_10, + MX6Q_PAD_DISP0_DAT11__IPU1_DISP0_DAT_11, + MX6Q_PAD_DISP0_DAT12__IPU1_DISP0_DAT_12, + MX6Q_PAD_DISP0_DAT13__IPU1_DISP0_DAT_13, + MX6Q_PAD_DISP0_DAT14__IPU1_DISP0_DAT_14, + MX6Q_PAD_DISP0_DAT15__IPU1_DISP0_DAT_15, + MX6Q_PAD_DISP0_DAT16__IPU1_DISP0_DAT_16, + MX6Q_PAD_DISP0_DAT17__IPU1_DISP0_DAT_17, + MX6Q_PAD_DISP0_DAT18__IPU1_DISP0_DAT_18, + MX6Q_PAD_DISP0_DAT19__IPU1_DISP0_DAT_19, + MX6Q_PAD_DISP0_DAT20__IPU1_DISP0_DAT_20, + MX6Q_PAD_DISP0_DAT21__IPU1_DISP0_DAT_21, + MX6Q_PAD_DISP0_DAT22__IPU1_DISP0_DAT_22, + MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, + + /* ipu1 csi0 */ + MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12, + MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13, + MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14, + MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15, + MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16, + MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17, + MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18, + MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19, + MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, + MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, + MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, + /* camera reset */ + MX6Q_PAD_GPIO_19__GPIO_4_5, + /* camera powerdown */ + MX6Q_PAD_CSI0_DAT5__GPIO_5_23, + + MX6Q_PAD_EIM_D24__GPIO_3_24, + + /* PWM1 */ + MX6Q_PAD_GPIO_9__PWM1_PWMO, + + /* DISP0 I2C ENABLE*/ + MX6Q_PAD_EIM_D28__GPIO_3_28, + + /* DISP0 DET */ + MX6Q_PAD_EIM_D31__GPIO_3_31, + + /* DISP0 RESET */ + MX6Q_PAD_EIM_WAIT__GPIO_5_0, + + /* HDMI */ + MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE, + MX6Q_PAD_SD1_DAT1__HDMI_TX_OPHYDTB_0, + MX6Q_PAD_SD1_DAT0__HDMI_TX_OPHYDTB_1, + + /* USBOTG ID pin */ + MX6Q_PAD_GPIO_1__USBOTG_ID, +}; + +static iomux_v3_cfg_t mx6q_sabreauto_i2c3_pads[] = { + MX6Q_PAD_GPIO_5__I2C3_SCL, + MX6Q_PAD_GPIO_16__I2C3_SDA, +}; + +static iomux_v3_cfg_t mx6q_sabreauto_spdif_pads[] = { + /* SPDIF */ + MX6Q_PAD_GPIO_16__SPDIF_IN1, + MX6Q_PAD_GPIO_17__SPDIF_OUT1, +}; + +static iomux_v3_cfg_t mx6q_sabreauto_can_pads[] = { + /* CAN1 */ + MX6Q_PAD_GPIO_7__CAN1_TXCAN, + MX6Q_PAD_KEY_ROW2__CAN1_RXCAN, + MX6Q_PAD_GPIO_17__GPIO_7_12, /* CAN1 STBY */ + MX6Q_PAD_GPIO_18__GPIO_7_13, /* CAN1 EN */ + + /* CAN2 */ + MX6Q_PAD_KEY_COL4__CAN2_TXCAN, + MX6Q_PAD_KEY_ROW4__CAN2_RXCAN, + MX6Q_PAD_CSI0_DAT6__GPIO_5_24, /* CAN2 EN */ +}; + +static iomux_v3_cfg_t mx6q_sabreauto_esai_record_pads[] = { + MX6Q_PAD_ENET_RX_ER__ESAI1_HCKR, + MX6Q_PAD_ENET_MDIO__ESAI1_SCKR, + MX6Q_PAD_ENET_REF_CLK__ESAI1_FSR, +}; + +static iomux_v3_cfg_t mx6q_sabreauto_mipi_sensor_pads[] = { + MX6Q_PAD_CSI0_MCLK__CCM_CLKO, +}; + +#define MX6Q_USDHC_PAD_SETTING(id, speed) \ +mx6q_sd##id##_##speed##mhz[] = { \ + MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \ + MX6Q_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \ + MX6Q_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \ +} + +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 50); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 100); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(3, 200); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 50); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 100); +static iomux_v3_cfg_t MX6Q_USDHC_PAD_SETTING(4, 200); + +enum sd_pad_mode { + SD_PAD_MODE_LOW_SPEED, + SD_PAD_MODE_MED_SPEED, + SD_PAD_MODE_HIGH_SPEED, +}; + +static int plt_sd3_pad_change(int clock) +{ + static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; + + if (clock > 100000000) { + if (pad_mode == SD_PAD_MODE_HIGH_SPEED) + return 0; + + pad_mode = SD_PAD_MODE_HIGH_SPEED; + return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_200mhz, + ARRAY_SIZE(mx6q_sd3_200mhz)); + } else if (clock > 52000000) { + if (pad_mode == SD_PAD_MODE_MED_SPEED) + return 0; + + pad_mode = SD_PAD_MODE_MED_SPEED; + return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_100mhz, + ARRAY_SIZE(mx6q_sd3_100mhz)); + } else { + if (pad_mode == SD_PAD_MODE_LOW_SPEED) + return 0; + + pad_mode = SD_PAD_MODE_LOW_SPEED; + return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_50mhz, + ARRAY_SIZE(mx6q_sd3_50mhz)); + } +} + +static int plt_sd4_pad_change(int clock) +{ + static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; + + if (clock > 100000000) { + if (pad_mode == SD_PAD_MODE_HIGH_SPEED) + return 0; + + pad_mode = SD_PAD_MODE_HIGH_SPEED; + return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_200mhz, + ARRAY_SIZE(mx6q_sd4_200mhz)); + } else if (clock > 52000000) { + if (pad_mode == SD_PAD_MODE_MED_SPEED) + return 0; + + pad_mode = SD_PAD_MODE_MED_SPEED; + return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_100mhz, + ARRAY_SIZE(mx6q_sd4_100mhz)); + } else { + if (pad_mode == SD_PAD_MODE_LOW_SPEED) + return 0; + + pad_mode = SD_PAD_MODE_LOW_SPEED; + return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_50mhz, + ARRAY_SIZE(mx6q_sd4_50mhz)); + } +} + +static const struct esdhc_platform_data mx6q_sabreauto_sd3_data __initconst = { + .cd_gpio = MX6Q_SABREAUTO_SD3_CD, + .wp_gpio = MX6Q_SABREAUTO_SD3_WP, + .support_18v = 1, + .support_8bit = 1, + .delay_line = 0, + .platform_pad_change = plt_sd3_pad_change, +}; + +/* No card detect signal for SD4 */ +static const struct esdhc_platform_data mx6q_sabreauto_sd4_data __initconst = { + .always_present = 1, + .support_8bit = 1, + .platform_pad_change = plt_sd4_pad_change, +}; + +/* The GPMI is conflicted with SD3, so init this in the driver. */ +static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = { + MX6Q_PAD_NANDF_CLE__RAWNAND_CLE, + MX6Q_PAD_NANDF_ALE__RAWNAND_ALE, + MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N, + MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N, + MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N, + MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N, + MX6Q_PAD_NANDF_RB0__RAWNAND_READY0, + MX6Q_PAD_SD4_DAT0__RAWNAND_DQS, + MX6Q_PAD_NANDF_D0__RAWNAND_D0, + MX6Q_PAD_NANDF_D1__RAWNAND_D1, + MX6Q_PAD_NANDF_D2__RAWNAND_D2, + MX6Q_PAD_NANDF_D3__RAWNAND_D3, + MX6Q_PAD_NANDF_D4__RAWNAND_D4, + MX6Q_PAD_NANDF_D5__RAWNAND_D5, + MX6Q_PAD_NANDF_D6__RAWNAND_D6, + MX6Q_PAD_NANDF_D7__RAWNAND_D7, + MX6Q_PAD_SD4_CMD__RAWNAND_RDN, + MX6Q_PAD_SD4_CLK__RAWNAND_WRN, + MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN, +}; + +static int gpmi_nfc_platform_init(void) +{ + return mxc_iomux_v3_setup_multiple_pads(mx6q_gpmi_nand, + ARRAY_SIZE(mx6q_gpmi_nand)); +} + +static const struct gpmi_nfc_platform_data +mx6q_gpmi_nfc_platform_data __initconst = { + .platform_init = gpmi_nfc_platform_init, + .min_prop_delay_in_ns = 5, + .max_prop_delay_in_ns = 9, + .max_chip_count = 1, +}; + +static const struct anatop_thermal_platform_data + mx6q_sabreauto_anatop_thermal_data __initconst = { + .name = "anatop_thermal", +}; + +static inline void mx6q_sabreauto_init_uart(void) +{ + imx6q_add_imx_uart(0, NULL); + imx6q_add_imx_uart(1, NULL); + imx6q_add_imx_uart(3, NULL); +} + +static int mx6q_sabreauto_fec_phy_init(struct phy_device *phydev) +{ + unsigned short val; + + /* To enable AR8031 ouput a 125MHz clk from CLK_25M */ + phy_write(phydev, 0xd, 0x7); + phy_write(phydev, 0xe, 0x8016); + phy_write(phydev, 0xd, 0x4007); + val = phy_read(phydev, 0xe); + + val &= 0xffe3; + val |= 0x18; + phy_write(phydev, 0xe, val); + + /* introduce tx clock delay */ + phy_write(phydev, 0x1d, 0x5); + val = phy_read(phydev, 0x1e); + val |= 0x0100; + phy_write(phydev, 0x1e, val); + + return 0; +} + +static int mx6q_sabreauto_fec_power_hibernate(struct phy_device *phydev) +{ + unsigned short val; + + /*set AR8031 debug reg 0xb to hibernate power*/ + phy_write(phydev, 0x1d, 0xb); + val = phy_read(phydev, 0x1e); + + val |= 0x8000; + phy_write(phydev, 0x1e, val); + + return 0; +} + +static struct fec_platform_data fec_data __initdata = { + .init = mx6q_sabreauto_fec_phy_init, + .power_hibernate = mx6q_sabreauto_fec_power_hibernate, + .phy = PHY_INTERFACE_MODE_RGMII, +}; + +static int mx6q_sabreauto_spi_cs[] = { + MX6Q_SABREAUTO_ECSPI1_CS0, + MX6Q_SABREAUTO_ECSPI1_CS1, +}; + +static const struct spi_imx_master mx6q_sabreauto_spi_data __initconst = { + .chipselect = mx6q_sabreauto_spi_cs, + .num_chipselect = ARRAY_SIZE(mx6q_sabreauto_spi_cs), +}; + +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition m25p32_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 0x00040000, + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct flash_platform_data m25p32_spi_flash_data = { + .name = "m25p32", + .parts = m25p32_partitions, + .nr_parts = ARRAY_SIZE(m25p32_partitions), + .type = "m25p32", +}; +#endif + +static struct spi_board_info m25p32_spi0_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &m25p32_spi_flash_data, + }, +#endif +}; + +static void spi_device_init(void) +{ + spi_register_board_info(m25p32_spi0_board_info, + ARRAY_SIZE(m25p32_spi0_board_info)); +} + +static int max7310_1_setup(struct i2c_client *client, + unsigned gpio_base, unsigned ngpio, + void *context) +{ + int max7310_gpio_value[] = { + 0, 1, 0, 1, 0, 0, 0, 0, + }; + + int n; + + for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) { + gpio_request(gpio_base + n, "MAX7310 1 GPIO Expander"); + if (max7310_gpio_value[n] < 0) + gpio_direction_input(gpio_base + n); + else + gpio_direction_output(gpio_base + n, + max7310_gpio_value[n]); + gpio_export(gpio_base + n, 0); + } + + return 0; +} + +static struct pca953x_platform_data max7310_platdata = { + .gpio_base = MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR, + .invert = 0, + .setup = max7310_1_setup, +}; + +static int max7310_u48_setup(struct i2c_client *client, + unsigned gpio_base, unsigned ngpio, + void *context) +{ + int max7310_gpio_value[] = { + 1, 1, 1, 1, 0, 0, 0, 0, + }; + + int n; + + for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) { + gpio_request(gpio_base + n, "MAX7310 U48 GPIO Expander"); + if (max7310_gpio_value[n] < 0) + gpio_direction_input(gpio_base + n); + else + gpio_direction_output(gpio_base + n, + max7310_gpio_value[n]); + gpio_export(gpio_base + n, 0); + } + + return 0; +} + +static struct pca953x_platform_data max7310_u48_platdata = { + .gpio_base = MX6Q_SABREAUTO_MAX7310_2_BASE_ADDR, + .invert = 0, + .setup = max7310_u48_setup, +}; + +static void ddc_dvi_init(void) +{ + /* enable DVI I2C */ + gpio_set_value(MX6Q_SABREAUTO_DISP0_I2C_EN, 1); +} + +static int ddc_dvi_update(void) +{ + /* DVI cable state */ + if (gpio_get_value(MX6Q_SABREAUTO_DISP0_DET_INT) == 1) + return 1; + else + return 0; +} + +static struct fsl_mxc_dvi_platform_data sabr_ddc_dvi_data = { + .ipu_id = 0, + .disp_id = 0, + .init = ddc_dvi_init, + .update = ddc_dvi_update, +}; + +static struct fsl_mxc_camera_platform_data camera_data = { + .analog_regulator = "DA9052_LDO7", + .core_regulator = "DA9052_LDO9", + .mclk = 24000000, + .csi = 0, +}; + +static struct fsl_mxc_camera_platform_data ov5640_mipi_data = { + .mclk = 24000000, + .csi = 0, +}; + + +static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { + { + I2C_BOARD_INFO("cs42888", 0x48), + }, + { + I2C_BOARD_INFO("ov3640", 0x3c), + .platform_data = (void *)&camera_data, + }, +}; + +static struct imxi2c_platform_data mx6q_sabreauto_i2c_data = { + .bitrate = 400000, +}; + +static struct imxi2c_platform_data mx6q_sabreauto_i2c0_data = { + .bitrate = 100000, +}; + +static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { + { + I2C_BOARD_INFO("max7310", 0x1F), + .platform_data = &max7310_platdata, + }, + { + I2C_BOARD_INFO("max7310", 0x1B), + .platform_data = &max7310_u48_platdata, + }, + { + I2C_BOARD_INFO("mxc_dvi", 0x50), + .platform_data = &sabr_ddc_dvi_data, + .irq = gpio_to_irq(MX6Q_SABREAUTO_DISP0_DET_INT), + }, + { + I2C_BOARD_INFO("egalax_ts", 0x4), + .irq = gpio_to_irq(MX6Q_SABREAUTO_CAP_TCH_INT), + }, + +}; + +static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { + { + I2C_BOARD_INFO("egalax_ts", 0x4), + .irq = gpio_to_irq(MX6Q_SABREAUTO_CAP_TCH_INT), + }, + { + I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50), + }, + { + I2C_BOARD_INFO("ov5640_mipi", 0x3c), + .platform_data = (void *)&ov5640_mipi_data, + }, +}; + +static void imx6q_sabreauto_usbotg_vbus(bool on) +{ + if (on) + gpio_set_value(MX6Q_SABREAUTO_USB_OTG_PWR, 1); + else + gpio_set_value(MX6Q_SABREAUTO_USB_OTG_PWR, 0); +} + +static void __init imx6q_sabreauto_init_usb(void) +{ + int ret = 0; + + imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR); + /* disable external charger detect, + * or it will affect signal quality at dp. + */ + + ret = gpio_request(MX6Q_SABREAUTO_USB_OTG_PWR, "usb-pwr"); + if (ret) { + printk(KERN_ERR"failed to get GPIO MX6Q_SABREAUTO_USB_OTG_PWR:" + " %d\n", ret); + return; + } + gpio_direction_output(MX6Q_SABREAUTO_USB_OTG_PWR, 0); + mxc_iomux_set_gpr_register(1, 13, 1, 1); + + mx6_set_otghost_vbus_func(imx6q_sabreauto_usbotg_vbus); + mx6_usb_dr_init(); + mx6_usb_h1_init(); +#ifdef CONFIG_USB_EHCI_ARC_HSIC + mx6_usb_h2_init(); + mx6_usb_h3_init(); +#endif +} + +static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = { + .reserved_mem_size = SZ_128M, +}; + +/* HW Initialization, if return 0, initialization is successful. */ +static int mx6q_sabreauto_sata_init(struct device *dev, void __iomem *addr) +{ + u32 tmpdata; + int ret = 0; + struct clk *clk; + + /* Enable SATA PWR CTRL_0 of MAX7310 */ + gpio_request(MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); + gpio_direction_output(MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR, 1); + + sata_clk = clk_get(dev, "imx_sata_clk"); + if (IS_ERR(sata_clk)) { + dev_err(dev, "no sata clock.\n"); + return PTR_ERR(sata_clk); + } + ret = clk_enable(sata_clk); + if (ret) { + dev_err(dev, "can't enable sata clock.\n"); + goto put_sata_clk; + } + + /* Set PHY Paremeters, two steps to configure the GPR13, + * one write for rest of parameters, mask of first write is 0x07FFFFFD, + * and the other one write for setting the mpll_clk_off_b + *.rx_eq_val_0(iomuxc_gpr13[26:24]), + *.los_lvl(iomuxc_gpr13[23:19]), + *.rx_dpll_mode_0(iomuxc_gpr13[18:16]), + *.sata_speed(iomuxc_gpr13[15]), + *.mpll_ss_en(iomuxc_gpr13[14]), + *.tx_atten_0(iomuxc_gpr13[13:11]), + *.tx_boost_0(iomuxc_gpr13[10:7]), + *.tx_lvl(iomuxc_gpr13[6:2]), + *.mpll_ck_off(iomuxc_gpr13[1]), + *.tx_edgerate_0(iomuxc_gpr13[0]), + */ + tmpdata = readl(IOMUXC_GPR13); + writel(((tmpdata & ~0x07FFFFFD) | 0x0593A044), IOMUXC_GPR13); + + /* enable SATA_PHY PLL */ + tmpdata = readl(IOMUXC_GPR13); + writel(((tmpdata & ~0x2) | 0x2), IOMUXC_GPR13); + + /* Get the AHB clock rate, and configure the TIMER1MS reg later */ + clk = clk_get(NULL, "ahb"); + if (IS_ERR(clk)) { + dev_err(dev, "no ahb clock.\n"); + ret = PTR_ERR(clk); + goto release_sata_clk; + } + tmpdata = clk_get_rate(clk) / 1000; + clk_put(clk); + + sata_init(addr, tmpdata); + + return ret; + +release_sata_clk: + clk_disable(sata_clk); +put_sata_clk: + clk_put(sata_clk); + + return ret; +} + +static void mx6q_sabreauto_sata_exit(struct device *dev) +{ + clk_disable(sata_clk); + clk_put(sata_clk); + + /* Disable SATA PWR CTRL_0 of MAX7310 */ + gpio_request(MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR, "SATA_PWR_EN"); + gpio_direction_output(MX6Q_SABREAUTO_MAX7310_1_BASE_ADDR, 0); + +} + +static struct ahci_platform_data mx6q_sabreauto_sata_data = { + .init = mx6q_sabreauto_sata_init, + .exit = mx6q_sabreauto_sata_exit, +}; + +static struct imx_asrc_platform_data imx_asrc_data = { + .channel_bits = 4, + .clk_map_ver = 2, +}; + +static void mx6q_sabreauto_reset_mipi_dsi(void) +{ + gpio_set_value(MX6Q_SABREAUTO_DISP0_PWR, 1); + gpio_set_value(MX6Q_SABREAUTO_DISP0_RESET, 1); + udelay(10); + gpio_set_value(MX6Q_SABREAUTO_DISP0_RESET, 0); + udelay(50); + gpio_set_value(MX6Q_SABREAUTO_DISP0_RESET, 1); + + /* + * it needs to delay 120ms minimum for reset complete + */ + msleep(120); +} + +static struct mipi_dsi_platform_data mipi_dsi_pdata = { + .ipu_id = 0, + .disp_id = 0, + .lcd_panel = "TRULY-WVGA", + .reset = mx6q_sabreauto_reset_mipi_dsi, +}; + +static struct ipuv3_fb_platform_data sabr_fb_data[] = { + { /*fb0*/ + .disp_dev = "ldb", + .interface_pix_fmt = IPU_PIX_FMT_RGB666, + .mode_str = "LDB-XGA", + .default_bpp = 16, + .int_clk = false, + }, { + .disp_dev = "lcd", + .interface_pix_fmt = IPU_PIX_FMT_RGB565, + .mode_str = "CLAA-WVGA", + .default_bpp = 16, + .int_clk = false, + }, { + .disp_dev = "ldb", + .interface_pix_fmt = IPU_PIX_FMT_RGB666, + .mode_str = "LDB-XGA", + .default_bpp = 16, + .int_clk = false, + }, +}; + +static void hdmi_init(int ipu_id, int disp_id) +{ + int hdmi_mux_setting; + + if ((ipu_id > 1) || (ipu_id < 0)) { + printk(KERN_ERR"Invalid IPU select for HDMI: %d. Set to 0\n", + ipu_id); + ipu_id = 0; + } + + if ((disp_id > 1) || (disp_id < 0)) { + printk(KERN_ERR"Invalid DI select for HDMI: %d. Set to 0\n", + disp_id); + disp_id = 0; + } + + /* Configure the connection between IPU1/2 and HDMI */ + hdmi_mux_setting = 2*ipu_id + disp_id; + + /* GPR3, bits 2-3 = HDMI_MUX_CTL */ + mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting); +} + +static struct fsl_mxc_hdmi_platform_data hdmi_data = { + .init = hdmi_init, +}; + +static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = { + .ipu_id = 0, + .disp_id = 0, +}; + +static struct fsl_mxc_lcd_platform_data lcdif_data = { + .ipu_id = 0, + .disp_id = 0, + .default_ifmt = IPU_PIX_FMT_RGB565, +}; + +static struct fsl_mxc_ldb_platform_data ldb_data = { + .ipu_id = 0, + .disp_id = 1, + .ext_ref = 1, + .mode = LDB_SEP0, + .sec_ipu_id = 1, + .sec_disp_id = 1, +}; + +static struct imx_ipuv3_platform_data ipu_data[] = { + { + .rev = 4, + .csi_clk[0] = "ccm_clk0", + }, { + .rev = 4, + .csi_clk[0] = "ccm_clk0", + }, +}; + +static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data = { + .pwm_id = 0, + .max_brightness = 255, + .dft_brightness = 128, + .pwm_period_ns = 50000, +}; + +static struct gpio mx6q_flexcan_gpios[] = { + { MX6Q_SABREAUTO_CAN1_EN, GPIOF_OUT_INIT_LOW, "flexcan1-en" }, + { MX6Q_SABREAUTO_CAN1_STBY, GPIOF_OUT_INIT_LOW, "flexcan1-stby" }, + { MX6Q_SABREAUTO_CAN2_EN, GPIOF_OUT_INIT_LOW, "flexcan2-en" }, +}; + +static void mx6q_flexcan0_switch(int enable) +{ + if (enable) { + gpio_set_value(MX6Q_SABREAUTO_CAN1_EN, 1); + gpio_set_value(MX6Q_SABREAUTO_CAN1_STBY, 1); + } else { + gpio_set_value(MX6Q_SABREAUTO_CAN1_EN, 0); + gpio_set_value(MX6Q_SABREAUTO_CAN1_STBY, 0); + } +} + +static void mx6q_flexcan1_switch(int enable) +{ + if (enable) { + gpio_set_value(MX6Q_SABREAUTO_CAN2_EN, 1); + gpio_set_value(MX6Q_SABREAUTO_CAN2_STBY, 1); + } else { + gpio_set_value(MX6Q_SABREAUTO_CAN2_EN, 0); + gpio_set_value(MX6Q_SABREAUTO_CAN2_STBY, 0); + } +} + +static const struct flexcan_platform_data + mx6q_sabreauto_flexcan_pdata[] __initconst = { + { + .transceiver_switch = mx6q_flexcan0_switch, + }, { + .transceiver_switch = mx6q_flexcan1_switch, + } +}; + +static struct mipi_csi2_platform_data mipi_csi2_pdata = { + .ipu_id = 0, + .csi_id = 0, + .v_channel = 0, + .lanes = 2, + .dphy_clk = "mipi_pllref_clk", + .pixel_clk = "emi_clk", +}; + +static void arm2_suspend_enter(void) +{ + /* suspend preparation */ +} + +static void arm2_suspend_exit(void) +{ + /* resmue resore */ +} +static const struct pm_platform_data mx6q_sabreauto_pm_data __initconst = { + .name = "imx_pm", + .suspend_enter = arm2_suspend_enter, + .suspend_exit = arm2_suspend_exit, +}; + +static struct mxc_audio_platform_data sab_audio_data = { + .sysclk = 16934400, +}; + +static struct platform_device sab_audio_device = { + .name = "imx-cs42888", +}; + +static struct imx_esai_platform_data sab_esai_pdata = { + .flags = IMX_ESAI_NET, +}; + +static struct regulator_consumer_supply arm2_vmmc_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"), + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"), + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.3"), +}; + +static struct regulator_init_data arm2_vmmc_init = { + .num_consumer_supplies = ARRAY_SIZE(arm2_vmmc_consumers), + .consumer_supplies = arm2_vmmc_consumers, +}; + +static struct fixed_voltage_config arm2_vmmc_reg_config = { + .supply_name = "vmmc", + .microvolts = 3300000, + .gpio = -1, + .init_data = &arm2_vmmc_init, +}; + +static struct platform_device arm2_vmmc_reg_devices = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &arm2_vmmc_reg_config, + }, +}; + +#ifdef CONFIG_SND_SOC_CS42888 + +static struct regulator_consumer_supply cs42888_arm2_consumer_va = { + .supply = "VA", + .dev_name = "0-0048", +}; + +static struct regulator_consumer_supply cs42888_arm2_consumer_vd = { + .supply = "VD", + .dev_name = "0-0048", +}; + +static struct regulator_consumer_supply cs42888_arm2_consumer_vls = { + .supply = "VLS", + .dev_name = "0-0048", +}; + +static struct regulator_consumer_supply cs42888_arm2_consumer_vlc = { + .supply = "VLC", + .dev_name = "0-0048", +}; + +static struct regulator_init_data cs42888_arm2_va_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_va, +}; + +static struct regulator_init_data cs42888_arm2_vd_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_vd, +}; + +static struct regulator_init_data cs42888_arm2_vls_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_vls, +}; + +static struct regulator_init_data cs42888_arm2_vlc_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &cs42888_arm2_consumer_vlc, +}; + +static struct fixed_voltage_config cs42888_arm2_va_reg_config = { + .supply_name = "VA", + .microvolts = 2800000, + .gpio = -1, + .init_data = &cs42888_arm2_va_reg_initdata, +}; + +static struct fixed_voltage_config cs42888_arm2_vd_reg_config = { + .supply_name = "VD", + .microvolts = 2800000, + .gpio = -1, + .init_data = &cs42888_arm2_vd_reg_initdata, +}; + +static struct fixed_voltage_config cs42888_arm2_vls_reg_config = { + .supply_name = "VLS", + .microvolts = 2800000, + .gpio = -1, + .init_data = &cs42888_arm2_vls_reg_initdata, +}; + +static struct fixed_voltage_config cs42888_arm2_vlc_reg_config = { + .supply_name = "VLC", + .microvolts = 2800000, + .gpio = -1, + .init_data = &cs42888_arm2_vlc_reg_initdata, +}; + +static struct platform_device cs42888_arm2_va_reg_devices = { + .name = "reg-fixed-voltage", + .id = 3, + .dev = { + .platform_data = &cs42888_arm2_va_reg_config, + }, +}; + +static struct platform_device cs42888_arm2_vd_reg_devices = { + .name = "reg-fixed-voltage", + .id = 4, + .dev = { + .platform_data = &cs42888_arm2_vd_reg_config, + }, +}; + +static struct platform_device cs42888_arm2_vls_reg_devices = { + .name = "reg-fixed-voltage", + .id = 5, + .dev = { + .platform_data = &cs42888_arm2_vls_reg_config, + }, +}; + +static struct platform_device cs42888_arm2_vlc_reg_devices = { + .name = "reg-fixed-voltage", + .id = 6, + .dev = { + .platform_data = &cs42888_arm2_vlc_reg_config, + }, +}; + +#endif /* CONFIG_SND_SOC_CS42888 */ + +#ifdef CONFIG_SND_SOC_SGTL5000 + +static struct regulator_consumer_supply sgtl5000_arm2_consumer_vdda = { + .supply = "VDDA", + .dev_name = "0-000a", +}; + +static struct regulator_consumer_supply sgtl5000_arm2_consumer_vddio = { + .supply = "VDDIO", + .dev_name = "0-000a", +}; + +static struct regulator_consumer_supply sgtl5000_arm2_consumer_vddd = { + .supply = "VDDD", + .dev_name = "0-000a", +}; + +static struct regulator_init_data sgtl5000_arm2_vdda_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &sgtl5000_arm2_consumer_vdda, +}; + +static struct regulator_init_data sgtl5000_arm2_vddio_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &sgtl5000_arm2_consumer_vddio, +}; + +static struct regulator_init_data sgtl5000_arm2_vddd_reg_initdata = { + .num_consumer_supplies = 1, + .consumer_supplies = &sgtl5000_arm2_consumer_vddd, +}; + +static struct fixed_voltage_config sgtl5000_arm2_vdda_reg_config = { + .supply_name = "VDDA", + .microvolts = 1800000, + .gpio = -1, + .init_data = &sgtl5000_arm2_vdda_reg_initdata, +}; + +static struct fixed_voltage_config sgtl5000_arm2_vddio_reg_config = { + .supply_name = "VDDIO", + .microvolts = 3300000, + .gpio = -1, + .init_data = &sgtl5000_arm2_vddio_reg_initdata, +}; + +static struct fixed_voltage_config sgtl5000_arm2_vddd_reg_config = { + .supply_name = "VDDD", + .microvolts = 0, + .gpio = -1, + .init_data = &sgtl5000_arm2_vddd_reg_initdata, +}; + +static struct platform_device sgtl5000_arm2_vdda_reg_devices = { + .name = "reg-fixed-voltage", + .id = 7, + .dev = { + .platform_data = &sgtl5000_arm2_vdda_reg_config, + }, +}; + +static struct platform_device sgtl5000_arm2_vddio_reg_devices = { + .name = "reg-fixed-voltage", + .id = 8, + .dev = { + .platform_data = &sgtl5000_arm2_vddio_reg_config, + }, +}; + +static struct platform_device sgtl5000_arm2_vddd_reg_devices = { + .name = "reg-fixed-voltage", + .id = 9, + .dev = { + .platform_data = &sgtl5000_arm2_vddd_reg_config, + }, +}; + +#endif /* CONFIG_SND_SOC_SGTL5000 */ + +static int __init imx6q_init_audio(void) +{ + struct clk *pll3_pfd, *esai_clk; + mxc_register_device(&sab_audio_device, &sab_audio_data); + imx6q_add_imx_esai(0, &sab_esai_pdata); + + esai_clk = clk_get(NULL, "esai_clk"); + if (IS_ERR(esai_clk)) + return PTR_ERR(esai_clk); + + pll3_pfd = clk_get(NULL, "pll3_pfd_508M"); + if (IS_ERR(pll3_pfd)) + return PTR_ERR(pll3_pfd); + + clk_set_parent(esai_clk, pll3_pfd); + clk_set_rate(esai_clk, 101647058); + +#ifdef CONFIG_SND_SOC_SGTL5000 + platform_device_register(&sgtl5000_arm2_vdda_reg_devices); + platform_device_register(&sgtl5000_arm2_vddio_reg_devices); + platform_device_register(&sgtl5000_arm2_vddd_reg_devices); +#endif + +#ifdef CONFIG_SND_SOC_CS42888 + platform_device_register(&cs42888_arm2_va_reg_devices); + platform_device_register(&cs42888_arm2_vd_reg_devices); + platform_device_register(&cs42888_arm2_vls_reg_devices); + platform_device_register(&cs42888_arm2_vlc_reg_devices); +#endif + return 0; +} + +static int __init early_use_esai_record(char *p) +{ + esai_record = 1; + return 0; +} + +early_param("esai_record", early_use_esai_record); + +static struct mxc_dvfs_platform_data arm2_dvfscore_data = { + .reg_id = "cpu_vddgp", + .clk1_id = "cpu_clk", + .clk2_id = "gpc_dvfs_clk", + .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, + .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET, + .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET, + .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET, + .prediv_mask = 0x1F800, + .prediv_offset = 11, + .prediv_val = 3, + .div3ck_mask = 0xE0000000, + .div3ck_offset = 29, + .div3ck_val = 2, + .emac_val = 0x08, + .upthr_val = 25, + .dnthr_val = 9, + .pncthr_val = 33, + .upcnt_val = 10, + .dncnt_val = 10, + .delay_time = 80, +}; + +static int mx6_arm2_set_cpu_voltage(u32 cpu_volt) +{ + int ret = -EINVAL; + + if (cpu_regulator == NULL) + cpu_regulator = regulator_get(NULL, gp_reg_id); + + if (!IS_ERR(cpu_regulator)) + ret = regulator_set_voltage(cpu_regulator, + cpu_volt, cpu_volt); + return ret; +} + +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + set_cpu_voltage = mx6_arm2_set_cpu_voltage; +} + +static int __init early_enable_mipi_sensor(char *p) +{ + mipi_sensor = 1; + return 0; +} +early_param("mipi_sensor", early_enable_mipi_sensor); + +static inline void __init mx6q_csi0_io_init(void) +{ + /* Camera reset */ + gpio_request(MX6Q_SMD_CSI0_RST, "cam-reset"); + gpio_direction_output(MX6Q_SMD_CSI0_RST, 1); + + /* Camera power down */ + gpio_request(MX6Q_SMD_CSI0_PWN, "cam-pwdn"); + gpio_direction_output(MX6Q_SMD_CSI0_PWN, 1); + msleep(1); + gpio_set_value(MX6Q_SMD_CSI0_PWN, 0); + mxc_iomux_set_gpr_register(1, 19, 1, 1); +} + +static int __init early_enable_spdif(char *p) +{ + spdif_en = 1; + return 0; +} + +early_param("spdif", early_enable_spdif); + +static int spdif_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long rate_actual; + rate_actual = clk_round_rate(clk, rate); + clk_set_rate(clk, rate_actual); + return 0; +} + +static struct mxc_spdif_platform_data mxc_spdif_data = { + .spdif_tx = 1, /* enable tx */ + .spdif_rx = 1, /* enable rx */ + /* + * spdif0_clk will be 454.7MHz divided by ccm dividers. + * + * 44.1KHz: 454.7MHz / 7 (ccm) / 23 (spdif) = 44,128 Hz ~ 0.06% error + * 48KHz: 454.7MHz / 4 (ccm) / 37 (spdif) = 48,004 Hz ~ 0.01% error + * 32KHz: 454.7MHz / 6 (ccm) / 37 (spdif) = 32,003 Hz ~ 0.01% error + */ + .spdif_clk_44100 = 1, /* tx clk from spdif0_clk_root */ + .spdif_clk_48000 = 1, /* tx clk from spdif0_clk_root */ + .spdif_div_44100 = 23, + .spdif_div_48000 = 37, + .spdif_div_32000 = 37, + .spdif_rx_clk = 0, /* rx clk from spdif stream */ + .spdif_clk_set_rate = spdif_clk_set_rate, + .spdif_clk = NULL, /* spdif bus clk */ +}; + +/*! + * Board specific initialization. + */ +static void __init mx6_board_init(void) +{ + int i; + int ret; + + mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_pads, + ARRAY_SIZE(mx6q_sabreauto_pads)); + + if (esai_record) + mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_esai_record_pads, + ARRAY_SIZE(mx6q_sabreauto_esai_record_pads)); + + /* + * S/PDIF in and i2c3 are mutually exclusive because both + * use GPIO_16. + * S/PDIF out and can1 stby are mutually exclusive because both + * use GPIO_17. + */ + if (spdif_en) { + mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_spdif_pads, + ARRAY_SIZE(mx6q_sabreauto_spdif_pads)); + } else { + mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_i2c3_pads, + ARRAY_SIZE(mx6q_sabreauto_i2c3_pads)); + mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_can_pads, + ARRAY_SIZE(mx6q_sabreauto_can_pads)); + } + + if (mipi_sensor) + mxc_iomux_v3_setup_multiple_pads( + mx6q_sabreauto_mipi_sensor_pads, + ARRAY_SIZE(mx6q_sabreauto_mipi_sensor_pads)); + + gp_reg_id = arm2_dvfscore_data.reg_id; + mx6q_sabreauto_init_uart(); + imx6q_add_mipi_csi2(&mipi_csi2_pdata); + imx6q_add_mxc_hdmi_core(&hdmi_core_data); + + imx6q_add_ipuv3(0, &ipu_data[0]); + imx6q_add_ipuv3(1, &ipu_data[1]); + + for (i = 0; i < ARRAY_SIZE(sabr_fb_data); i++) + imx6q_add_ipuv3fb(i, &sabr_fb_data[i]); + + imx6q_add_mipi_dsi(&mipi_dsi_pdata); + imx6q_add_lcdif(&lcdif_data); + imx6q_add_ldb(&ldb_data); + imx6q_add_v4l2_output(0); + imx6q_add_v4l2_capture(0); + + imx6q_add_imx_snvs_rtc(); + + imx6q_add_imx_i2c(0, &mx6q_sabreauto_i2c0_data); + imx6q_add_imx_i2c(1, &mx6q_sabreauto_i2c_data); + i2c_register_board_info(0, mxc_i2c0_board_info, + ARRAY_SIZE(mxc_i2c0_board_info)); + i2c_register_board_info(1, mxc_i2c1_board_info, + ARRAY_SIZE(mxc_i2c1_board_info)); + if (!spdif_en) { + imx6q_add_imx_i2c(2, &mx6q_sabreauto_i2c_data); + i2c_register_board_info(2, mxc_i2c2_board_info, + ARRAY_SIZE(mxc_i2c2_board_info)); + } + + /* SPI */ + imx6q_add_ecspi(0, &mx6q_sabreauto_spi_data); + spi_device_init(); + + imx6q_add_mxc_hdmi(&hdmi_data); + + imx6q_add_anatop_thermal_imx(1, &mx6q_sabreauto_anatop_thermal_data); + + if (!esai_record) + imx6_init_fec(fec_data); + + imx6q_add_pm_imx(0, &mx6q_sabreauto_pm_data); + /* imx6q_add_sdhci_usdhc_imx(3, &mx6q_sabreauto_sd4_data); */ + imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabreauto_sd3_data); + imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata); + imx6q_sabreauto_init_usb(); + imx6q_add_ahci(0, &mx6q_sabreauto_sata_data); + imx6q_add_vpu(); + imx6q_init_audio(); + platform_device_register(&arm2_vmmc_reg_devices); + imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); + imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); + imx6q_add_asrc(&imx_asrc_data); + + if (!mipi_sensor) + mx6q_csi0_io_init(); + + /* DISP0 Detect */ + gpio_request(MX6Q_SABREAUTO_DISP0_DET_INT, "disp0-detect"); + gpio_direction_input(MX6Q_SABREAUTO_DISP0_DET_INT); + + /* DISP0 Reset - Assert for i2c disabled mode */ + gpio_request(MX6Q_SABREAUTO_DISP0_RESET, "disp0-reset"); + gpio_direction_output(MX6Q_SABREAUTO_DISP0_RESET, 0); + + /* DISP0 I2C enable */ + gpio_request(MX6Q_SABREAUTO_DISP0_I2C_EN, "disp0-i2c"); + gpio_direction_output(MX6Q_SABREAUTO_DISP0_I2C_EN, 0); + + gpio_request(MX6Q_SABREAUTO_DISP0_PWR, "disp0-pwr"); + gpio_direction_output(MX6Q_SABREAUTO_DISP0_PWR, 1); + + gpio_request(MX6Q_SABREAUTO_LDB_BACKLIGHT, "ldb-backlight"); + gpio_direction_output(MX6Q_SABREAUTO_LDB_BACKLIGHT, 1); + imx6q_add_otp(); + imx6q_add_viim(); + imx6q_add_imx2_wdt(0, NULL); + imx6q_add_dma(); + imx6q_add_gpmi(&mx6q_gpmi_nfc_platform_data); + + imx6q_add_dvfs_core(&arm2_dvfscore_data); + + imx6q_add_mxc_pwm(0); + imx6q_add_mxc_pwm_backlight(0, &mx6_arm2_pwm_backlight_data); + + if (spdif_en) { + mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0", + NULL); + clk_put(mxc_spdif_data.spdif_core_clk); + imx6q_add_spdif(&mxc_spdif_data); + imx6q_add_spdif_dai(); + imx6q_add_spdif_audio_device(); + } else { + ret = gpio_request_array(mx6q_flexcan_gpios, + ARRAY_SIZE(mx6q_flexcan_gpios)); + if (ret) { + pr_err("failed to request flexcan-gpios: %d\n", ret); + } else { + imx6q_add_flexcan0(&mx6q_sabreauto_flexcan_pdata[0]); + imx6q_add_flexcan1(&mx6q_sabreauto_flexcan_pdata[1]); + } + } + + imx6q_add_hdmi_soc(); + imx6q_add_hdmi_soc_dai(); +} + +extern void __iomem *twd_base; +static void __init mx6_timer_init(void) +{ + struct clk *uart_clk; +#ifdef CONFIG_LOCAL_TIMERS + twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256); + BUG_ON(!twd_base); +#endif + mx6_clocks_init(32768, 24000000, 0, 0); + + uart_clk = clk_get_sys("imx-uart.0", NULL); + early_console_setup(UART4_BASE_ADDR, uart_clk); +} + +static struct sys_timer mxc_timer = { + .init = mx6_timer_init, +}; + +static void __init mx6q_reserve(void) +{ + phys_addr_t phys; + + if (imx6q_gpu_pdata.reserved_mem_size) { + phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size, + SZ_4K, SZ_2G); + memblock_free(phys, imx6q_gpu_pdata.reserved_mem_size); + memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size); + imx6q_gpu_pdata.reserved_mem_base = phys; + } +} + +/* + * initialize __mach_desc_MX6Q_SABREAUTO data structure. + */ +MACHINE_START(MX6Q_SABREAUTO, "Freescale i.MX 6Quad Sabre Auto Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .boot_params = MX6_PHYS_OFFSET + 0x100, + .fixup = fixup_mxc_board, + .map_io = mx6_map_io, + .init_irq = mx6_init_irq, + .init_machine = mx6_board_init, + .timer = &mxc_timer, + .reserve = mx6q_reserve, +MACHINE_END diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c index c3b49eb9fc10..3918989ca166 100755 --- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c +++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c @@ -82,6 +82,8 @@ #define MX6Q_SABRELITE_USB_OTG_PWR IMX_GPIO_NR(3, 22) #define MX6Q_SABRELITE_CAP_TCH_INT1 IMX_GPIO_NR(1, 9) #define MX6Q_SABRELITE_USB_HUB_RESET IMX_GPIO_NR(7, 12) +#define MX6Q_SABRELITE_CAN1_STBY IMX_GPIO_NR(1, 2) +#define MX6Q_SABRELITE_CAN1_EN IMX_GPIO_NR(1, 4) #define MX6Q_SABRELITE_SD3_WP_PADCFG (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_MED | \ @@ -106,9 +108,9 @@ static iomux_v3_cfg_t mx6q_sabrelite_pads[] = { /* CAN1 */ MX6Q_PAD_KEY_ROW2__CAN1_RXCAN, MX6Q_PAD_KEY_COL2__CAN1_TXCAN, - MX6Q_PAD_ENET_CRS_DV__GPIO_1_25, /* STNDBY */ - MX6Q_PAD_ENET_RXD1__GPIO_1_26, /* NERR */ - MX6Q_PAD_ENET_RXD0__GPIO_1_27, /* Enable */ + MX6Q_PAD_GPIO_2__GPIO_1_2, /* STNDBY */ + MX6Q_PAD_GPIO_7__GPIO_1_7, /* NERR */ + MX6Q_PAD_GPIO_4__GPIO_1_4, /* Enable */ /* CCM */ MX6Q_PAD_GPIO_0__CCM_CLKO, /* SGTL500 sys_mclk */ @@ -582,10 +584,37 @@ static void __init imx6q_sabrelite_init_usb(void) mx6_usb_dr_init(); mx6_usb_h1_init(); } + +static struct gpio mx6q_sabrelite_flexcan_gpios[] = { + { MX6Q_SABRELITE_CAN1_EN, GPIOF_OUT_INIT_LOW, "flexcan1-en" }, + { MX6Q_SABRELITE_CAN1_STBY, GPIOF_OUT_INIT_LOW, "flexcan1-stby" }, +}; + +static void mx6q_sabrelite_flexcan0_switch(int enable) +{ + if (enable) { + gpio_set_value(MX6Q_SABRELITE_CAN1_EN, 1); + gpio_set_value(MX6Q_SABRELITE_CAN1_STBY, 1); + } else { + gpio_set_value(MX6Q_SABRELITE_CAN1_EN, 0); + gpio_set_value(MX6Q_SABRELITE_CAN1_STBY, 0); + } +} + +static const struct flexcan_platform_data + mx6q_sabrelite_flexcan0_pdata __initconst = { + .transceiver_switch = mx6q_sabrelite_flexcan0_switch, +}; + static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = { .reserved_mem_size = SZ_128M, }; +static struct imx_asrc_platform_data imx_asrc_data = { + .channel_bits = 4, + .clk_map_ver = 2, +}; + static struct ipuv3_fb_platform_data sabrelite_fb_data[] = { { /*fb0*/ .disp_dev = "ldb", @@ -885,10 +914,12 @@ static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, static void __init mx6_sabrelite_board_init(void) { int i; + int ret; mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_pads, ARRAY_SIZE(mx6q_sabrelite_pads)); + gp_reg_id = sabrelite_dvfscore_data.reg_id; mx6q_sabrelite_init_uart(); imx6q_add_mxc_hdmi_core(&hdmi_core_data); @@ -930,6 +961,10 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_vpu(); imx6q_init_audio(); platform_device_register(&sabrelite_vmmc_reg_devices); + imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); + imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk"); + imx6q_add_asrc(&imx_asrc_data); + /* release USB Hub reset */ gpio_set_value(MX6Q_SABRELITE_USB_HUB_RESET, 1); @@ -953,6 +988,13 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_hdmi_soc(); imx6q_add_hdmi_soc_dai(); + + ret = gpio_request_array(mx6q_sabrelite_flexcan_gpios, + ARRAY_SIZE(mx6q_sabrelite_flexcan_gpios)); + if (ret) + pr_err("failed to request flexcan1-gpios: %d\n", ret); + else + imx6q_add_flexcan0(&mx6q_sabrelite_flexcan0_pdata); } extern void __iomem *twd_base; diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 01469475b8a9..12a8d3583921 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -37,8 +37,11 @@ #define __INIT_CLK_DEBUG(n) #endif +extern u32 arm_max_freq; extern int mxc_jtag_enabled; extern struct cpu_op *(*get_cpu_op)(int *op); +extern int mx6_set_cpu_voltage(u32 cpu_volt); + extern int lp_high_freq; extern int lp_med_freq; @@ -67,6 +70,12 @@ static int cpu_op_nr; #define AUDIO_VIDEO_MIN_CLK_FREQ 650000000 #define AUDIO_VIDEO_MAX_CLK_FREQ 1300000000 +/* We need to check the exp status again after timer expiration, + * as there might be interrupt coming between the first time exp + * and the time reading, then the time reading may be several ms + * after the exp checking due to the irq handle, so we need to + * check it to make sure the exp return the right value after + * timer expiration. */ #define WAIT(exp, timeout) \ ({ \ struct timespec nstimeofday; \ @@ -76,7 +85,8 @@ static int cpu_op_nr; while (!(exp)) { \ getnstimeofday(&curtime); \ if ((curtime.tv_nsec - nstimeofday.tv_nsec) > (timeout)) { \ - result = 0; \ + if (!(exp)) \ + result = 0; \ break; \ } \ } \ @@ -906,7 +916,7 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) int i; u32 div; u32 parent_rate; - struct clk *old_parent = pll1_sw_clk.parent; + for (i = 0; i < cpu_op_nr; i++) { if (rate == cpu_op_tbl[i].cpu_rate) @@ -915,23 +925,14 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) if (i >= cpu_op_nr) return -EINVAL; - if (rate <= clk_get_rate(&pll2_pfd_400M)) { - /* - * Move pll1_sw_clk to PLL2_PFD_400M - * so that we can disable PLL1. - */ - if (pll2_pfd_400M.usecount == 0) - pll2_pfd_400M.enable(&pll2_pfd_400M); - pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M); - pll1_sw_clk.parent = &pll2_pfd_400M; - } else { - /* Rate is above 400MHz. We may need to relock PLL1. */ - pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk); - if (pll1_sys_main_clk.usecount == 0) - pll1_sys_main_clk.enable(&pll1_sys_main_clk); + if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { + /* Change the PLL1 rate. */ + if (pll2_pfd_400M.usecount != 0) + pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M); + else + pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk); pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate); pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); - pll1_sw_clk.parent = &pll1_sys_main_clk; } parent_rate = clk_get_rate(clk->parent); @@ -948,15 +949,6 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) __raw_writel(div - 1, MXC_CCM_CACRR); - /* Increment current parent's usecount. */ - pll1_sw_clk.parent->usecount++; - - /* Decrement the current parent's usecount */ - old_parent->usecount--; - - if (old_parent->usecount == 0) - old_parent->disable(old_parent); - return 0; } @@ -4214,8 +4206,8 @@ static int _clk_gpu2d_core_set_rate(struct clk *clk, unsigned long rate) return -EINVAL; reg = __raw_readl(MXC_CCM_CBCMR); - reg &= ~MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK; - reg |= (div - 1) << MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET; + reg &= ~MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET; __raw_writel(reg, MXC_CCM_CBCMR); return 0; @@ -4645,6 +4637,33 @@ static struct clk clko_clk = { .round_rate = _clk_clko_round_rate, }; +static struct clk perfmon0_clk = { + __INIT_CLK_DEBUG(perfmon0_clk) + .parent = &mmdc_ch0_axi_clk[0], + .enable = _clk_enable1, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, + .disable = _clk_disable1, +}; + +static struct clk perfmon1_clk = { + __INIT_CLK_DEBUG(perfmon1_clk) + .parent = &ipu1_clk, + .enable = _clk_enable1, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET, + .disable = _clk_disable1, +}; + +static struct clk perfmon2_clk = { + __INIT_CLK_DEBUG(perfmon2_clk) + .parent = &mmdc_ch0_axi_clk[0], + .enable = _clk_enable1, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET, + .disable = _clk_disable1, +}; + static struct clk dummy_clk = { .id = 0, }; @@ -4770,6 +4789,9 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, NULL, aips_tz2_clk), _REGISTER_CLOCK(NULL, NULL, aips_tz1_clk), _REGISTER_CLOCK(NULL, "clko_clk", clko_clk), + _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk), + _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk), + _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk), }; @@ -4857,12 +4879,12 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_set_rate(&gpu3d_core_clk[0], 528000000); /* - * FIXME: asrc needs to use asrc_serial(spdif1) clock to do sample rate convertion, - * however we found it only works when set to 1.5M clock and the - * parent is pll3_sw_clk. + * FIXME: asrc needs to use asrc_serial(spdif1) clock to do sample + * rate convertion and this clock frequency can not be too high, set + * it to the minimum value 7.5Mhz to make asrc work properly. */ clk_set_parent(&asrc_clk[1], &pll3_sw_clk); - clk_set_rate(&asrc_clk[1], 1500000); + clk_set_rate(&asrc_clk[1], 7500000); /* set the NAND to 11MHz. Too fast will cause dma timeout. */ clk_set_rate(&enfc_clk, enfc_clk.round_rate(&enfc_clk, 11000000)); @@ -4909,6 +4931,10 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, base = ioremap(GPT_BASE_ADDR, SZ_4K); mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT); + /* Set the core to max frequency requested. */ + mx6_set_cpu_voltage(cpu_op_tbl[0].cpu_voltage); + clk_set_rate(&cpu_clk, cpu_op_tbl[0].pll_rate); + lp_high_freq = 0; lp_med_freq = 0; diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c index f2b934519cfe..e392a3cbef10 100644 --- a/arch/arm/mach-mx6/cpu.c +++ b/arch/arm/mach-mx6/cpu.c @@ -29,6 +29,8 @@ #include <asm/mach/map.h> #include "crm_regs.h" +#include "cpu_op-mx6.h" + void *mx6_wait_in_iram_base; void (*mx6_wait_in_iram)(void *ccm_base); @@ -37,6 +39,7 @@ extern void mx6_wait(void); struct cpu_op *(*get_cpu_op)(int *op); bool enable_wait_mode; +u32 arm_max_freq = CPU_AT_1GHz; void __iomem *gpc_base; void __iomem *ccm_base; @@ -128,3 +131,18 @@ static int __init enable_wait(char *p) } early_param("enable_wait_mode", enable_wait); +static int __init arm_core_max(char *p) +{ + if (memcmp(p, "1000", 4) == 0) { + arm_max_freq = CPU_AT_1GHz; + p += 4; + } else if (memcmp(p, "800", 3) == 0) { + arm_max_freq = CPU_AT_800MHz; + p += 3; + } + return 0; +} + +early_param("arm_freq", arm_core_max); + + diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c index c0694fd71e3b..30a4346282ea 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.c +++ b/arch/arm/mach-mx6/cpu_op-mx6.c @@ -15,14 +15,16 @@ #include <linux/kernel.h> #include <mach/hardware.h> #include <mach/mxc_dvfs.h> +#include "cpu_op-mx6.h" extern struct cpu_op *(*get_cpu_op)(int *op); extern struct dvfs_op *(*get_dvfs_core_op)(int *wp); extern void (*set_num_cpu_op)(int num); +extern u32 arm_max_freq; static int num_cpu_op; /* working point(wp): 0 - 1GHzMHz; 1 - 800MHz, 3 - 400MHz, 4 - 160MHz */ -static struct cpu_op mx6_cpu_op[] = { +static struct cpu_op mx6_cpu_op_1G[] = { { .pll_rate = 996000000, .cpu_rate = 996000000, @@ -31,7 +33,7 @@ static struct cpu_op mx6_cpu_op[] = { .mfd = 11, .mfn = 5, .cpu_podf = 0, - .cpu_voltage = 1150000,}, + .cpu_voltage = 1225000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, @@ -40,35 +42,72 @@ static struct cpu_op mx6_cpu_op[] = { .mfd = 2, .mfn = 1, .cpu_podf = 0, - .cpu_voltage = 1150000,}, + .cpu_voltage = 1100000,}, { - .pll_rate = 396000000, + .pll_rate = 792000000, .cpu_rate = 396000000, - .cpu_podf = 0, - .cpu_voltage = 1050000,}, + .cpu_podf = 1, + .cpu_voltage = 950000,}, { - .pll_rate = 396000000, + .pll_rate = 792000000, .cpu_rate = 198000000, - .cpu_podf = 1, - .cpu_voltage = 900000,}, + .cpu_podf = 3, + .cpu_voltage = 850000,}, }; -static struct dvfs_op dvfs_core_setpoint[] = { +static struct cpu_op mx6_cpu_op[] = { + { + .pll_rate = 792000000, + .cpu_rate = 792000000, + .pdf = 0, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 0, + .cpu_voltage = 1100000,}, + { + .pll_rate = 792000000, + .cpu_rate = 396000000, + .cpu_podf = 1, + .cpu_voltage = 950000,}, + { + .pll_rate = 792000000, + .cpu_rate = 198000000, + .cpu_podf = 3, + .cpu_voltage = 850000,}, +}; + +static struct dvfs_op dvfs_core_setpoint_1G[] = { {33, 14, 33, 10, 10, 0x08}, /* 1GHz*/ {30, 12, 33, 10, 10, 0x08}, /* 800MHz */ {28, 8, 33, 10, 10, 0x08}, /* 400MHz */ - {20, 0, 33, 20, 10, 0x08} }; /* 167MHz*/ + {20, 0, 33, 20, 10, 0x08} }; /* 200MHz*/ + +static struct dvfs_op dvfs_core_setpoint[] = { + {33, 14, 33, 10, 10, 0x08}, /* 800MHz */ + {26, 8, 33, 10, 10, 0x08}, /* 400MHz */ + {20, 0, 33, 20, 10, 0x08} }; /* 200MHz*/ static struct dvfs_op *mx6_get_dvfs_core_table(int *wp) { - *wp = ARRAY_SIZE(dvfs_core_setpoint); - return dvfs_core_setpoint; + if (arm_max_freq == CPU_AT_1GHz) { + *wp = ARRAY_SIZE(dvfs_core_setpoint_1G); + return dvfs_core_setpoint_1G; + } else { + *wp = ARRAY_SIZE(dvfs_core_setpoint); + return dvfs_core_setpoint; + } } struct cpu_op *mx6_get_cpu_op(int *op) { - *op = num_cpu_op; - return mx6_cpu_op; + if (arm_max_freq == CPU_AT_1GHz) { + *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op_1G); + return mx6_cpu_op_1G; + } else { + *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op); + return mx6_cpu_op; + } } void mx6_set_num_cpu_op(int num) @@ -82,7 +121,6 @@ void mx6_cpu_op_init(void) get_cpu_op = mx6_get_cpu_op; set_num_cpu_op = mx6_set_num_cpu_op; - num_cpu_op = ARRAY_SIZE(mx6_cpu_op); get_dvfs_core_op = mx6_get_dvfs_core_table; } diff --git a/arch/arm/mach-mx6/cpu_op-mx6.h b/arch/arm/mach-mx6/cpu_op-mx6.h index f13b26962bde..77e8222c5d38 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.h +++ b/arch/arm/mach-mx6/cpu_op-mx6.h @@ -11,4 +11,7 @@ * http://www.gnu.org/copyleft/gpl.html */ +#define CPU_AT_800MHz 0 +#define CPU_AT_1GHz 1 + void mx6_cpu_op_init(void); diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h index e46c97ef927c..e87f9c0d7e7f 100644 --- a/arch/arm/mach-mx6/devices-imx6q.h +++ b/arch/arm/mach-mx6/devices-imx6q.h @@ -189,3 +189,8 @@ extern const struct imx_flexcan_data imx6q_flexcan_data[] __initconst; extern const struct imx_mipi_csi2_data imx6q_mipi_csi2_data __initconst; #define imx6q_add_mipi_csi2(pdata) \ imx_add_mipi_csi2(&imx6q_mipi_csi2_data, pdata) + +extern const struct imx_perfmon_data imx6q_perfmon_data[] __initconst; +#define imx6q_add_perfmon(id) \ + imx_add_perfmon(&imx6q_perfmon_data[id]) + diff --git a/arch/arm/mach-mx6/mx6_fec.c b/arch/arm/mach-mx6/mx6_fec.c index 32e858355390..b2aa45b3c510 100644 --- a/arch/arm/mach-mx6/mx6_fec.c +++ b/arch/arm/mach-mx6/mx6_fec.c @@ -25,7 +25,7 @@ #include <asm/mach/arch.h> #include "devices-imx6q.h" -#define HW_OCOTP_MACn(n) (0x00000250 + (n) * 0x10) +#define HW_OCOTP_MACn(n) (0x00000620 + (n) * 0x10) static int fec_get_mac_addr(unsigned char *mac) { diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c index 36e35cc062c5..bdf337144554 100644 --- a/arch/arm/mach-mx6/pm.c +++ b/arch/arm/mach-mx6/pm.c @@ -186,11 +186,11 @@ static int mx6_suspend_enter(suspend_state_t state) wake_irq_isr[0] = __raw_readl(gpc_base + GPC_ISR1_OFFSET) & gpc_wake_irq[0]; wake_irq_isr[1] = __raw_readl(gpc_base + - GPC_ISR1_OFFSET) & gpc_wake_irq[1]; + GPC_ISR2_OFFSET) & gpc_wake_irq[1]; wake_irq_isr[2] = __raw_readl(gpc_base + - GPC_ISR1_OFFSET) & gpc_wake_irq[2]; + GPC_ISR3_OFFSET) & gpc_wake_irq[2]; wake_irq_isr[3] = __raw_readl(gpc_base + - GPC_ISR1_OFFSET) & gpc_wake_irq[3]; + GPC_ISR4_OFFSET) & gpc_wake_irq[3]; if (wake_irq_isr[0] | wake_irq_isr[1] | wake_irq_isr[2] | wake_irq_isr[3]) { printk(KERN_INFO "There are wakeup irq pending,system resume!\n"); diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index 801826c0fecc..69e761c00402 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -124,7 +124,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) /* dormant mode, need to power off the arm core */ if (stop_mode == 2) { - __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET); + __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET); __raw_writel(0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET); __raw_writel(0x1, gpc_base + GPC_CNTR_OFFSET); /* Enable weak 2P5 linear regulator */ @@ -134,7 +134,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) /* Make sure ARM and SOC domain has same voltage */ anatop_val = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET); anatop_val &= ~(0x1f << 18); - anatop_val |= 0xc; + anatop_val |= (anatop_val & 0x1f) << 18; __raw_writel(anatop_val, anatop_base + ANATOP_REG_CORE_OFFSET); __raw_writel(__raw_readl(MXC_CCM_CCR) | MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR); ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM; @@ -243,3 +243,4 @@ int mxs_reset_block(void __iomem *hwreg, int just_enable) } return r; } +EXPORT_SYMBOL(mxs_reset_block); diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c index de84a4ded23b..957b021e0a73 100644 --- a/arch/arm/mach-mx6/usb_dr.c +++ b/arch/arm/mach-mx6/usb_dr.c @@ -365,6 +365,19 @@ static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata) #ifdef CONFIG_USB_GADGET_ARC /* Beginning of device related operation for DR port */ +static void _gadget_discharge_dp(bool enable) +{ + void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR); + if (enable) { + __raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_SET); + __raw_writel(BF_USBPHY_DEBUG_HSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_SET); + } else { + __raw_writel(BF_USBPHY_DEBUG_ENHSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_CLR); + __raw_writel(BF_USBPHY_DEBUG_HSTPULLDOWN(0x2), phy_reg + HW_USBPHY_DEBUG_CLR); + } + +} + static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { __phy_lowpower_suspend(pdata, enable, ENABLED_BY_DEVICE); @@ -450,6 +463,7 @@ void __init mx6_usb_dr_init(void) dr_utmi_config.wake_up_enable = _device_wakeup_enable; dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend; dr_utmi_config.is_wakeup_event = _is_device_wakeup; + dr_utmi_config.gadget_discharge_dp = _gadget_discharge_dp; dr_utmi_config.wakeup_pdata = &dr_wakeup_config; dr_utmi_config.wakeup_handler = device_wakeup_handler; pdev = imx6q_add_fsl_usb2_udc(&dr_utmi_config); diff --git a/arch/arm/plat-mxc/devices/platform-imx-perfmon.c b/arch/arm/plat-mxc/devices/platform-imx-perfmon.c index faec9b0e1111..25d1bf582de2 100644 --- a/arch/arm/plat-mxc/devices/platform-imx-perfmon.c +++ b/arch/arm/plat-mxc/devices/platform-imx-perfmon.c @@ -21,6 +21,7 @@ #include <mach/hardware.h> #include <mach/devices-common.h> #include <linux/fsl_devices.h> +#include <mach/iomux-v3.h> #ifdef CONFIG_SOC_IMX50 static struct mxs_perfmon_bit_config @@ -51,10 +52,95 @@ const struct imx_perfmon_data imx50_perfmon_data = { }; #endif +#ifdef CONFIG_SOC_IMX6Q +static struct mxs_perfmon_bit_config +mx6q_perfmon1_bit_config[] = { + {.field = (1 << 0), .name = "MID0-GPU_3D" }, + {.field = (1 << 1), .name = "MID1-GPU_2D" }, + {.field = (1 << 2), .name = "MID2-VDOA" }, + {.field = (1 << 3), .name = "MID3-Unused" }, + {.field = (1 << 4), .name = "MID4-OPENVG" } +}; + +static struct mxs_perfmon_bit_config +mx6q_perfmon2_bit_config[] = { + {.field = (1 << 0), .name = "MID0-IPU1.ld00" }, + {.field = (1 << 1), .name = "MID1-IPU1.ld01" }, + {.field = (1 << 2), .name = "MID2-IPU1.ld10" }, + {.field = (1 << 3), .name = "MID3-IPU1.ld11" } +}; + +static struct mxs_perfmon_bit_config +mx6q_perfmon3_bit_config[] = { + {.field = (1 << 0), .name = "MID0-CORES" }, + {.field = (1 << 1), .name = "MID1-L2-BUF" }, + {.field = (1 << 2), .name = "MID2-Unused" }, + {.field = (1 << 3), .name = "MID3-L2-EVIC" }, + {.field = (1 << 4), .name = "MID4-Unused" } +}; + +static int init; + +static void platform_perfmon_init(void) +{ + if (init) + return; + + /* GPR11 bit[16] is the clock enable bit for perfmon */ + mxc_iomux_set_gpr_register(11, 16, 1, 1); + init = true; +} + +static void platform_perfmon_exit(void) +{ + if (!init) + return; + + /* GPR11 bit[16] is the clock enable bit for perfmon */ + mxc_iomux_set_gpr_register(11, 16, 1, 0); + init = false; +} + +struct mxs_platform_perfmon_data mxc_perfmon_data1 = { + .bit_config_tab = mx6q_perfmon1_bit_config, + .bit_config_cnt = ARRAY_SIZE(mx6q_perfmon1_bit_config), + .plt_init = platform_perfmon_init, + .plt_exit = platform_perfmon_exit, +}; + +struct mxs_platform_perfmon_data mxc_perfmon_data2 = { + .bit_config_tab = mx6q_perfmon2_bit_config, + .bit_config_cnt = ARRAY_SIZE(mx6q_perfmon2_bit_config), + .plt_init = platform_perfmon_init, +}; + +struct mxs_platform_perfmon_data mxc_perfmon_data3 = { + .bit_config_tab = mx6q_perfmon3_bit_config, + .bit_config_cnt = ARRAY_SIZE(mx6q_perfmon3_bit_config), + .plt_init = platform_perfmon_init, +}; + +const struct imx_perfmon_data imx6q_perfmon_data[3] = { + { + .iobase = IP2APB_PERFMON1_BASE_ADDR, + .pdata = &mxc_perfmon_data1, + }, + { + .iobase = IP2APB_PERFMON2_BASE_ADDR, + .pdata = &mxc_perfmon_data2, + }, + { + .iobase = IP2APB_PERFMON3_BASE_ADDR, + .pdata = &mxc_perfmon_data3, + } +}; +#endif struct platform_device *__init imx_add_perfmon( const struct imx_perfmon_data *data) { + static int id; + struct resource res[] = { { .start = data->iobase, @@ -63,7 +149,7 @@ struct platform_device *__init imx_add_perfmon( } }; - return imx_add_platform_device("mxs-perfmon", 0, + return imx_add_platform_device("mxs-perfmon", id++, res, ARRAY_SIZE(res), data->pdata, sizeof(struct mxs_platform_perfmon_data)); } diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c index a8812d8ef612..006530416edd 100644 --- a/arch/arm/plat-mxc/dvfs_core.c +++ b/arch/arm/plat-mxc/dvfs_core.c @@ -820,7 +820,7 @@ void dump_dvfs_core_regs() __raw_readl(dvfs_data->membase + MXC_DVFSCORE_THRS + 0x40)); } - +#if 0 static ssize_t downthreshold_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -856,7 +856,7 @@ static ssize_t downcount_store(struct device *dev, return size; } - +#endif static ssize_t dvfs_enable_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -903,9 +903,6 @@ static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, dvfs_enable_show, dvfs_enable_store); static DEVICE_ATTR(show_regs, S_IRUGO, dvfs_regs_show, dvfs_regs_store); -static DEVICE_ATTR(down_threshold, 0644, downthreshold_show, - downthreshold_store); -static DEVICE_ATTR(down_count, 0644, downcount_show, downcount_store); /*! * This is the probe routine for the DVFS driver. @@ -996,20 +993,6 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev) goto err3; } - err = sysfs_create_file(&dvfs_dev->kobj, &dev_attr_down_threshold.attr); - if (err) { - printk(KERN_ERR - "DVFS: Unable to register sysdev entry for DVFS"); - goto err3; - } - - err = sysfs_create_file(&dvfs_dev->kobj, &dev_attr_down_count.attr); - if (err) { - printk(KERN_ERR - "DVFS: Unable to register sysdev entry for DVFS"); - goto err3; - } - /* Set the current working point. */ cpu_op_tbl = get_cpu_op(&cpu_op_nr); old_op = 0; diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h index 9ef53aba40f8..1862c70ac13d 100644 --- a/arch/arm/plat-mxc/include/mach/esdhc.h +++ b/arch/arm/plat-mxc/include/mach/esdhc.h @@ -25,6 +25,7 @@ struct esdhc_platform_data { unsigned int always_present; unsigned int support_18v; unsigned int support_8bit; + unsigned int keep_power_at_suspend; unsigned int delay_line; int (*platform_pad_change)(int clock); }; diff --git a/arch/arm/plat-mxc/include/mach/imx-uart.h b/arch/arm/plat-mxc/include/mach/imx-uart.h index 15b1a6c03f94..21dcdaf29512 100644 --- a/arch/arm/plat-mxc/include/mach/imx-uart.h +++ b/arch/arm/plat-mxc/include/mach/imx-uart.h @@ -22,6 +22,7 @@ #define IMXUART_HAVE_RTSCTS (1<<0) #define IMXUART_IRDA (1<<1) #define IMXUART_USE_DCEDTE (1<<2) +#define IMXUART_SDMA (1<<3) struct imxuart_platform_data { int (*init)(struct platform_device *pdev); @@ -31,6 +32,8 @@ struct imxuart_platform_data { unsigned int irda_inv_rx:1; unsigned int irda_inv_tx:1; unsigned short transceiver_delay; + unsigned int dma_req_rx; + unsigned int dma_req_tx; }; #endif diff --git a/arch/arm/plat-mxc/include/mach/ipu-v3.h b/arch/arm/plat-mxc/include/mach/ipu-v3.h index 480b4ea338e7..dd18f36c3ff2 100644 --- a/arch/arm/plat-mxc/include/mach/ipu-v3.h +++ b/arch/arm/plat-mxc/include/mach/ipu-v3.h @@ -136,7 +136,12 @@ typedef union { uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; + uint32_t outh_resize_ratio; + uint32_t outv_resize_ratio; uint32_t csi; + uint32_t mipi_id; + uint32_t mipi_vc; + bool mipi_en; } csi_prp_enc_mem; struct { uint32_t in_width; @@ -163,10 +168,21 @@ typedef union { uint32_t out_width; uint32_t out_height; uint32_t out_pixel_fmt; + uint32_t outh_resize_ratio; + uint32_t outv_resize_ratio; bool graphics_combine_en; bool global_alpha_en; bool key_color_en; + uint32_t in_g_pixel_fmt; + uint8_t alpha; + uint32_t key_color; + bool alpha_chan_en; + ipu_motion_sel motion_sel; + enum v4l2_field field_fmt; uint32_t csi; + uint32_t mipi_id; + uint32_t mipi_vc; + bool mipi_en; } csi_prp_vf_mem; struct { uint32_t in_width; diff --git a/arch/arm/plat-mxc/include/mach/mipi_csi2.h b/arch/arm/plat-mxc/include/mach/mipi_csi2.h index b2660836c295..7679027a2770 100644 --- a/arch/arm/plat-mxc/include/mach/mipi_csi2.h +++ b/arch/arm/plat-mxc/include/mach/mipi_csi2.h @@ -24,32 +24,45 @@ #define CSI2_N_LANES (0x004/4) #define CSI2_PHY_SHUTDOWNZ (0x008/4) #define CSI2_DPHY_RSTZ (0x00c/4) -#define CSI2_RESETN (0x010/4) +#define CSI2_RESETN (0x010/4) #define CSI2_PHY_STATE (0x014/4) #define CSI2_DATA_IDS_1 (0x018/4) #define CSI2_DATA_IDS_2 (0x01c/4) -#define CSI2_ERR1 (0x020/4) -#define CSI2_ERR2 (0x024/4) -#define CSI2_MSK1 (0x028/4) -#define CSI2_MSK2 (0x02c/4) +#define CSI2_ERR1 (0x020/4) +#define CSI2_ERR2 (0x024/4) +#define CSI2_MSK1 (0x028/4) +#define CSI2_MSK2 (0x02c/4) #define CSI2_PHY_TST_CTRL0 (0x030/4) #define CSI2_PHY_TST_CTRL1 (0x034/4) #define CSI2_SFT_RESET (0xf00/4) /* mipi data type */ -#define MIPI_DT_YUV422 0x1e -#define MIPI_DT_RGB444 0x20 -#define MIPI_DT_RGB555 0x21 -#define MIPI_DT_RGB565 0x22 -#define MIPI_DT_RGB888 0x24 -#define MIPI_DT_RAW8 0x2a -#define MIPI_DT_RAW10 0x2b +#define MIPI_DT_YUV420 0x18 /* YYY.../UYVY.... */ +#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY... */ +#define MIPI_DT_YUV422 0x1e /* UYVY... */ +#define MIPI_DT_RGB444 0x20 +#define MIPI_DT_RGB555 0x21 +#define MIPI_DT_RGB565 0x22 +#define MIPI_DT_RGB666 0x23 +#define MIPI_DT_RGB888 0x24 +#define MIPI_DT_RAW6 0x28 +#define MIPI_DT_RAW7 0x29 +#define MIPI_DT_RAW8 0x2a +#define MIPI_DT_RAW10 0x2b +#define MIPI_DT_RAW12 0x2c +#define MIPI_DT_RAW14 0x2d struct mipi_csi2_info; /* mipi csi2 API */ struct mipi_csi2_info *mipi_csi2_get_info(void); +bool mipi_csi2_enable(struct mipi_csi2_info *info); + +bool mipi_csi2_disable(struct mipi_csi2_info *info); + +bool mipi_csi2_get_status(struct mipi_csi2_info *info); + int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info); unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info); @@ -59,7 +72,7 @@ unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info); unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info); unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info, - unsigned int datatype); + unsigned int datatype); unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info); diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index bc6515bb9494..b8ad52fac513 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -90,6 +90,8 @@ extern unsigned int system_rev; board_is_rev(IMX_BOARD_REV_1)) #define board_is_mx6q_sabre_lite() (cpu_is_mx6q() && \ board_is_rev(IMX_BOARD_REV_2)) +#define board_is_mx6q_sabre_auto() (cpu_is_mx6q() && \ + board_is_rev(IMX_BOARD_REV_3)) #endif #ifndef __ASSEMBLY__ diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h index 7859f113cd2c..2f9a7ad7a1aa 100644 --- a/arch/arm/plat-mxc/include/mach/uncompress.h +++ b/arch/arm/plat-mxc/include/mach/uncompress.h @@ -127,6 +127,9 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) case MACH_TYPE_MX6Q_SABRELITE: uart_base = MX6Q_UART2_BASE_ADDR; break; + case MACH_TYPE_MX6Q_SABREAUTO: + uart_base = MX6Q_UART4_BASE_ADDR; + break; default: break; } diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 7dd48b11ee4c..881969c36949 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -264,6 +264,8 @@ struct sdma_channel { struct dma_async_tx_descriptor desc; dma_cookie_t last_completed; enum dma_status status; + unsigned int chn_count; + unsigned int chn_real_count; }; #define IMX_DMA_SG_LOOP (1 << 0) @@ -467,6 +469,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) struct sdma_buffer_descriptor *bd; int i, error = 0; + sdmac->chn_real_count = 0; /* * non loop mode. Iterate over all descriptors, collect * errors and call callback function @@ -476,6 +479,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) if (bd->mode.status & (BD_DONE | BD_RROR)) error = -EIO; + sdmac->chn_real_count += bd->mode.count; } if (error) @@ -483,9 +487,9 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac) else sdmac->status = DMA_SUCCESS; + sdmac->last_completed = sdmac->desc.cookie; if (sdmac->desc.callback) sdmac->desc.callback(sdmac->desc.callback_param); - sdmac->last_completed = sdmac->desc.cookie; } static void mxc_sdma_handle_channel(struct sdma_channel *sdmac) @@ -903,6 +907,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( goto err_out; } + sdmac->chn_count = 0; for_each_sg(sgl, sg, sg_len, i) { struct sdma_buffer_descriptor *bd = &sdmac->bd[i]; int param; @@ -919,6 +924,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( } bd->mode.count = count; + sdmac->chn_count += count; if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) { ret = -EINVAL; @@ -1081,7 +1087,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, last_used = chan->cookie; - dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0); + dma_set_tx_state(txstate, sdmac->last_completed, last_used, + sdmac->chn_count - sdmac->chn_real_count); return sdmac->status; } diff --git a/drivers/media/video/mxc/capture/Kconfig b/drivers/media/video/mxc/capture/Kconfig index 93d56057e31c..c9f3e3bcaec1 100644 --- a/drivers/media/video/mxc/capture/Kconfig +++ b/drivers/media/video/mxc/capture/Kconfig @@ -84,6 +84,14 @@ config MXC_CAMERA_OV5640_MIPI ---help--- If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here. +config MXC_CAMERA_OV8820_MIPI + tristate "OmniVision ov8820 camera support using mipi" + depends on !VIDEO_MXC_EMMA_CAMERA + depends on ARCH_MX6Q + select MXC_MIPI_CSI2 if ARCH_MX6Q + ---help--- + If you plan to use the ov8820 Camera with mipi interface in your MXC system, say Y here. + config MXC_CAMERA_OV5642 tristate "OmniVision ov5642 camera support" depends on !VIDEO_MXC_EMMA_CAMERA diff --git a/drivers/media/video/mxc/capture/Makefile b/drivers/media/video/mxc/capture/Makefile index d8633307a1dc..8dab021fa64f 100644 --- a/drivers/media/video/mxc/capture/Makefile +++ b/drivers/media/video/mxc/capture/Makefile @@ -40,6 +40,9 @@ obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera.o ov5640_camera_mipi-objs := ov5640_mipi.o sensor_clock.o obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o +ov8820_camera_mipi-objs := ov8820_mipi.o sensor_clock.o +obj-$(CONFIG_MXC_CAMERA_OV8820_MIPI) += ov8820_camera_mipi.o + ov5642_camera-objs := ov5642.o sensor_clock.o obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o diff --git a/drivers/media/video/mxc/capture/ipu_csi_enc.c b/drivers/media/video/mxc/capture/ipu_csi_enc.c index 71fd113df9e9..0261a7ecd212 100644 --- a/drivers/media/video/mxc/capture/ipu_csi_enc.c +++ b/drivers/media/video/mxc/capture/ipu_csi_enc.c @@ -131,15 +131,34 @@ static int csi_enc_setup(cam_data *cam) #ifdef CONFIG_MXC_MIPI_CSI2 mipi_csi2_info = mipi_csi2_get_info(); - ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); - csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); - if (cam->ipu == ipu_get_soc(ipu_id) && cam->csi == csi_id) { - params.csi_mem.mipi_en = true; - params.csi_mem.mipi_vc = mipi_csi2_get_virtual_channel(mipi_csi2_info); - params.csi_mem.mipi_id = mipi_csi2_get_datatype(mipi_csi2_info); - - mipi_csi2_pixelclk_enable(mipi_csi2_info); + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) { + params.csi_mem.mipi_en = true; + params.csi_mem.mipi_vc = + mipi_csi2_get_virtual_channel(mipi_csi2_info); + params.csi_mem.mipi_id = + mipi_csi2_get_datatype(mipi_csi2_info); + + mipi_csi2_pixelclk_enable(mipi_csi2_info); + } else { + params.csi_mem.mipi_en = false; + params.csi_mem.mipi_vc = 0; + params.csi_mem.mipi_id = 0; + } + } else { + params.csi_mem.mipi_en = false; + params.csi_mem.mipi_vc = 0; + params.csi_mem.mipi_id = 0; + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; } #endif @@ -275,13 +294,23 @@ static int csi_enc_disabling_tasks(void *private) cam->dummy_frame.paddress); cam->dummy_frame.vaddress = 0; } + #ifdef CONFIG_MXC_MIPI_CSI2 mipi_csi2_info = mipi_csi2_get_info(); - ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); - csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); - if (cam->ipu == ipu_get_soc(ipu_id) && cam->csi == csi_id) - mipi_csi2_pixelclk_disable(mipi_csi2_info); + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) + mipi_csi2_pixelclk_disable(mipi_csi2_info); + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } #endif ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_ENC, cam->csi, false, false); diff --git a/drivers/media/video/mxc/capture/ipu_prp_enc.c b/drivers/media/video/mxc/capture/ipu_prp_enc.c index 3ead6f1900a2..6710cba5d817 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_enc.c +++ b/drivers/media/video/mxc/capture/ipu_prp_enc.c @@ -20,7 +20,10 @@ */ #include <linux/dma-mapping.h> +#include <linux/platform_device.h> #include <linux/ipu.h> +#include <mach/devices-common.h> +#include <mach/mipi_csi2.h> #include "mxc_v4l2_capture.h" #include "ipu_prp_sw.h" @@ -68,6 +71,11 @@ static int prp_enc_setup(cam_data *cam) ipu_channel_params_t enc; int err = 0; dma_addr_t dummy = 0xdeadbeaf; +#ifdef CONFIG_MXC_MIPI_CSI2 + void *mipi_csi2_info; + int ipu_id; + int csi_id; +#endif CAMERA_TRACE("In prp_enc_setup\n"); if (!cam) { @@ -123,6 +131,39 @@ static int prp_enc_setup(cam_data *cam) return -EINVAL; } +#ifdef CONFIG_MXC_MIPI_CSI2 + mipi_csi2_info = mipi_csi2_get_info(); + + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) { + enc.csi_prp_enc_mem.mipi_en = true; + enc.csi_prp_enc_mem.mipi_vc = + mipi_csi2_get_virtual_channel(mipi_csi2_info); + enc.csi_prp_enc_mem.mipi_id = + mipi_csi2_get_datatype(mipi_csi2_info); + + mipi_csi2_pixelclk_enable(mipi_csi2_info); + } else { + enc.csi_prp_enc_mem.mipi_en = false; + enc.csi_prp_enc_mem.mipi_vc = 0; + enc.csi_prp_enc_mem.mipi_id = 0; + } + } else { + enc.csi_prp_enc_mem.mipi_en = false; + enc.csi_prp_enc_mem.mipi_vc = 0; + enc.csi_prp_enc_mem.mipi_id = 0; + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } +#endif + err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc); if (err != 0) { printk(KERN_ERR "ipu_init_channel %d\n", err); @@ -383,6 +424,11 @@ static int prp_enc_disabling_tasks(void *private) { cam_data *cam = (cam_data *) private; int err = 0; +#ifdef CONFIG_MXC_MIPI_CSI2 + void *mipi_csi2_info; + int ipu_id; + int csi_id; +#endif if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam); @@ -410,6 +456,25 @@ static int prp_enc_disabling_tasks(void *private) cam->dummy_frame.paddress); cam->dummy_frame.vaddress = 0; } + +#ifdef CONFIG_MXC_MIPI_CSI2 + mipi_csi2_info = mipi_csi2_get_info(); + + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) + mipi_csi2_pixelclk_disable(mipi_csi2_info); + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } +#endif + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_ENC, cam->csi, false, false); return err; diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c index 6e101748c576..121b328ad18b 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c +++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c @@ -24,6 +24,7 @@ #include <linux/ipu.h> #include <linux/mxcfb.h> #include <mach/hardware.h> +#include <mach/mipi_csi2.h> #include "mxc_v4l2_capture.h" #include "ipu_prp_sw.h" @@ -49,6 +50,11 @@ static int prpvf_start(void *private) u32 size = 2, temp = 0; int err = 0, i = 0; short *tmp, color; +#ifdef CONFIG_MXC_MIPI_CSI2 + void *mipi_csi2_info; + int ipu_id; + int csi_id; +#endif if (!cam) { printk(KERN_ERR "private is NULL\n"); @@ -132,6 +138,39 @@ static int prpvf_start(void *private) vf.csi_prp_vf_mem.out_pixel_fmt = vf_out_format; size = cam->win.w.width * cam->win.w.height * size; +#ifdef CONFIG_MXC_MIPI_CSI2 + mipi_csi2_info = mipi_csi2_get_info(); + + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) { + vf.csi_prp_vf_mem.mipi_en = true; + vf.csi_prp_vf_mem.mipi_vc = + mipi_csi2_get_virtual_channel(mipi_csi2_info); + vf.csi_prp_vf_mem.mipi_id = + mipi_csi2_get_datatype(mipi_csi2_info); + + mipi_csi2_pixelclk_enable(mipi_csi2_info); + } else { + vf.csi_prp_vf_mem.mipi_en = false; + vf.csi_prp_vf_mem.mipi_vc = 0; + vf.csi_prp_vf_mem.mipi_id = 0; + } + } else { + vf.csi_prp_vf_mem.mipi_en = false; + vf.csi_prp_vf_mem.mipi_vc = 0; + vf.csi_prp_vf_mem.mipi_id = 0; + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } +#endif + err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf); if (err != 0) goto out_5; @@ -320,6 +359,11 @@ static int prpvf_stop(void *private) int err = 0, i = 0; struct fb_info *fbi = NULL; struct fb_var_screeninfo fbvar; +#ifdef CONFIG_MXC_MIPI_CSI2 + void *mipi_csi2_info; + int ipu_id; + int csi_id; +#endif if (cam->overlay_active == false) return 0; @@ -363,6 +407,24 @@ static int prpvf_stop(void *private) fbvar.activate |= FB_ACTIVATE_FORCE; fb_set_var(fbi, &fbvar); +#ifdef CONFIG_MXC_MIPI_CSI2 + mipi_csi2_info = mipi_csi2_get_info(); + + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) + mipi_csi2_pixelclk_disable(mipi_csi2_info); + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } +#endif + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_VF, cam->csi, false, false); if (cam->vf_bufs_vaddr[0]) { diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c index ef7f33c27a65..99fa4eaecfac 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c +++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c @@ -21,6 +21,7 @@ #include <linux/dma-mapping.h> #include <linux/fb.h> #include <linux/ipu.h> +#include <mach/mipi_csi2.h> #include "mxc_v4l2_capture.h" #include "ipu_prp_sw.h" @@ -87,6 +88,11 @@ static int prpvf_start(void *private) u32 offset; u32 bpp, size = 3; int err = 0; +#ifdef CONFIG_MXC_MIPI_CSI2 + void *mipi_csi2_info; + int ipu_id; + int csi_id; +#endif if (!cam) { printk(KERN_ERR "private is NULL\n"); @@ -137,6 +143,39 @@ static int prpvf_start(void *private) vf.csi_prp_vf_mem.out_pixel_fmt = format; size = cam->win.w.width * cam->win.w.height * size; +#ifdef CONFIG_MXC_MIPI_CSI2 + mipi_csi2_info = mipi_csi2_get_info(); + + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) { + vf.csi_prp_vf_mem.mipi_en = true; + vf.csi_prp_vf_mem.mipi_vc = + mipi_csi2_get_virtual_channel(mipi_csi2_info); + vf.csi_prp_vf_mem.mipi_id = + mipi_csi2_get_datatype(mipi_csi2_info); + + mipi_csi2_pixelclk_enable(mipi_csi2_info); + } else { + vf.csi_prp_vf_mem.mipi_en = false; + vf.csi_prp_vf_mem.mipi_vc = 0; + vf.csi_prp_vf_mem.mipi_id = 0; + } + } else { + vf.csi_prp_vf_mem.mipi_en = false; + vf.csi_prp_vf_mem.mipi_vc = 0; + vf.csi_prp_vf_mem.mipi_id = 0; + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } +#endif + err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf); if (err != 0) goto out_4; @@ -304,6 +343,11 @@ static int prpvf_start(void *private) static int prpvf_stop(void *private) { cam_data *cam = (cam_data *) private; +#ifdef CONFIG_MXC_MIPI_CSI2 + void *mipi_csi2_info; + int ipu_id; + int csi_id; +#endif if (cam->overlay_active == false) return 0; @@ -316,6 +360,25 @@ static int prpvf_stop(void *private) ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true); ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); + +#ifdef CONFIG_MXC_MIPI_CSI2 + mipi_csi2_info = mipi_csi2_get_info(); + + if (mipi_csi2_info) { + if (mipi_csi2_get_status(mipi_csi2_info)) { + ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); + csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); + + if (cam->ipu == ipu_get_soc(ipu_id) + && cam->csi == csi_id) + mipi_csi2_pixelclk_disable(mipi_csi2_info); + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } +#endif + ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_VF, cam->csi, false, false); if (cam->vf_bufs_vaddr[0]) { diff --git a/drivers/media/video/mxc/capture/ov3640.c b/drivers/media/video/mxc/capture/ov3640.c index 24e12d78b1aa..e10190687d80 100644 --- a/drivers/media/video/mxc/capture/ov3640.c +++ b/drivers/media/video/mxc/capture/ov3640.c @@ -1391,6 +1391,9 @@ static int ov3640_probe(struct i2c_client *client, gpo_regulator = NULL; } + if (plat_data->io_init) + plat_data->io_init(); + if (plat_data->pwdn) plat_data->pwdn(0); diff --git a/drivers/media/video/mxc/capture/ov5640.c b/drivers/media/video/mxc/capture/ov5640.c index 69bbd2a678d5..6ed73ca85645 100644 --- a/drivers/media/video/mxc/capture/ov5640.c +++ b/drivers/media/video/mxc/capture/ov5640.c @@ -1424,6 +1424,9 @@ static int ov5640_probe(struct i2c_client *client, analog_regulator = NULL; } + if (plat_data->io_init) + plat_data->io_init(); + if (plat_data->pwdn) plat_data->pwdn(0); diff --git a/drivers/media/video/mxc/capture/ov5640_mipi.c b/drivers/media/video/mxc/capture/ov5640_mipi.c index 7618ab93019d..53b841956c46 100644 --- a/drivers/media/video/mxc/capture/ov5640_mipi.c +++ b/drivers/media/video/mxc/capture/ov5640_mipi.c @@ -102,251 +102,619 @@ struct sensor { } ov5640_data; static struct reg_value ov5640_setting_30fps_VGA_640_480[] = { - {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, {0x3103, 0x03, 0, 0}, - {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, {0x3630, 0x2e, 0, 0}, - {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0}, {0x3634, 0x44, 0, 0}, + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, - {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x04, 0, 0}, - {0x3601, 0x22, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a18, 0x00, 0, 0}, - {0x3a19, 0xf8, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3500, 0x00, 0, 0}, - {0x3501, 0x01, 0, 0}, {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, - {0x350b, 0x3f, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, - {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x3612, 0x49, 0, 0}, - {0x3618, 0x00, 0, 0}, {0x3034, 0x18, 0, 0}, {0x3035, 0x41, 0, 0}, - {0x3036, 0xa8, 0, 0}, {0x3708, 0x66, 0, 0}, {0x3709, 0x52, 0, 0}, - {0x370c, 0x03, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, - {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0}, - {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 5}, {0x3807, 0x9f, 0, 0}, - {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, - {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x58, 0, 0}, - {0x380e, 0x01, 0, 0}, {0x380f, 0xf0, 0, 0}, {0x3810, 0x00, 0, 0}, - {0x3811, 0x04, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x02, 0, 0}, - {0x3814, 0x71, 0, 0}, {0x3815, 0x35, 0, 0}, {0x3820, 0x40, 0, 0}, - {0x3821, 0x01, 0, 0}, {0x3824, 0x01, 0, 0}, {0x3a02, 0x01, 0, 0}, - {0x3a03, 0xf0, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbe, 0, 0}, - {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x74, 0, 0}, {0x3a0e, 0x01, 0, 0}, - {0x3a0d, 0x01, 0, 0}, {0x3a14, 0x01, 0, 0}, {0x3a15, 0xf0, 0, 0}, - {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4300, 0x3f, 0, 0}, - {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x4713, 0x02, 0, 0}, - {0x4750, 0x00, 0, 0}, {0x4751, 0x00, 0, 0}, {0x5000, 0x07, 0, 0}, - {0x5001, 0x23, 0, 0}, {0x501d, 0x00, 0, 0}, {0x501f, 0x00, 0, 0}, - {0x5684, 0x10, 0, 0}, {0x5685, 0xa0, 0, 0}, {0x5686, 0x0c, 0, 0}, - {0x5687, 0x78, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x5a21, 0x00, 0, 0}, - {0x5a24, 0x00, 0, 0}, {0x4837, 0x0a, 0, 0}, {0x3037, 0x01, 0, 0}, - {0x4800, 0x14, 0, 5}, {0x483b, 0xff, 0, 0}, {0x3007, 0xf7, 0, 0}, - {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0}, - {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, - {0x3c06, 0x1c, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, - {0x3c0a, 0x9c, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0b, 0x40, 0, 0}, - {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, - {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, - {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, - {0x5189, 0x75, 0, 0}, {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, - {0x518c, 0xb2, 0, 0}, {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, - {0x518f, 0x56, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, - {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, - {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, - {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, - {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, - {0x519e, 0x38, 0, 0}, {0x5381, 0x1c, 0, 0}, {0x5382, 0x5a, 0, 0}, - {0x5383, 0x06, 0, 5}, {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, - {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, - {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, - {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, - {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, - {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, - {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, - {0x4814, 0x00, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 10}, - {0x483b, 0x33, 0, 0}, {0x3007, 0xff, 0, 10}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0}, + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0}, + {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0}, + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0}, + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0}, + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0}, + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0}, + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0}, + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, + {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, + {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, + {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, + {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, }; static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = { - {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, {0x3103, 0x03, 0, 0}, - {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, {0x3630, 0x2e, 0, 0}, - {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0}, {0x3634, 0x44, 0, 0}, + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, - {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x04, 0, 0}, - {0x3601, 0x22, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a18, 0x00, 0, 0}, - {0x3a19, 0xf8, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3500, 0x00, 0, 0}, - {0x3501, 0x01, 0, 0}, {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, - {0x350b, 0x3f, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, - {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x3612, 0x49, 0, 0}, - {0x3618, 0x00, 0, 0}, {0x3034, 0x18, 0, 0}, {0x3035, 0x41, 0, 0}, - {0x3036, 0xa8, 0, 0}, {0x3708, 0x24, 0, 0}, {0x3709, 0x52, 0, 0}, - {0x370c, 0x03, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, - {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0}, - {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 5}, {0x3807, 0x9f, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, + {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0}, + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, - {0x380b, 0xf0, 0, 0}, {0x380c, 0x0a, 0, 0}, {0x380d, 0xda, 0, 0}, - {0x380e, 0x00, 0, 0}, {0x380f, 0xfc, 0, 0}, {0x3810, 0x00, 0, 0}, - {0x3811, 0x04, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x02, 0, 0}, - {0x3814, 0xf1, 0, 0}, {0x3815, 0xf1, 0, 0}, {0x3820, 0x41, 0, 0}, - {0x3821, 0x01, 0, 0}, {0x3824, 0x01, 0, 0}, {0x3a02, 0x01, 0, 0}, - {0x3a03, 0xf0, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x2e, 0, 0}, - {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xfc, 0, 0}, {0x3a0e, 0x01, 0, 0}, - {0x3a0d, 0x01, 0, 0}, {0x3a14, 0x01, 0, 0}, {0x3a15, 0xf0, 0, 0}, - {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4300, 0x3f, 0, 0}, - {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x4713, 0x02, 0, 0}, - {0x4750, 0x00, 0, 0}, {0x4751, 0x00, 0, 0}, {0x5000, 0x07, 0, 0}, - {0x5001, 0x23, 0, 0}, {0x501d, 0x00, 0, 0}, {0x501f, 0x00, 0, 0}, - {0x5684, 0x10, 0, 0}, {0x5685, 0xa0, 0, 0}, {0x5686, 0x0c, 0, 0}, - {0x5687, 0x78, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x5a21, 0x00, 0, 0}, - {0x5a24, 0x00, 0, 0}, {0x4837, 0x0a, 0, 0}, {0x3037, 0x01, 0, 0}, - {0x4800, 0x14, 0, 5}, {0x483b, 0xff, 0, 0}, {0x3007, 0xf7, 0, 0}, - {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0}, - {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0}, + {0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0}, + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0}, + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0}, + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0}, + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0}, + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0}, + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, + {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, + {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, + {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, + {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, +}; + +static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = { + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, + {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, + {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, + {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, - {0x3c06, 0x1c, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, - {0x3c0a, 0x9c, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0b, 0x40, 0, 0}, - {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, - {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, - {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, - {0x5189, 0x75, 0, 0}, {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, - {0x518c, 0xb2, 0, 0}, {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, - {0x518f, 0x56, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, - {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, - {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, - {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, - {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, - {0x519e, 0x38, 0, 0}, {0x5381, 0x1c, 0, 0}, {0x5382, 0x5a, 0, 0}, - {0x5383, 0x06, 0, 5}, {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, - {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, - {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, - {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, - {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, - {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, - {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, - {0x4814, 0x00, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 10}, - {0x483b, 0x33, 0, 0}, {0x3007, 0xff, 0, 10}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0}, + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0}, + {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0}, + {0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0}, + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0}, + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0}, + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0}, + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0}, + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0}, + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, + {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, + {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, + {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, + {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, +}; + +static struct reg_value ov5640_setting_30fps_PAL_720_576[] = { + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x12, 0, 0}, {0x3036, 0x38, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, + {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, + {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, + {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, + {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0}, + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, + {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0}, + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0}, + {0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0}, + {0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0}, + {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0}, + {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0}, + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0}, + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0}, + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0}, + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, + {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, + {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, + {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, + {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, }; static struct reg_value ov5640_setting_30fps_720P_1280_720[] = { - {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, {0x3103, 0x03, 0, 0}, - {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, {0x3630, 0x2e, 0, 0}, - {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0}, {0x3634, 0x44, 0, 0}, + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, - {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x04, 0, 0}, - {0x3601, 0x22, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a18, 0x00, 0, 0}, - {0x3a19, 0xf8, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3500, 0x00, 0, 0}, - {0x3501, 0x01, 0, 0}, {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, - {0x350b, 0x3f, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, - {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x3612, 0x49, 0, 0}, - {0x3618, 0x00, 0, 0}, {0x3034, 0x18, 0, 0}, {0x3035, 0x41, 0, 0}, - {0x3036, 0xa8, 0, 0}, {0x3708, 0x62, 0, 0}, {0x3709, 0x52, 0, 0}, - {0x370c, 0x03, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, + {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0}, + {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0}, - {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 5}, {0x3807, 0xa9, 0, 0}, + {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0}, {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0}, {0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0}, {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0}, - {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3820, 0x41, 0, 0}, - {0x3821, 0x01, 0, 0}, {0x3824, 0x01, 0, 0}, {0x3a02, 0x01, 0, 0}, - {0x3a03, 0xf0, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0}, + {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0}, + {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, + {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0}, - {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x01, 0, 0}, {0x3a15, 0xf0, 0, 0}, - {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4300, 0x3f, 0, 0}, - {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x4713, 0x02, 0, 0}, - {0x4750, 0x00, 0, 0}, {0x4751, 0x00, 0, 0}, {0x5000, 0x07, 0, 0}, - {0x5001, 0x23, 0, 0}, {0x501d, 0x00, 0, 0}, {0x501f, 0x00, 0, 0}, - {0x5684, 0x10, 0, 0}, {0x5685, 0xa0, 0, 0}, {0x5686, 0x0c, 0, 0}, - {0x5687, 0x78, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x5a21, 0x00, 0, 0}, - {0x5a24, 0x00, 0, 0}, {0x4837, 0x0a, 0, 0}, {0x3037, 0x01, 0, 0}, - {0x4800, 0x14, 0, 5}, {0x483b, 0xff, 0, 0}, {0x3007, 0xf7, 0, 0}, - {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0}, - {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0}, - {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, - {0x3c06, 0x1c, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, - {0x3c0a, 0x9c, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0b, 0x40, 0, 0}, - {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, - {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, - {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, - {0x5189, 0x75, 0, 0}, {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, - {0x518c, 0xb2, 0, 0}, {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, - {0x518f, 0x56, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, - {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, - {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, - {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, - {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, - {0x519e, 0x38, 0, 0}, {0x5381, 0x1c, 0, 0}, {0x5382, 0x5a, 0, 0}, - {0x5383, 0x06, 0, 5}, {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, - {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, - {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, - {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, - {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, - {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, - {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, - {0x4814, 0x00, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 10}, - {0x483b, 0x33, 0, 0}, {0x3007, 0xff, 0, 10}, + {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, + {0x4827, 0x16, 0, 0}, {0x4837, 0x0a, 0, 0}, {0x3824, 0x04, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0x83, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, + {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, + {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, + {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, + {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, }; static struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = { - {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, {0x3103, 0x03, 0, 0}, - {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, {0x3630, 0x2e, 0, 0}, - {0x3632, 0xe2, 0, 0}, {0x3633, 0x23, 0, 0}, {0x3634, 0x44, 0, 0}, + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x54, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, - {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x04, 0, 0}, - {0x3601, 0x22, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a18, 0x00, 0, 0}, - {0x3a19, 0xf8, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3500, 0x00, 0, 0}, - {0x3501, 0x01, 0, 0}, {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, - {0x350b, 0x3f, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, - {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x3612, 0x4b, 0, 0}, - {0x3618, 0x04, 0, 0}, {0x3034, 0x18, 0, 0}, {0x3035, 0x41, 0, 0}, - {0x3036, 0xa8, 0, 0}, {0x3708, 0x61, 0, 0}, {0x3709, 0x12, 0, 0}, - {0x370c, 0x03, 0, 0}, {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, + {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0}, + {0x3815, 0x11, 0, 0}, {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0}, {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, - {0x3805, 0xef, 0, 0}, {0x3806, 0x05, 0, 5}, {0x3807, 0xf2, 0, 0}, + {0x3805, 0xef, 0, 0}, {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0}, {0x380f, 0x60, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0}, - {0x3814, 0x11, 0, 0}, {0x3815, 0x11, 0, 0}, {0x3820, 0x40, 0, 0}, - {0x3821, 0x00, 0, 0}, {0x3824, 0x01, 0, 0}, {0x3a02, 0x01, 0, 0}, - {0x3a03, 0xf0, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x50, 0, 0}, + {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0}, + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x04, 0, 0}, + {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0}, {0x3a0e, 0x03, 0, 0}, - {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x01, 0, 0}, {0x3a15, 0xf0, 0, 0}, - {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4300, 0x3f, 0, 0}, - {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x4713, 0x02, 0, 0}, - {0x4750, 0x00, 0, 0}, {0x4751, 0x00, 0, 0}, {0x5000, 0x07, 0, 0}, - {0x5001, 0x23, 0, 0}, {0x501d, 0x00, 0, 0}, {0x501f, 0x00, 0, 0}, - {0x5684, 0x10, 0, 0}, {0x5685, 0xa0, 0, 0}, {0x5686, 0x0c, 0, 0}, - {0x5687, 0x78, 0, 0}, {0x5a00, 0x08, 0, 0}, {0x5a21, 0x00, 0, 0}, - {0x5a24, 0x00, 0, 0}, {0x4837, 0x0a, 0, 0}, {0x3037, 0x01, 0, 0}, - {0x4800, 0x14, 0, 5}, {0x483b, 0xff, 0, 0}, {0x3007, 0xf7, 0, 0}, + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0}, {0x3a15, 0x60, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5000, 0xa7, 0, 0}, + {0x5001, 0x83, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0}, + {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, + {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0}, + {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, {0x518a, 0x54, 0, 0}, + {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x42, 0, 0}, + {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, {0x5190, 0x46, 0, 0}, + {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, + {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, + {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, + {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, + {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, {0x5381, 0x1e, 0, 0}, + {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, {0x5384, 0x0a, 0, 0}, + {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0}, + {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0}, + {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0}, + {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0}, + {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0}, + {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0}, + {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, {0x5481, 0x08, 0, 0}, + {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, {0x5484, 0x51, 0, 0}, + {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, {0x5487, 0x7d, 0, 0}, + {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, {0x548a, 0x9a, 0, 0}, + {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, {0x548d, 0xcd, 0, 0}, + {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, {0x5490, 0x1d, 0, 0}, + {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x10, 0, 0}, + {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, {0x558b, 0xf8, 0, 0}, + {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, {0x5802, 0x0f, 0, 0}, + {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, {0x5805, 0x26, 0, 0}, + {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, {0x5808, 0x05, 0, 0}, + {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, {0x580b, 0x0d, 0, 0}, + {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, {0x580e, 0x00, 0, 0}, + {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, {0x5811, 0x09, 0, 0}, + {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x00, 0, 0}, + {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, {0x5817, 0x08, 0, 0}, + {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, {0x581a, 0x05, 0, 0}, + {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, {0x581d, 0x0e, 0, 0}, + {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, {0x5820, 0x11, 0, 0}, + {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, {0x5823, 0x28, 0, 0}, + {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, {0x5826, 0x08, 0, 0}, + {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, {0x5829, 0x26, 0, 0}, + {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, {0x582c, 0x24, 0, 0}, + {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, {0x582f, 0x22, 0, 0}, + {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, {0x5832, 0x24, 0, 0}, + {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, {0x5835, 0x22, 0, 0}, + {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, {0x5838, 0x44, 0, 0}, + {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, {0x583b, 0x28, 0, 0}, + {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x14, 0, 0}, + {0x3008, 0x02, 0, 0}, +}; + +static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = { + {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, + {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, + {0x3034, 0x18, 0, 0}, {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, + {0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0}, + {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0}, + {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0}, + {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0}, + {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0}, + {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0}, + {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0}, + {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0}, + {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0}, + {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0}, - {0x3c06, 0x1c, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, - {0x3c0a, 0x9c, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0b, 0x40, 0, 0}, - {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, - {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, - {0x5186, 0x09, 0, 0}, {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, - {0x5189, 0x75, 0, 0}, {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, - {0x518c, 0xb2, 0, 0}, {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, - {0x518f, 0x56, 0, 0}, {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, - {0x5192, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, - {0x5195, 0xf0, 0, 0}, {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, - {0x5198, 0x04, 0, 0}, {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, - {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, - {0x519e, 0x38, 0, 0}, {0x5381, 0x1c, 0, 0}, {0x5382, 0x5a, 0, 0}, - {0x5383, 0x06, 0, 5}, {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, - {0x5386, 0x88, 0, 0}, {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, - {0x5389, 0x10, 0, 0}, {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, - {0x5300, 0x08, 0, 0}, {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, - {0x5303, 0x00, 0, 0}, {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, - {0x5306, 0x08, 0, 0}, {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, - {0x530a, 0x30, 0, 0}, {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, - {0x4814, 0x00, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0x00, 0, 10}, - {0x483b, 0x33, 0, 0}, {0x3007, 0xff, 0, 10}, + {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0}, + {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0}, + {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0}, + {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0}, + {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0}, + {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0}, + {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, + {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0}, + {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0}, + {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0}, + {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0}, + {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0}, + {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0}, + {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0}, + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, + {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0x83, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, + {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x75, 0, 0}, + {0x518a, 0x54, 0, 0}, {0x518b, 0xe0, 0, 0}, {0x518c, 0xb2, 0, 0}, + {0x518d, 0x42, 0, 0}, {0x518e, 0x3d, 0, 0}, {0x518f, 0x56, 0, 0}, + {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0}, + {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0}, + {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0}, + {0x5199, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, + {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, {0x519e, 0x38, 0, 0}, + {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0}, + {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0}, + {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0}, + {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0}, + {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0}, + {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0}, + {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0}, + {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0}, + {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0}, + {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0}, + {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0}, + {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0}, + {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0}, + {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0}, + {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0}, + {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0}, + {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0}, + {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0}, + {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0}, + {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0}, + {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0}, + {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0}, + {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0}, + {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0}, + {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0}, + {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0}, + {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0}, + {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0}, + {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0}, + {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0}, + {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0}, + {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0}, + {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0}, + {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0}, + {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0}, + {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0}, + {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0}, + {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0}, + {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, }; static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = { @@ -357,7 +725,9 @@ static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = { {ov5640_mode_PAL_720_576, 0, 0, NULL, 0}, {ov5640_mode_720P_1280_720, 0, 0, NULL, 0}, {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0}, - {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0}, + {ov5640_mode_QSXGA_2592_1944, 2592, 1944, + ov5640_setting_15fps_QSXGA_2592_1944, + ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)}, }, { {ov5640_mode_VGA_640_480, 640, 480, @@ -366,8 +736,12 @@ static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = { {ov5640_mode_QVGA_320_240, 320, 240, ov5640_setting_30fps_QVGA_320_240, ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)}, - {ov5640_mode_NTSC_720_480, 0, 0, NULL, 0}, - {ov5640_mode_PAL_720_576, 0, 0, NULL, 0}, + {ov5640_mode_NTSC_720_480, 720, 480, + ov5640_setting_30fps_NTSC_720_480, + ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)}, + {ov5640_mode_PAL_720_576, 720, 576, + ov5640_setting_30fps_PAL_720_576, + ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)}, {ov5640_mode_720P_1280_720, 1280, 720, ov5640_setting_30fps_720P_1280_720, ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)}, @@ -475,15 +849,26 @@ static int ov5640_init_mode(enum ov5640_frame_rate frame_rate, /* initial mipi dphy */ if (mipi_csi2_info) { - mipi_csi2_set_lanes(mipi_csi2_info); - mipi_csi2_reset(mipi_csi2_info); - - if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_YUYV) - mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422); - else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565) - mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565); - else - pr_err("currently this sensor format can not be supported!\n"); + if (!mipi_csi2_get_status(mipi_csi2_info)) + mipi_csi2_enable(mipi_csi2_info); + + if (mipi_csi2_get_status(mipi_csi2_info)) { + mipi_csi2_set_lanes(mipi_csi2_info); + mipi_csi2_reset(mipi_csi2_info); + + if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_UYVY) + mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422); + else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565) + mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565); + else + pr_err("currently this sensor format can not be supported!\n"); + } else { + pr_err("Can not enable mipi csi2 driver!\n"); + return -1; + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -1; } pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr; @@ -522,15 +907,37 @@ static int ov5640_init_mode(enum ov5640_frame_rate frame_rate, } if (mipi_csi2_info) { + unsigned int i; + + i = 0; + /* wait for mipi sensor ready */ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); - while (mipi_reg == 0x200) + while ((mipi_reg == 0x200) && (i < 10)) { mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); + i++; + msleep(10); + } + + if (i >= 10) { + pr_err("mipi csi2 can not receive sensor clk!\n"); + return -1; + } + + i = 0; /* wait for mipi stable */ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); - while (mipi_reg != 0x0) + while ((mipi_reg != 0x0) && (i < 10)) { mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); + i++; + msleep(10); + } + + if (i >= 10) { + pr_err("mipi csi2 can not reveive data correctly!\n"); + return -1; + } } err: return retval; @@ -924,6 +1331,7 @@ static int ioctl_dev_init(struct v4l2_int_device *s) u32 tgt_fps; /* target frames per secound */ int ret; enum ov5640_frame_rate frame_rate; + void *mipi_csi2_info; ov5640_data.on = true; @@ -947,6 +1355,16 @@ static int ioctl_dev_init(struct v4l2_int_device *s) else return -EINVAL; /* Only support 15fps or 30fps now. */ + mipi_csi2_info = mipi_csi2_get_info(); + + /* enable mipi csi2 */ + if (mipi_csi2_info) + mipi_csi2_enable(mipi_csi2_info); + else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } + ret = ov5640_init_mode(frame_rate, sensor->streamcap.capturemode); @@ -961,6 +1379,15 @@ static int ioctl_dev_init(struct v4l2_int_device *s) */ static int ioctl_dev_exit(struct v4l2_int_device *s) { + void *mipi_csi2_info; + + mipi_csi2_info = mipi_csi2_get_info(); + + /* disable mipi csi2 */ + if (mipi_csi2_info) + if (mipi_csi2_get_status(mipi_csi2_info)) + mipi_csi2_disable(mipi_csi2_info); + return 0; } @@ -1027,7 +1454,7 @@ static int ov5640_probe(struct i2c_client *client, ov5640_data.csi = plat_data->csi; ov5640_data.i2c_client = client; - ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; + ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY; ov5640_data.pix.width = 640; ov5640_data.pix.height = 480; ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | @@ -1091,6 +1518,9 @@ static int ov5640_probe(struct i2c_client *client, analog_regulator = NULL; } + if (plat_data->io_init) + plat_data->io_init(); + if (plat_data->pwdn) plat_data->pwdn(0); @@ -1181,7 +1611,7 @@ module_init(ov5640_init); module_exit(ov5640_clean); MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("OV5640 Camera Driver"); +MODULE_DESCRIPTION("OV5640 MIPI Camera Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); MODULE_ALIAS("CSI"); diff --git a/drivers/media/video/mxc/capture/ov5642.c b/drivers/media/video/mxc/capture/ov5642.c index 25749673caa2..f874635d201c 100644 --- a/drivers/media/video/mxc/capture/ov5642.c +++ b/drivers/media/video/mxc/capture/ov5642.c @@ -2762,6 +2762,9 @@ static int ov5642_probe(struct i2c_client *client, analog_regulator = NULL; } + if (plat_data->io_init) + plat_data->io_init(); + if (plat_data->pwdn) plat_data->pwdn(0); diff --git a/drivers/media/video/mxc/capture/ov8820_mipi.c b/drivers/media/video/mxc/capture/ov8820_mipi.c new file mode 100644 index 000000000000..4c2a49d8bef5 --- /dev/null +++ b/drivers/media/video/mxc/capture/ov8820_mipi.c @@ -0,0 +1,1037 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * 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/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/ctype.h> +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/regulator/consumer.h> +#include <linux/fsl_devices.h> +#include <mach/mipi_csi2.h> +#include <media/v4l2-chip-ident.h> +#include <media/v4l2-int-device.h> +#include "mxc_v4l2_capture.h" + +#define OV8820_VOLTAGE_ANALOG 2800000 +#define OV8820_VOLTAGE_DIGITAL_CORE 1500000 +#define OV8820_VOLTAGE_DIGITAL_IO 1800000 + +#define MIN_FPS 15 +#define MAX_FPS 30 +#define DEFAULT_FPS 30 + +#define OV8820_XCLK_MIN 6000000 +#define OV8820_XCLK_MAX 24000000 + +enum ov8820_mode { + ov8820_mode_MIN = 0, + ov8820_mode_480_480 = 0, + ov8820_mode_MAX = 0 +}; + +enum ov8820_frame_rate { + ov8820_15_fps, + ov8820_30_fps +}; + +struct reg_value { + u16 u16RegAddr; + u8 u8Val; + u8 u8Mask; + u32 u32Delay_ms; +}; + +struct ov8820_mode_info { + enum ov8820_mode mode; + u32 width; + u32 height; + struct reg_value *init_data_ptr; + u32 init_data_size; +}; + +/*! + * Maintains the information on the current state of the sesor. + */ +struct sensor { + const struct ov8820_platform_data *platform_data; + struct v4l2_int_device *v4l2_int_device; + struct i2c_client *i2c_client; + struct v4l2_pix_format pix; + struct v4l2_captureparm streamcap; + bool on; + + /* control settings */ + int brightness; + int hue; + int contrast; + int saturation; + int red; + int green; + int blue; + int ae_mode; + + u32 mclk; + int csi; +} ov8820_data; + +static struct reg_value ov8820_setting_30fps_480_480[] = { + {0x0103, 0x01, 0, 5}, {0x3000, 0x02, 0, 0}, {0x3001, 0x00, 0, 0}, + {0x3002, 0x6c, 0, 0}, {0x300d, 0x00, 0, 0}, {0x301f, 0x09, 0, 0}, + {0x3010, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, {0x3300, 0x00, 0, 0}, + {0x3500, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3509, 0x00, 0, 0}, + {0x3600, 0x08, 0, 0}, {0x3601, 0x44, 0, 0}, {0x3602, 0x75, 0, 0}, + {0x3603, 0x5c, 0, 0}, {0x3604, 0x98, 0, 0}, {0x3605, 0xe9, 0, 0}, + {0x3609, 0xb8, 0, 0}, {0x360a, 0xbc, 0, 0}, {0x360b, 0xb4, 0, 0}, + {0x360c, 0x0d, 0, 0}, {0x3613, 0x02, 0, 0}, {0x3614, 0x0f, 0, 0}, + {0x3615, 0x00, 0, 0}, {0x3616, 0x03, 0, 0}, {0x3617, 0x01, 0, 0}, + {0x3618, 0x00, 0, 0}, {0x3619, 0x00, 0, 0}, {0x361a, 0x00, 0, 0}, + {0x361b, 0x00, 0, 0}, {0x3700, 0x20, 0, 0}, {0x3701, 0x44, 0, 0}, + {0x3702, 0x50, 0, 0}, {0x3703, 0xcc, 0, 0}, {0x3704, 0x19, 0, 0}, + {0x3706, 0x4b, 0, 0}, {0x3707, 0x63, 0, 0}, {0x3708, 0x84, 0, 0}, + {0x3709, 0x40, 0, 0}, {0x370b, 0x01, 0, 0}, {0x370c, 0x50, 0, 0}, + {0x370d, 0x0c, 0, 0}, {0x370e, 0x00, 0, 0}, {0x3711, 0x01, 0, 0}, + {0x3712, 0x9c, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3804, 0x0c, 0, 0}, + {0x3810, 0x00, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3816, 0x02, 0, 0}, + {0x3817, 0x40, 0, 0}, {0x3818, 0x00, 0, 0}, {0x3819, 0x40, 0, 0}, + {0x3d00, 0x00, 0, 0}, {0x3d01, 0x00, 0, 0}, {0x3d02, 0x00, 0, 0}, + {0x3d03, 0x00, 0, 0}, {0x3d04, 0x00, 0, 0}, {0x3d05, 0x00, 0, 0}, + {0x3d06, 0x00, 0, 0}, {0x3d07, 0x00, 0, 0}, {0x3d08, 0x00, 0, 0}, + {0x3d09, 0x00, 0, 0}, {0x3d0a, 0x00, 0, 0}, {0x3d0b, 0x00, 0, 0}, + {0x3d0c, 0x00, 0, 0}, {0x3d0d, 0x00, 0, 0}, {0x3d0e, 0x00, 0, 0}, + {0x3d0f, 0x00, 0, 0}, {0x3d10, 0x00, 0, 0}, {0x3d11, 0x00, 0, 0}, + {0x3d12, 0x00, 0, 0}, {0x3d13, 0x00, 0, 0}, {0x3d14, 0x00, 0, 0}, + {0x3d15, 0x00, 0, 0}, {0x3d16, 0x00, 0, 0}, {0x3d17, 0x00, 0, 0}, + {0x3d18, 0x00, 0, 0}, {0x3d19, 0x00, 0, 0}, {0x3d1a, 0x00, 0, 0}, + {0x3d1b, 0x00, 0, 0}, {0x3d1c, 0x00, 0, 0}, {0x3d1d, 0x00, 0, 0}, + {0x3d1e, 0x00, 0, 0}, {0x3d1f, 0x00, 0, 0}, {0x3d80, 0x00, 0, 0}, + {0x3d81, 0x00, 0, 0}, {0x3d84, 0x00, 0, 0}, {0x3f01, 0xfc, 0, 0}, + {0x3f05, 0x10, 0, 0}, {0x3f06, 0x00, 0, 0}, {0x3f07, 0x00, 0, 0}, + {0x4000, 0x29, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4002, 0x45, 0, 0}, + {0x4003, 0x08, 0, 0}, {0x4004, 0x04, 0, 0}, {0x4005, 0x18, 0, 0}, + {0x4300, 0xff, 0, 0}, {0x4303, 0x00, 0, 0}, {0x4304, 0x08, 0, 0}, + {0x4307, 0x00, 0, 0}, {0x4800, 0x04, 0, 0}, {0x4801, 0x0f, 0, 0}, + {0x4843, 0x02, 0, 0}, {0x5000, 0x00, 0, 0}, {0x5001, 0x00, 0, 0}, + {0x5002, 0x00, 0, 0}, {0x501f, 0x00, 0, 0}, {0x5c00, 0x80, 0, 0}, + {0x5c01, 0x00, 0, 0}, {0x5c02, 0x00, 0, 0}, {0x5c03, 0x00, 0, 0}, + {0x5c04, 0x00, 0, 0}, {0x5c05, 0x00, 0, 0}, {0x5c06, 0x00, 0, 0}, + {0x5c07, 0x80, 0, 0}, {0x5c08, 0x10, 0, 0}, {0x6700, 0x05, 0, 0}, + {0x6701, 0x19, 0, 0}, {0x6702, 0xfd, 0, 0}, {0x6703, 0xd1, 0, 0}, + {0x6704, 0xff, 0, 0}, {0x6705, 0xff, 0, 0}, {0x6800, 0x10, 0, 0}, + {0x6801, 0x02, 0, 0}, {0x6802, 0x90, 0, 0}, {0x6803, 0x10, 0, 0}, + {0x6804, 0x59, 0, 0}, {0x6900, 0x61, 0, 0}, {0x6901, 0x04, 0, 0}, + {0x3612, 0x00, 0, 0}, {0x3617, 0xa1, 0, 0}, {0x3b1f, 0x00, 0, 0}, + {0x3000, 0x12, 0, 0}, {0x3000, 0x16, 0, 0}, {0x3b1f, 0x00, 0, 0}, + {0x3003, 0xce, 0, 0}, {0x3004, 0xd8, 0, 0}, {0x3005, 0x00, 0, 0}, + {0x3006, 0x10, 0, 0}, {0x3007, 0x3b, 0, 0}, {0x3012, 0x80, 0, 0}, + {0x3013, 0x39, 0, 0}, {0x3104, 0x20, 0, 0}, {0x3503, 0x07, 0, 0}, + {0x3500, 0x00, 0, 0}, {0x3501, 0x14, 0, 0}, {0x3502, 0x80, 0, 0}, + {0x350b, 0xff, 0, 0}, {0x3400, 0x04, 0, 0}, {0x3401, 0x00, 0, 0}, + {0x3402, 0x04, 0, 0}, {0x3403, 0x00, 0, 0}, {0x3404, 0x04, 0, 0}, + {0x3405, 0x00, 0, 0}, {0x3406, 0x01, 0, 0}, {0x5001, 0x01, 0, 0}, + {0x5000, 0x06, 0, 0}, {0x0100, 0x00, 0, 0}, {0x3004, 0xbf, 0, 0}, + {0x3005, 0x10, 0, 0}, {0x3006, 0x00, 0, 0}, {0x3011, 0x02, 0, 0}, + {0x370a, 0x74, 0, 0}, {0x3801, 0x08, 0, 0}, {0x3802, 0x00, 0, 0}, + {0x3803, 0x00, 0, 0}, {0x3805, 0xd7, 0, 0}, {0x3806, 0x09, 0, 0}, + {0x3807, 0x97, 0, 0}, {0x3808, 0x01, 0, 0}, {0x3809, 0xe0, 0, 0}, + {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x0d, 0, 0}, + {0x380d, 0xb0, 0, 0}, {0x380e, 0x02, 0, 0}, {0x380f, 0x7a, 0, 0}, + {0x3811, 0x04, 0, 0}, {0x3813, 0x02, 0, 0}, {0x3814, 0x71, 0, 0}, + {0x3815, 0x71, 0, 0}, {0x3820, 0x00, 0, 0}, {0x3821, 0x16, 0, 0}, + {0x3f00, 0x00, 0, 0}, {0x4600, 0x14, 0, 0}, {0x4601, 0x14, 0, 0}, + {0x4602, 0x00, 0, 0}, {0x4837, 0x1e, 0, 0}, {0x5068, 0x59, 0, 0}, + {0x506a, 0x5a, 0, 0}, {0x0100, 0x01, 0, 0}, +}; + +static struct ov8820_mode_info ov8820_mode_info_data[2][ov8820_mode_MAX + 1] = { + { + {ov8820_mode_480_480, 0, 0, NULL, 0}, + }, + { + {ov8820_mode_480_480, 480, 480, + ov8820_setting_30fps_480_480, + ARRAY_SIZE(ov8820_setting_30fps_480_480)}, + }, +}; + +static struct regulator *io_regulator; +static struct regulator *core_regulator; +static struct regulator *analog_regulator; +static struct regulator *gpo_regulator; +static struct fsl_mxc_camera_platform_data *camera_plat; + +static int ov8820_probe(struct i2c_client *adapter, + const struct i2c_device_id *device_id); +static int ov8820_remove(struct i2c_client *client); + +static s32 ov8820_read_reg(u16 reg, u8 *val); +static s32 ov8820_write_reg(u16 reg, u8 val); + +static const struct i2c_device_id ov8820_id[] = { + {"ov8820_mipi", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, ov8820_id); + +static struct i2c_driver ov8820_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ov8820_mipi", + }, + .probe = ov8820_probe, + .remove = ov8820_remove, + .id_table = ov8820_id, +}; + + +static s32 ov8820_write_reg(u16 reg, u8 val) +{ + u8 au8Buf[3] = {0}; + + au8Buf[0] = reg >> 8; + au8Buf[1] = reg & 0xff; + au8Buf[2] = val; + + if (i2c_master_send(ov8820_data.i2c_client, au8Buf, 3) < 0) { + pr_err("%s:write reg error:reg=%x,val=%x\n", + __func__, reg, val); + return -1; + } + + return 0; +} + +static s32 ov8820_read_reg(u16 reg, u8 *val) +{ + u8 au8RegBuf[2] = {0}; + u8 u8RdVal = 0; + + au8RegBuf[0] = reg >> 8; + au8RegBuf[1] = reg & 0xff; + + if (2 != i2c_master_send(ov8820_data.i2c_client, au8RegBuf, 2)) { + pr_err("%s:write reg error:reg=%x\n", + __func__, reg); + return -1; + } + + if (1 != i2c_master_recv(ov8820_data.i2c_client, &u8RdVal, 1)) { + pr_err("%s:read reg error:reg=%x,val=%x\n", + __func__, reg, u8RdVal); + return -1; + } + + *val = u8RdVal; + + return u8RdVal; +} + +static int ov8820_init_mode(enum ov8820_frame_rate frame_rate, + enum ov8820_mode mode) +{ + struct reg_value *pModeSetting = NULL; + s32 i = 0; + s32 iModeSettingArySize = 0; + register u32 Delay_ms = 0; + register u16 RegAddr = 0; + register u8 Mask = 0; + register u8 Val = 0; + u8 RegVal = 0; + int retval = 0; + void *mipi_csi2_info; + u32 mipi_reg; + + if (mode > ov8820_mode_MAX || mode < ov8820_mode_MIN) { + pr_err("Wrong ov8820 mode detected!\n"); + return -1; + } + + mipi_csi2_info = mipi_csi2_get_info(); + + /* initial mipi dphy */ + if (mipi_csi2_info) { + if (!mipi_csi2_get_status(mipi_csi2_info)) + mipi_csi2_enable(mipi_csi2_info); + + if (mipi_csi2_get_status(mipi_csi2_info)) { + mipi_csi2_set_lanes(mipi_csi2_info); + mipi_csi2_reset(mipi_csi2_info); + + if (ov8820_data.pix.pixelformat == V4L2_PIX_FMT_SBGGR10) + mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RAW10); + else + pr_err("currently this sensor format can not be supported!\n"); + } else { + pr_err("Can not enable mipi csi2 driver!\n"); + return -1; + } + } else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -1; + } + + pModeSetting = ov8820_mode_info_data[frame_rate][mode].init_data_ptr; + iModeSettingArySize = + ov8820_mode_info_data[frame_rate][mode].init_data_size; + + ov8820_data.pix.width = ov8820_mode_info_data[frame_rate][mode].width; + ov8820_data.pix.height = ov8820_mode_info_data[frame_rate][mode].height; + + if (ov8820_data.pix.width == 0 || ov8820_data.pix.height == 0 || + pModeSetting == NULL || iModeSettingArySize == 0) + return -EINVAL; + + for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { + Delay_ms = pModeSetting->u32Delay_ms; + RegAddr = pModeSetting->u16RegAddr; + Val = pModeSetting->u8Val; + Mask = pModeSetting->u8Mask; + + if (Mask) { + retval = ov8820_read_reg(RegAddr, &RegVal); + if (retval < 0) + goto err; + + RegVal &= ~(u8)Mask; + Val &= Mask; + Val |= RegVal; + } + + retval = ov8820_write_reg(RegAddr, Val); + if (retval < 0) + goto err; + + if (Delay_ms) + msleep(Delay_ms); + } + + if (mipi_csi2_info) { + unsigned int i; + + i = 0; + + /* wait for mipi sensor ready */ + mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); + while ((mipi_reg == 0x200) && (i < 10)) { + mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); + i++; + msleep(10); + } + + if (i >= 10) { + pr_err("mipi csi2 can not receive sensor clk!\n"); + return -1; + } + + i = 0; + + /* wait for mipi stable */ + mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); + while ((mipi_reg != 0x0) && (i < 10)) { + mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); + i++; + msleep(10); + } + + if (i >= 10) { + pr_err("mipi csi2 can not reveive data correctly!\n"); + return -1; + } + } +err: + return retval; +} + +/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ + +static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) +{ + if (s == NULL) { + pr_err(" ERROR!! no slave device set!\n"); + return -1; + } + + memset(p, 0, sizeof(*p)); + p->u.bt656.clock_curr = ov8820_data.mclk; + pr_debug(" clock_curr=mclk=%d\n", ov8820_data.mclk); + p->if_type = V4L2_IF_TYPE_BT656; + p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; + p->u.bt656.clock_min = OV8820_XCLK_MIN; + p->u.bt656.clock_max = OV8820_XCLK_MAX; + p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ + + return 0; +} + +/*! + * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl + * @s: pointer to standard V4L2 device structure + * @on: indicates power mode (on or off) + * + * Turns the power on or off, depending on the value of on and returns the + * appropriate error code. + */ +static int ioctl_s_power(struct v4l2_int_device *s, int on) +{ + struct sensor *sensor = s->priv; + + if (on && !sensor->on) { + if (io_regulator) + if (regulator_enable(io_regulator) != 0) + return -EIO; + if (core_regulator) + if (regulator_enable(core_regulator) != 0) + return -EIO; + if (gpo_regulator) + if (regulator_enable(gpo_regulator) != 0) + return -EIO; + if (analog_regulator) + if (regulator_enable(analog_regulator) != 0) + return -EIO; + /* Make sure power on */ + if (camera_plat->pwdn) + camera_plat->pwdn(0); + + } else if (!on && sensor->on) { + if (analog_regulator) + regulator_disable(analog_regulator); + if (core_regulator) + regulator_disable(core_regulator); + if (io_regulator) + regulator_disable(io_regulator); + if (gpo_regulator) + regulator_disable(gpo_regulator); + } + + sensor->on = on; + + return 0; +} + +/*! + * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl + * @s: pointer to standard V4L2 device structure + * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure + * + * Returns the sensor's video CAPTURE parameters. + */ +static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) +{ + struct sensor *sensor = s->priv; + struct v4l2_captureparm *cparm = &a->parm.capture; + int ret = 0; + + switch (a->type) { + /* This is the only case currently handled. */ + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + memset(a, 0, sizeof(*a)); + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cparm->capability = sensor->streamcap.capability; + cparm->timeperframe = sensor->streamcap.timeperframe; + cparm->capturemode = sensor->streamcap.capturemode; + ret = 0; + break; + + /* These are all the possible cases. */ + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + ret = -EINVAL; + break; + + default: + pr_debug(" type is unknown - %d\n", a->type); + ret = -EINVAL; + break; + } + + return ret; +} + +/*! + * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl + * @s: pointer to standard V4L2 device structure + * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure + * + * Configures the sensor to use the input parameters, if possible. If + * not possible, reverts to the old parameters and returns the + * appropriate error code. + */ +static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) +{ + struct sensor *sensor = s->priv; + struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; + u32 tgt_fps; /* target frames per secound */ + enum ov8820_frame_rate frame_rate; + int ret = 0; + + /* Make sure power on */ + if (camera_plat->pwdn) + camera_plat->pwdn(0); + + switch (a->type) { + /* This is the only case currently handled. */ + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + /* Check that the new frame rate is allowed. */ + if ((timeperframe->numerator == 0) || + (timeperframe->denominator == 0)) { + timeperframe->denominator = DEFAULT_FPS; + timeperframe->numerator = 1; + } + + tgt_fps = timeperframe->denominator / + timeperframe->numerator; + + if (tgt_fps > MAX_FPS) { + timeperframe->denominator = MAX_FPS; + timeperframe->numerator = 1; + } else if (tgt_fps < MIN_FPS) { + timeperframe->denominator = MIN_FPS; + timeperframe->numerator = 1; + } + + /* Actual frame rate we use */ + tgt_fps = timeperframe->denominator / + timeperframe->numerator; + + if (tgt_fps == 15) + frame_rate = ov8820_15_fps; + else if (tgt_fps == 30) + frame_rate = ov8820_30_fps; + else { + pr_err(" The camera frame rate is not supported!\n"); + return -EINVAL; + } + + sensor->streamcap.timeperframe = *timeperframe; + sensor->streamcap.capturemode = + (u32)a->parm.capture.capturemode; + + ret = ov8820_init_mode(frame_rate, + sensor->streamcap.capturemode); + break; + + /* These are all the possible cases. */ + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + pr_debug(" type is not " \ + "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", + a->type); + ret = -EINVAL; + break; + + default: + pr_debug(" type is unknown - %d\n", a->type); + ret = -EINVAL; + break; + } + + return ret; +} + +/*! + * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap + * @s: pointer to standard V4L2 device structure + * @f: pointer to standard V4L2 v4l2_format structure + * + * Returns the sensor's current pixel format in the v4l2_format + * parameter. + */ +static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +{ + struct sensor *sensor = s->priv; + + f->fmt.pix = sensor->pix; + + return 0; +} + +/*! + * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl + * @s: pointer to standard V4L2 device structure + * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure + * + * If the requested control is supported, returns the control's current + * value from the video_control[] array. Otherwise, returns -EINVAL + * if the control is not supported. + */ +static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) +{ + int ret = 0; + + switch (vc->id) { + case V4L2_CID_BRIGHTNESS: + vc->value = ov8820_data.brightness; + break; + case V4L2_CID_HUE: + vc->value = ov8820_data.hue; + break; + case V4L2_CID_CONTRAST: + vc->value = ov8820_data.contrast; + break; + case V4L2_CID_SATURATION: + vc->value = ov8820_data.saturation; + break; + case V4L2_CID_RED_BALANCE: + vc->value = ov8820_data.red; + break; + case V4L2_CID_BLUE_BALANCE: + vc->value = ov8820_data.blue; + break; + case V4L2_CID_EXPOSURE: + vc->value = ov8820_data.ae_mode; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +/*! + * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl + * @s: pointer to standard V4L2 device structure + * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure + * + * If the requested control is supported, sets the control's current + * value in HW (and updates the video_control[] array). Otherwise, + * returns -EINVAL if the control is not supported. + */ +static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) +{ + int retval = 0; + + pr_debug("In ov8820:ioctl_s_ctrl %d\n", + vc->id); + + switch (vc->id) { + case V4L2_CID_BRIGHTNESS: + break; + case V4L2_CID_CONTRAST: + break; + case V4L2_CID_SATURATION: + break; + case V4L2_CID_HUE: + break; + case V4L2_CID_AUTO_WHITE_BALANCE: + break; + case V4L2_CID_DO_WHITE_BALANCE: + break; + case V4L2_CID_RED_BALANCE: + break; + case V4L2_CID_BLUE_BALANCE: + break; + case V4L2_CID_GAMMA: + break; + case V4L2_CID_EXPOSURE: + break; + case V4L2_CID_AUTOGAIN: + break; + case V4L2_CID_GAIN: + break; + case V4L2_CID_HFLIP: + break; + case V4L2_CID_VFLIP: + break; + default: + retval = -EPERM; + break; + } + + return retval; +} + +/*! + * ioctl_enum_framesizes - V4L2 sensor interface handler for + * VIDIOC_ENUM_FRAMESIZES ioctl + * @s: pointer to standard V4L2 device structure + * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure + * + * Return 0 if successful, otherwise -EINVAL. + */ +static int ioctl_enum_framesizes(struct v4l2_int_device *s, + struct v4l2_frmsizeenum *fsize) +{ + if (fsize->index > ov8820_mode_MAX) + return -EINVAL; + + fsize->pixel_format = ov8820_data.pix.pixelformat; + fsize->discrete.width = + max(ov8820_mode_info_data[0][fsize->index].width, + ov8820_mode_info_data[1][fsize->index].width); + fsize->discrete.height = + max(ov8820_mode_info_data[0][fsize->index].height, + ov8820_mode_info_data[1][fsize->index].height); + return 0; +} + +/*! + * ioctl_g_chip_ident - V4L2 sensor interface handler for + * VIDIOC_DBG_G_CHIP_IDENT ioctl + * @s: pointer to standard V4L2 device structure + * @id: pointer to int + * + * Return 0. + */ +static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) +{ + ((struct v4l2_dbg_chip_ident *)id)->match.type = + V4L2_CHIP_MATCH_I2C_DRIVER; + strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov8820_camera"); + + return 0; +} + +/*! + * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT + * @s: pointer to standard V4L2 device structure + */ +static int ioctl_init(struct v4l2_int_device *s) +{ + + return 0; +} + +/*! + * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT + * @s: pointer to standard V4L2 device structure + * @fmt: pointer to standard V4L2 fmt description structure + * + * Return 0. + */ +static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, + struct v4l2_fmtdesc *fmt) +{ + if (fmt->index > ov8820_mode_MAX) + return -EINVAL; + + fmt->pixelformat = ov8820_data.pix.pixelformat; + + return 0; +} + +/*! + * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num + * @s: pointer to standard V4L2 device structure + * + * Initialise the device when slave attaches to the master. + */ +static int ioctl_dev_init(struct v4l2_int_device *s) +{ + struct sensor *sensor = s->priv; + u32 tgt_xclk; /* target xclk */ + u32 tgt_fps; /* target frames per secound */ + int ret; + enum ov8820_frame_rate frame_rate; + void *mipi_csi2_info; + + ov8820_data.on = true; + + /* mclk */ + tgt_xclk = ov8820_data.mclk; + tgt_xclk = min(tgt_xclk, (u32)OV8820_XCLK_MAX); + tgt_xclk = max(tgt_xclk, (u32)OV8820_XCLK_MIN); + ov8820_data.mclk = tgt_xclk; + + pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); + set_mclk_rate(&ov8820_data.mclk, ov8820_data.csi); + + /* Default camera frame rate is set in probe */ + tgt_fps = sensor->streamcap.timeperframe.denominator / + sensor->streamcap.timeperframe.numerator; + + if (tgt_fps == 15) + frame_rate = ov8820_15_fps; + else if (tgt_fps == 30) + frame_rate = ov8820_30_fps; + else + return -EINVAL; /* Only support 15fps or 30fps now. */ + + mipi_csi2_info = mipi_csi2_get_info(); + + /* enable mipi csi2 */ + if (mipi_csi2_info) + mipi_csi2_enable(mipi_csi2_info); + else { + printk(KERN_ERR "Fail to get mipi_csi2_info!\n"); + return -EPERM; + } + + ret = ov8820_init_mode(frame_rate, + sensor->streamcap.capturemode); + + return ret; +} + +/*! + * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num + * @s: pointer to standard V4L2 device structure + * + * Delinitialise the device when slave detaches to the master. + */ +static int ioctl_dev_exit(struct v4l2_int_device *s) +{ + void *mipi_csi2_info; + + mipi_csi2_info = mipi_csi2_get_info(); + + /* disable mipi csi2 */ + if (mipi_csi2_info) + if (mipi_csi2_get_status(mipi_csi2_info)) + mipi_csi2_disable(mipi_csi2_info); + + return 0; +} + +/*! + * This structure defines all the ioctls for this module and links them to the + * enumeration. + */ +static struct v4l2_int_ioctl_desc ov8820_ioctl_desc[] = { + {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*) ioctl_dev_init}, + {vidioc_int_dev_exit_num, ioctl_dev_exit}, + {vidioc_int_s_power_num, (v4l2_int_ioctl_func*) ioctl_s_power}, + {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*) ioctl_g_ifparm}, +/* {vidioc_int_g_needs_reset_num, + (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */ +/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */ + {vidioc_int_init_num, (v4l2_int_ioctl_func*) ioctl_init}, + {vidioc_int_enum_fmt_cap_num, + (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, +/* {vidioc_int_try_fmt_cap_num, + (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */ + {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap}, +/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, */ + {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm}, + {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm}, +/* {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */ + {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl}, + {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl}, + {vidioc_int_enum_framesizes_num, + (v4l2_int_ioctl_func *) ioctl_enum_framesizes}, + {vidioc_int_g_chip_ident_num, + (v4l2_int_ioctl_func *) ioctl_g_chip_ident}, +}; + +static struct v4l2_int_slave ov8820_slave = { + .ioctls = ov8820_ioctl_desc, + .num_ioctls = ARRAY_SIZE(ov8820_ioctl_desc), +}; + +static struct v4l2_int_device ov8820_int_device = { + .module = THIS_MODULE, + .name = "ov8820", + .type = v4l2_int_type_slave, + .u = { + .slave = &ov8820_slave, + }, +}; + +/*! + * ov8820 I2C probe function + * + * @param adapter struct i2c_adapter * + * @return Error code indicating success or failure + */ +static int ov8820_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int retval; + struct fsl_mxc_camera_platform_data *plat_data = client->dev.platform_data; + + /* Set initial values for the sensor struct. */ + memset(&ov8820_data, 0, sizeof(ov8820_data)); + ov8820_data.mclk = 24000000; /* 6 - 54 MHz, typical 24MHz */ + ov8820_data.mclk = plat_data->mclk; + ov8820_data.csi = plat_data->csi; + + ov8820_data.i2c_client = client; + ov8820_data.pix.pixelformat = V4L2_PIX_FMT_SBGGR10; + ov8820_data.pix.width = 480; + ov8820_data.pix.height = 480; + ov8820_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | + V4L2_CAP_TIMEPERFRAME; + ov8820_data.streamcap.capturemode = 0; + ov8820_data.streamcap.timeperframe.denominator = DEFAULT_FPS; + ov8820_data.streamcap.timeperframe.numerator = 1; + + if (plat_data->io_regulator) { + io_regulator = regulator_get(&client->dev, + plat_data->io_regulator); + if (!IS_ERR(io_regulator)) { + regulator_set_voltage(io_regulator, + OV8820_VOLTAGE_DIGITAL_IO, + OV8820_VOLTAGE_DIGITAL_IO); + if (regulator_enable(io_regulator) != 0) { + pr_err("%s:io set voltage error\n", __func__); + goto err1; + } else { + dev_dbg(&client->dev, + "%s:io set voltage ok\n", __func__); + } + } else + io_regulator = NULL; + } + + if (plat_data->core_regulator) { + core_regulator = regulator_get(&client->dev, + plat_data->core_regulator); + if (!IS_ERR(core_regulator)) { + regulator_set_voltage(core_regulator, + OV8820_VOLTAGE_DIGITAL_CORE, + OV8820_VOLTAGE_DIGITAL_CORE); + if (regulator_enable(core_regulator) != 0) { + pr_err("%s:core set voltage error\n", __func__); + goto err2; + } else { + dev_dbg(&client->dev, + "%s:core set voltage ok\n", __func__); + } + } else + core_regulator = NULL; + } + + if (plat_data->analog_regulator) { + analog_regulator = regulator_get(&client->dev, + plat_data->analog_regulator); + if (!IS_ERR(analog_regulator)) { + regulator_set_voltage(analog_regulator, + OV8820_VOLTAGE_ANALOG, + OV8820_VOLTAGE_ANALOG); + if (regulator_enable(analog_regulator) != 0) { + pr_err("%s:analog set voltage error\n", + __func__); + goto err3; + } else { + dev_dbg(&client->dev, + "%s:analog set voltage ok\n", __func__); + } + } else + analog_regulator = NULL; + } + + if (plat_data->io_init) + plat_data->io_init(); + + if (plat_data->pwdn) + plat_data->pwdn(0); + + camera_plat = plat_data; + + ov8820_int_device.priv = &ov8820_data; + retval = v4l2_int_device_register(&ov8820_int_device); + + return retval; + +err3: + if (core_regulator) { + regulator_disable(core_regulator); + regulator_put(core_regulator); + } +err2: + if (io_regulator) { + regulator_disable(io_regulator); + regulator_put(io_regulator); + } +err1: + return -1; +} + +/*! + * ov8820 I2C detach function + * + * @param client struct i2c_client * + * @return Error code indicating success or failure + */ +static int ov8820_remove(struct i2c_client *client) +{ + v4l2_int_device_unregister(&ov8820_int_device); + + if (gpo_regulator) { + regulator_disable(gpo_regulator); + regulator_put(gpo_regulator); + } + + if (analog_regulator) { + regulator_disable(analog_regulator); + regulator_put(analog_regulator); + } + + if (core_regulator) { + regulator_disable(core_regulator); + regulator_put(core_regulator); + } + + if (io_regulator) { + regulator_disable(io_regulator); + regulator_put(io_regulator); + } + + return 0; +} + +/*! + * ov8820 init function + * Called by insmod ov8820_camera.ko. + * + * @return Error code indicating success or failure + */ +static __init int ov8820_init(void) +{ + u8 err; + + err = i2c_add_driver(&ov8820_i2c_driver); + if (err != 0) + pr_err("%s:driver registration failed, error=%d\n", + __func__, err); + + return err; +} + +/*! + * OV8820 cleanup function + * Called on rmmod ov8820_camera.ko + * + * @return Error code indicating success or failure + */ +static void __exit ov8820_clean(void) +{ + i2c_del_driver(&ov8820_i2c_driver); +} + +module_init(ov8820_init); +module_exit(ov8820_clean); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("OV8820 MIPI Camera Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0"); +MODULE_ALIAS("CSI"); diff --git a/drivers/media/video/mxc/output/mxc_vout.c b/drivers/media/video/mxc/output/mxc_vout.c index d7e6fa3e02c3..57e684f99308 100644 --- a/drivers/media/video/mxc/output/mxc_vout.c +++ b/drivers/media/video/mxc/output/mxc_vout.c @@ -61,6 +61,7 @@ struct mxc_vout_output { bool disp_support_csc; bool fmt_init; + bool bypass_pp; struct ipu_task task; bool timer_stop; @@ -318,7 +319,7 @@ static bool is_pp_bypass(struct mxc_vout_output *vout) (vout->task.input.height == vout->task.output.height) && (vout->task.input.crop.w == vout->task.output.crop.w) && (vout->task.input.crop.h == vout->task.output.crop.h) && - (vout->task.output.rotate < IPU_ROTATE_90_RIGHT) && + (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) && !vout->task.input.deinterlace.enable) { if (vout->disp_support_csc) return true; @@ -329,7 +330,7 @@ static bool is_pp_bypass(struct mxc_vout_output *vout) (vout->task.output.crop.w == vout->task.output.width) && (vout->task.input.crop.h == vout->task.output.crop.h) && (vout->task.output.crop.h == vout->task.output.height) && - (vout->task.output.rotate < IPU_ROTATE_90_RIGHT) && + (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) && !vout->task.input.deinterlace.enable) { if (vout->disp_support_csc) return true; @@ -367,7 +368,8 @@ static void setup_buf_timer(struct mxc_vout_output *vout, "timer handler next schedule: %lu\n", timeout); } -static int show_buf(struct mxc_vout_output *vout, int idx) +static int show_buf(struct mxc_vout_output *vout, int idx, + struct ipu_pos *ipos) { struct fb_info *fbi = vout->fbi; struct fb_var_screeninfo var; @@ -375,16 +377,16 @@ static int show_buf(struct mxc_vout_output *vout, int idx) memcpy(&var, &fbi->var, sizeof(var)); - if (is_pp_bypass(vout)) { + if (vout->bypass_pp) { /* * crack fb base * NOTE: should not do other fb operation during v4l2 */ console_lock(); fbi->fix.smem_start = vout->task.output.paddr; - fbi->var.yoffset = vout->task.input.crop.pos.y + 1; - var.xoffset = vout->task.input.crop.pos.x; - var.yoffset = vout->task.input.crop.pos.y; + fbi->var.yoffset = ipos->y + 1; + var.xoffset = ipos->x; + var.yoffset = ipos->y; ret = fb_pan_display(fbi, &var); console_unlock(); } else { @@ -404,8 +406,11 @@ static void disp_work_func(struct work_struct *work) struct videobuf_queue *q = &vout->vbq; struct videobuf_buffer *vb, *vb_next = NULL; unsigned long flags = 0; + struct ipu_pos ipos; int ret = 0; + v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n"); + spin_lock_irqsave(q->irqlock, flags); if (deinterlace_3_field(vout)) { @@ -439,9 +444,11 @@ static void disp_work_func(struct work_struct *work) else vout->task.input.paddr = videobuf_to_dma_contig(vb); - if (is_pp_bypass(vout)) + if (vout->bypass_pp) { vout->task.output.paddr = vout->task.input.paddr; - else { + ipos.x = vout->task.input.crop.pos.x; + ipos.y = vout->task.input.crop.pos.y; + } else { if (deinterlace_3_field(vout)) { if (vb->memory == V4L2_MEMORY_USERPTR) vout->task.input.paddr_n = vb_next->baddr; @@ -458,29 +465,35 @@ static void disp_work_func(struct work_struct *work) } } - ret = show_buf(vout, vout->frame_count % FB_BUFS); - if (ret < 0) - v4l2_warn(vout->vfd->v4l2_dev, "show buf with ret %d\n", ret); - mutex_unlock(&vout->task_lock); + ret = show_buf(vout, vout->frame_count % FB_BUFS, &ipos); + if (ret < 0) + v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "show buf with ret %d\n", ret); + spin_lock_irqsave(q->irqlock, flags); list_del(&vb->queue); /* * previous videobuf finish show, set VIDEOBUF_DONE state here - * to avoid tearing issue, which make sure showing buffer will - * not be dequeue to write new data. It also bring side-effect - * that the last buffer can not be dequeue correctly, app need - * take care about it. + * to avoid tearing issue in pp bypass case, which make sure + * showing buffer will not be dequeue to write new data. It also + * bring side-effect that the last buffer can not be dequeue + * correctly, app need take care about it. */ if (vout->pre_vb) { vout->pre_vb->state = VIDEOBUF_DONE; wake_up_interruptible(&vout->pre_vb->done); } - vout->pre_vb = vb; + if (vout->bypass_pp) + vout->pre_vb = vb; + else { + vout->pre_vb = NULL; + vb->state = VIDEOBUF_DONE; + wake_up_interruptible(&vb->done); + } vout->frame_count++; @@ -651,8 +664,10 @@ static int mxc_vout_release(struct file *file) q = &vout->vbq; if (q->streaming) mxc_vidioc_streamoff(file, vout, vout->type); - else + else { + release_disp_output(vout); videobuf_queue_cancel(q); + } destroy_workqueue(vout->v4l_wq); ret = videobuf_mmap_free(q); } @@ -757,9 +772,10 @@ static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh, return 0; } -static inline int ipu_try_task(struct ipu_task *task) +static inline int ipu_try_task(struct mxc_vout_output *vout) { int ret; + struct ipu_task *task = &vout->task; again: ret = ipu_check_task(task); @@ -774,11 +790,19 @@ again: goto again; } if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { - task->output.crop.w -= 8; + if (vout->disp_support_windows) { + task->output.width -= 8; + task->output.crop.w = task->output.width; + } else + task->output.crop.w -= 8; goto again; } if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { - task->output.crop.h -= 8; + if (vout->disp_support_windows) { + task->output.height -= 8; + task->output.crop.h = task->output.height; + } else + task->output.crop.h -= 8; goto again; } ret = -EINVAL; @@ -799,9 +823,11 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout) /* assume task.output already set by S_CROP */ if (is_pp_bypass(vout)) { v4l2_info(vout->vfd->v4l2_dev, "Bypass IC.\n"); + vout->bypass_pp = true; vout->task.output.format = vout->task.input.format; } else { /* if need CSC, choose IPU-DP or IPU_IC do it */ + vout->bypass_pp = false; if (vout->disp_support_csc) { if (colorspaceofpixel(vout->task.input.format) == YUV_CS) vout->task.output.format = IPU_PIX_FMT_UYVY; @@ -813,7 +839,7 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout) else vout->task.output.format = IPU_PIX_FMT_RGB565; } - ret = ipu_try_task(&vout->task); + ret = ipu_try_task(vout); } return ret; @@ -979,10 +1005,26 @@ static int mxc_vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop crop->c.height -= crop->c.height % 8; crop->c.width -= crop->c.width % 8; - mutex_lock(&vout->task_lock); + /* the same setting, return */ + if (vout->disp_support_windows) { + if ((vout->win_pos.x == crop->c.left) && + (vout->win_pos.y == crop->c.top) && + (vout->task.output.crop.w == crop->c.width) && + (vout->task.output.crop.h == crop->c.height)) + return 0; + } else { + if ((vout->task.output.crop.pos.x == crop->c.left) && + (vout->task.output.crop.pos.y == crop->c.top) && + (vout->task.output.crop.w == crop->c.width) && + (vout->task.output.crop.h == crop->c.height)) + return 0; + } - if (vout->fmt_init && vout->vbq.streaming) - release_disp_output(vout); + /* wait current work finish */ + if (vout->vbq.streaming) + cancel_work_sync(&vout->disp_work); + + mutex_lock(&vout->task_lock); if (vout->disp_support_windows) { vout->task.output.crop.pos.x = 0; @@ -1005,6 +1047,9 @@ static int mxc_vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop * check ipu task too. */ if (vout->fmt_init) { + if (vout->vbq.streaming) + release_disp_output(vout); + ret = mxc_vout_try_task(vout); if (ret < 0) { v4l2_err(vout->vfd->v4l2_dev, @@ -1125,6 +1170,10 @@ static int mxc_vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c int ret = 0; struct mxc_vout_output *vout = fh; + /* wait current work finish */ + if (vout->vbq.streaming) + cancel_work_sync(&vout->disp_work); + mutex_lock(&vout->task_lock); switch (ctrl->id) { case V4L2_CID_ROTATE: @@ -1154,8 +1203,32 @@ static int mxc_vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c } default: ret = -EINVAL; + goto done; + } + + if (vout->fmt_init) { + if (vout->vbq.streaming) + release_disp_output(vout); + + ret = mxc_vout_try_task(vout); + if (ret < 0) { + v4l2_err(vout->vfd->v4l2_dev, + "vout check task failed\n"); + goto done; + } + if (vout->vbq.streaming) { + ret = config_disp_output(vout); + if (ret < 0) { + v4l2_err(vout->vfd->v4l2_dev, + "Config display output failed\n"); + goto done; + } + } } + +done: mutex_unlock(&vout->task_lock); + return ret; } @@ -1216,7 +1289,7 @@ static int mxc_vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 0); } -static int set_window_position(struct mxc_vout_output *vout) +static int set_window_position(struct mxc_vout_output *vout, struct mxcfb_pos *pos) { struct fb_info *fbi = vout->fbi; mm_segment_t old_fs; @@ -1226,7 +1299,7 @@ static int set_window_position(struct mxc_vout_output *vout) old_fs = get_fs(); set_fs(KERNEL_DS); ret = fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS, - (unsigned long)&vout->win_pos); + (unsigned long)pos); set_fs(old_fs); } @@ -1243,7 +1316,7 @@ static int config_disp_output(struct mxc_vout_output *vout) var.xres = vout->task.output.width; var.yres = vout->task.output.height; - if (is_pp_bypass(vout)) { + if (vout->bypass_pp) { fb_num = 1; /* input crop */ if (vout->task.input.width > vout->task.output.width) @@ -1254,6 +1327,7 @@ static int config_disp_output(struct mxc_vout_output *vout) var.yres_virtual = vout->task.input.height; else var.yres_virtual = var.yres; + var.rotate = vout->task.output.rotate; } else { fb_num = FB_BUFS; var.xres_virtual = var.xres; @@ -1266,7 +1340,7 @@ static int config_disp_output(struct mxc_vout_output *vout) "set display fb to %d %d\n", var.xres, var.yres); - ret = set_window_position(vout); + ret = set_window_position(vout, &vout->win_pos); if (ret < 0) return ret; @@ -1286,7 +1360,9 @@ static int config_disp_output(struct mxc_vout_output *vout) vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size; console_lock(); + fbi->flags |= FBINFO_MISC_USEREVENT; ret = fb_blank(fbi, FB_BLANK_UNBLANK); + fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); return ret; @@ -1295,13 +1371,21 @@ static int config_disp_output(struct mxc_vout_output *vout) static void release_disp_output(struct mxc_vout_output *vout) { struct fb_info *fbi = vout->fbi; + struct mxcfb_pos pos; console_lock(); + fbi->flags |= FBINFO_MISC_USEREVENT; fb_blank(fbi, FB_BLANK_POWERDOWN); + fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); + /* restore pos to 0,0 avoid fb pan display hang? */ + pos.x = 0; + pos.y = 0; + set_window_position(vout, &pos); + /* fix if ic bypass crack smem_start */ - if (is_pp_bypass(vout)) { + if (vout->bypass_pp) { console_lock(); fbi->fix.smem_start = vout->disp_bufs[0]; console_unlock(); @@ -1309,7 +1393,9 @@ static void release_disp_output(struct mxc_vout_output *vout) if (get_ipu_channel(fbi) == MEM_BG_SYNC) { console_lock(); + fbi->flags |= FBINFO_MISC_USEREVENT; fb_blank(fbi, FB_BLANK_UNBLANK); + fbi->flags &= ~FBINFO_MISC_USEREVENT; console_unlock(); } } @@ -1362,11 +1448,11 @@ static int mxc_vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type int ret = 0; if (q->streaming) { - del_timer(&vout->timer); - cancel_work_sync(&vout->disp_work); flush_workqueue(vout->v4l_wq); + del_timer_sync(&vout->timer); + release_disp_output(vout); ret = videobuf_streamoff(&vout->vbq); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 7ae1ff64a48c..65bcce3c7fb3 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -499,7 +499,7 @@ config APANIC_PLABEL crashdumps, enter it here. config MXS_PERFMON tristate "i.MX Performance Monitor" - depends on ARCH_MX50 + depends on ARCH_MX50 || ARCH_MX6 default y source "drivers/misc/c2port/Kconfig" diff --git a/drivers/misc/mxs-perfmon.c b/drivers/misc/mxs-perfmon.c index 94916e000e84..5986e1ca9508 100644 --- a/drivers/misc/mxs-perfmon.c +++ b/drivers/misc/mxs-perfmon.c @@ -27,6 +27,7 @@ #include <linux/platform_device.h> #include <linux/sysfs.h> #include <linux/io.h> +#include <linux/clk.h> #include <linux/fsl_devices.h> #include <mach/hardware.h> #include <asm/irq.h> @@ -104,6 +105,7 @@ struct mxs_perfmon_data { struct attribute_group attr_group; unsigned int base; unsigned int initial; + struct clk *clk; /* attribute ** follow */ /* device_attribute follow */ }; @@ -150,6 +152,7 @@ perfmon_show(struct device *dev, struct device_attribute *attr, char *buf) int idx; u32 val; ssize_t result = 0; + struct mxs_platform_perfmon_data *pdata = pdev->dev.platform_data; idx = attr - devattr; if ((unsigned int)idx >= pd->count) @@ -163,6 +166,11 @@ perfmon_show(struct device *dev, struct device_attribute *attr, char *buf) [idx - pd->pdata->bit_config_cnt]; if (!pd->initial) { + if (pd->clk) + clk_enable(pd->clk); + if (pdata->plt_init) + pdata->plt_init(); + mxs_reset_block((void *)pd->base, true); pd->initial = true; } @@ -204,6 +212,7 @@ perfmon_store(struct device *dev, struct device_attribute *attr, struct mxs_perfmon_bit_config *pb; int idx, r; unsigned long val, newval; + struct mxs_platform_perfmon_data *pdata = pdev->dev.platform_data; idx = attr - devattr; if ((unsigned int)idx >= pd->count) @@ -220,6 +229,11 @@ perfmon_store(struct device *dev, struct device_attribute *attr, [idx - pd->pdata->bit_config_cnt]; if (!pd->initial) { + if (pd->clk) + clk_enable(pd->clk); + if (pdata->plt_init) + pdata->plt_init(); + mxs_reset_block((void *)pd->base, true); pd->initial = true; } @@ -278,6 +292,7 @@ static int __devinit mxs_perfmon_probe(struct platform_device *pdev) struct device_attribute *devattr; int i, cnt, size; int err; + struct device *dev = &pdev->dev; pdata = pdev->dev.platform_data; if (pdata == NULL) @@ -301,6 +316,7 @@ static int __devinit mxs_perfmon_probe(struct platform_device *pdev) pd->pdata_common = pdata_common; pd->base = (unsigned int)ioremap(res->start, res->end - res->start); pd->initial = false; + pd->clk = clk_get(dev, "perfmon"); platform_set_drvdata(pdev, pd); pd->count = cnt; @@ -341,10 +357,21 @@ static int __devinit mxs_perfmon_probe(struct platform_device *pdev) static int __devexit mxs_perfmon_remove(struct platform_device *pdev) { struct mxs_perfmon_data *pd; + struct mxs_platform_perfmon_data *pdata = pdev->dev.platform_data;; pd = platform_get_drvdata(pdev); sysfs_remove_group(&pdev->dev.kobj, &pd->attr_group); platform_set_drvdata(pdev, NULL); + + if (pdata->plt_exit) + pdata->plt_exit(); + + if (pd->clk) { + if (pd->initial) + clk_disable(pd->clk); + clk_put(pd->clk); + } + kfree(pd); return 0; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index e68884c849e9..3f164e7ba7fa 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -104,7 +104,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) if (boarddata && gpio_is_valid(boarddata->cd_gpio) && gpio_get_value(boarddata->cd_gpio)) /* no card, if a valid gpio says so... */ - val &= SDHCI_CARD_PRESENT; + val &= ~SDHCI_CARD_PRESENT; else /* ... in all other cases assume card is present */ val |= SDHCI_CARD_PRESENT; @@ -469,6 +469,8 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd host->ocr_avail_sd |= MMC_VDD_165_195; if (boarddata->support_8bit) host->mmc->caps |= MMC_CAP_8_BIT_DATA; + if (boarddata->keep_power_at_suspend) + host->mmc->pm_caps |= MMC_PM_KEEP_POWER; if (cpu_is_mx6q()) { host->mmc->caps |= MMC_CAP_1_8V_DDR; host->tuning_min = SDHCI_TUNE_CTRL_MIN; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index dad820ad423f..c051ea791e95 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1398,7 +1398,7 @@ static void sdhci_tasklet_card(unsigned long param) out: spin_unlock_irqrestore(&host->lock, flags); - mmc_detect_change(host->mmc, msecs_to_jiffies(200)); + mmc_detect_change(host->mmc, msecs_to_jiffies(500)); } static void sdhci_tasklet_finish(unsigned long param) diff --git a/drivers/mxc/gpu-viv/Kbuild b/drivers/mxc/gpu-viv/Kbuild index fee9dfdc9d62..aa1ec7bf5eba 100644 --- a/drivers/mxc/gpu-viv/Kbuild +++ b/drivers/mxc/gpu-viv/Kbuild @@ -209,6 +209,15 @@ else EXTRA_CFLAGS += -DgcdSMP=0 endif +ifeq ($(VIVANTE_NO_3D),1) +EXTRA_CFLAGS += -DVIVANTE_NO_3D +endif + +ifeq ($(ENABLE_OUTER_CACHE_PATCH), 1) +EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=1 +else +EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=0 +endif EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c index 2b5e9ece7fc3..20c79b88806f 100644 --- a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c +++ b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c @@ -1792,7 +1792,7 @@ gckVGHARDWARE_SetPowerManagementState( gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->idleSemaphore)); } /* Reset power off time */ - gcmkONERROR(gckOS_GetTicks(¤tTime)); + gcmkVERIFY_OK(gckOS_GetTicks(¤tTime)); Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout; if (commitMutex) diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c index dbf8680cf9d3..f1b4dd099cec 100644 --- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c +++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c @@ -67,6 +67,14 @@ gcvFALSE, gcvFALSE \ ) +#define _STATE_MIRROR(reg, mirror) \ + _StateMirror(\ + Context, \ + reg ## _Address >> 2, \ + reg ## _Count, \ + mirror ## _Address >> 2 \ + ) + #define _STATE_HINT(reg) \ _State(\ Context, index, \ @@ -353,6 +361,32 @@ _State( /* Return number of slots required. */ return Size; } + +static gctSIZE_T +_StateMirror( + IN gckCONTEXT Context, + IN gctUINT32 Address, + IN gctSIZE_T Size, + IN gctUINT32 AddressMirror + ) +{ + gctSIZE_T i; + + /* Process when buffer is set. */ + if (Context->buffer != gcvNULL) + { + /* Walk all states. */ + for (i = 0; i < Size; i++) + { + /* Copy the mapping address. */ + Context->map[Address + i].index = + Context->map[AddressMirror + i].index; + } + } + + /* Return the number of required maps. */ + return Size; +} #endif static gceSTATUS @@ -565,7 +599,7 @@ _InitializeContextBuffer( index += _State(Context, index, 0x0091C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE); index += _CLOSE_RANGE(); - if (Context->hardware->identity.instructionCount >= 2048) + if (Context->hardware->identity.instructionCount > 1024) { /* New Shader instruction memory. */ index += _State(Context, index, 0x0085C >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE); @@ -579,7 +613,7 @@ _InitializeContextBuffer( index += _CLOSE_RANGE(); } } - else if (Context->hardware->identity.instructionCount >= 1024) + else if (Context->hardware->identity.instructionCount > 256) { /* VX instruction memory. */ for (i = 0; i < 4096; i += 1024) @@ -588,11 +622,7 @@ _InitializeContextBuffer( index += _CLOSE_RANGE(); } - for (i = 0; i < 4096; i += 1024) - { - index += _State(Context, index, (0x08000 >> 2) + i, 0x00000000, 1024, gcvFALSE, gcvFALSE); - index += _CLOSE_RANGE(); - } + index += _StateMirror(Context, (0x08000 >> 2), 4096, 0x0C000 >> 2); } /* Store the index of the "XD" entry. */ diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c index fe6c1a93bfe6..0ceced9754bb 100644 --- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c +++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c @@ -715,15 +715,15 @@ gckHARDWARE_InitializeHardware( 0x00418, baseAddress)); -#ifndef VIVANTE_NO_3D gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, - 0x00420, + 0x00428, baseAddress)); +#ifndef VIVANTE_NO_3D gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, - 0x00428, + 0x00420, baseAddress)); gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, @@ -3684,6 +3684,22 @@ gckHARDWARE_SetPowerManagementState( Hardware->powerMutex, gcvINFINITE)); mutexAcquired = gcvTRUE; + + /* chipPowerState may be changed by external world during the time + ** we give up powerMutex, so updating flag now is necessary. */ + flag = flags[Hardware->chipPowerState][State]; + + if (flag == 0) + { + gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore)); + globalAcquired = gcvFALSE; + + gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex)); + mutexAcquired = gcvFALSE; + + gcmkFOOTER_NO(); + return gcvSTATUS_OK; + } } else { @@ -3695,6 +3711,40 @@ gckHARDWARE_SetPowerManagementState( gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore)); globalAcquired = gcvFALSE; } + else + { + if (State == gcvPOWER_OFF || State == gcvPOWER_SUSPEND || State == gcvPOWER_IDLE) + { + /* Acquire the global semaphore if it has not been acquired. */ + status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore); + if (status == gcvSTATUS_OK) + { + globalAcquired = gcvTRUE; + } + else if (status != gcvSTATUS_TIMEOUT) + { + /* Other errors. */ + gcmkONERROR(status); + } + /* Ignore gcvSTATUS_TIMEOUT and leave globalAcquired as gcvFALSE. + ** gcvSTATUS_TIMEOUT means global semaphore has already + ** been acquired before this operation, so even if we fail, + ** we should not release it in our error handling. It should be + ** released by the next successful global gcvPOWER_ON. */ + } + + /* Global power management can't be aborted, so sync with + ** proceeding last commit. */ + if (flag & gcvPOWER_FLAG_ACQUIRE) + { + /* Acquire the power management semaphore. */ + gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore)); + acquired = gcvTRUE; + + /* avoid acquiring again. */ + flag &= ~gcvPOWER_FLAG_ACQUIRE; + } + } if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON)) { @@ -3714,15 +3764,20 @@ gckHARDWARE_SetPowerManagementState( gctBOOL idle; gctINT32 atomValue; - /* Check commit atom. */ - gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue)); - - if (atomValue > 0) + /* For global operation, all pending commits have already been + ** blocked by globalSemaphore or powerSemaphore.*/ + if (!global) { - /* Commits are pending - abort power management. */ - status = broadcast ? gcvSTATUS_CHIP_NOT_READY - : gcvSTATUS_MORE_DATA; - goto OnError; + /* Check commit atom. */ + gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue)); + + if (atomValue > 0) + { + /* Commits are pending - abort power management. */ + status = broadcast ? gcvSTATUS_CHIP_NOT_READY + : gcvSTATUS_MORE_DATA; + goto OnError; + } } if (broadcast) @@ -3780,13 +3835,6 @@ gckHARDWARE_SetPowerManagementState( /* Acquire the power management semaphore. */ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore)); acquired = gcvTRUE; - - if (global) - { - /* Acquire the global semaphore. */ - gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore)); - globalAcquired = gcvTRUE; - } } if (flag & gcvPOWER_FLAG_STOP) @@ -3796,7 +3844,7 @@ gckHARDWARE_SetPowerManagementState( /* Stop the Isr. */ gcmkONERROR(Hardware->stopIsr(Hardware->isrContext)); - } + } /* Get time until stopped. */ gcmkPROFILE_QUERY(time, stopTime); @@ -3883,6 +3931,18 @@ gckHARDWARE_SetPowerManagementState( if (global) { + /* Verify global semaphore has been acquired already before + ** we release it. + ** If it was acquired, gckOS_TryAcquireSemaphore will return + ** gcvSTATUS_TIMEOUT and we release it. Otherwise, global + ** semaphore will be acquried now, but it still is released + ** immediately. */ + status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore); + if (status != gcvSTATUS_TIMEOUT) + { + gcmkONERROR(status); + } + /* Release the global semaphore. */ gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore)); globalAcquired = gcvFALSE; diff --git a/drivers/mxc/gpu-viv/config b/drivers/mxc/gpu-viv/config index 043a91b535f2..68a43adf1aae 100644 --- a/drivers/mxc/gpu-viv/config +++ b/drivers/mxc/gpu-viv/config @@ -29,4 +29,7 @@ NONPAGED_MEMORY_BUFFERABLE ?= 1 CACHE_FUNCTION_UNIMPLEMENTED ?= 0 VIVANTE_ENABLE_VG ?= 1 NO_USER_DIRECT_ACCESS_FROM_KERNEL ?= 1 +VIVANTE_NO_3D ?= 0 +ENABLE_OUTER_CACHE_PATCH ?= 1 ENABLE_GPU_CLOCK_BY_DRIVER = 1 + diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c index 8af629283ea2..4aeb53ce883a 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c @@ -681,13 +681,6 @@ gckKERNEL_Dispatch( /* Get the current process ID. */ gcmkONERROR(gckOS_GetProcessID(&processID)); -#ifdef UNDER_CE - if (!FromUser) - { - gcmkONERROR(gckOS_GetCurrentProcessID(&processID)); - } -#endif - #if gcdSECURE_USER gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache)); #endif @@ -1566,23 +1559,81 @@ gckKERNEL_Dispatch( if ((node = Interface->u.GetSharedInfo.node) != gcvNULL) { - if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) - { - data = &node->VidMem.sharedInfo; - } - else - { - data = &node->Virtual.sharedInfo; - } + switch (Interface->u.GetSharedInfo.infoType) + { + case gcvVIDMEM_INFO_GENERIC: + { /* Generic data stored */ + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) + { + data = &node->VidMem.sharedInfo; + + } + else + { + data = &node->Virtual.sharedInfo; + } + + gcmkONERROR(gckOS_CopyToUserData( + Kernel->os, + data, + Interface->u.GetSharedInfo.nodeData, + sizeof(gcsVIDMEM_NODE_SHARED_INFO) + )); + } + break; - gcmkONERROR(gckOS_CopyToUserData( - Kernel->os, - data, - Interface->u.GetSharedInfo.nodeData, - sizeof(gcsVIDMEM_NODE_SHARED_INFO) - )); + case gcvVIDMEM_INFO_DIRTY_RECTANGLE: + { /* Dirty rectangle stored */ + gcsVIDMEM_NODE_SHARED_INFO *storedSharedInfo; + gcsVIDMEM_NODE_SHARED_INFO alignedSharedInfo; + + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) + { + storedSharedInfo = &node->VidMem.sharedInfo; + } + else + { + storedSharedInfo = &node->Virtual.sharedInfo; + } + + /* Stored shared info holds the unaligned dirty rectangle. + Align it first. */ + + /* Hardware requires 64-byte aligned address, and 16x4 pixel aligned rectsize. + We simply align to 32 pixels which covers both 16- and 32-bpp formats. */ + + /* Make sure we have a legit rectangle. */ + gcmkASSERT((storedSharedInfo->RectSize.width != 0) && (storedSharedInfo->RectSize.height != 0)); + + alignedSharedInfo.SrcOrigin.x = gcmALIGN_BASE(storedSharedInfo->SrcOrigin.x, 32); + alignedSharedInfo.RectSize.width = gcmALIGN((storedSharedInfo->RectSize.width + (storedSharedInfo->SrcOrigin.x - alignedSharedInfo.SrcOrigin.x)), 16); + + alignedSharedInfo.SrcOrigin.y = gcmALIGN_BASE(storedSharedInfo->SrcOrigin.y, 4); + alignedSharedInfo.RectSize.height = gcmALIGN((storedSharedInfo->RectSize.height + (storedSharedInfo->SrcOrigin.y - alignedSharedInfo.SrcOrigin.y)), 4); + + gcmkONERROR(gckOS_CopyToUserData( + Kernel->os, + &alignedSharedInfo, + Interface->u.GetSharedInfo.nodeData, + sizeof(gcsVIDMEM_NODE_SHARED_INFO) + )); + + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, + "Node = %p, unaligned rectangle (l=%d, t=%d, w=%d, h=%d) aligned to (l=%d, t=%d, w=%d, h=%d)", node, + storedSharedInfo->SrcOrigin.x, storedSharedInfo->SrcOrigin.y, + storedSharedInfo->RectSize.width, storedSharedInfo->RectSize.height, + alignedSharedInfo.SrcOrigin.x, alignedSharedInfo.SrcOrigin.y, + alignedSharedInfo.RectSize.width, alignedSharedInfo.RectSize.height); + + /* Rectangle */ + storedSharedInfo->SrcOrigin.x = + storedSharedInfo->SrcOrigin.y = + storedSharedInfo->RectSize.width = + storedSharedInfo->RectSize.height = 0; + } + break; + } } - break; case gcvHAL_SET_SHARED_INFO: @@ -1637,21 +1688,86 @@ gckKERNEL_Dispatch( if ((node = Interface->u.SetSharedInfo.node) != gcvNULL) { - if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) - { - data = &node->VidMem.sharedInfo; - } - else - { - data = &node->Virtual.sharedInfo; - } + switch (Interface->u.SetSharedInfo.infoType) + { + case gcvVIDMEM_INFO_GENERIC: + { /* Generic data stored */ + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) + { + data = &node->VidMem.sharedInfo; + } + else + { + data = &node->Virtual.sharedInfo; + } + + gcmkONERROR(gckOS_CopyFromUserData( + Kernel->os, + data, + Interface->u.SetSharedInfo.nodeData, + sizeof(gcsVIDMEM_NODE_SHARED_INFO) + )); + } + break; - gcmkONERROR(gckOS_CopyFromUserData( - Kernel->os, - data, - Interface->u.SetSharedInfo.nodeData, - sizeof(gcsVIDMEM_NODE_SHARED_INFO) - )); + case gcvVIDMEM_INFO_DIRTY_RECTANGLE: + { /* Dirty rectangle stored */ + gcsVIDMEM_NODE_SHARED_INFO newSharedInfo; + gcsVIDMEM_NODE_SHARED_INFO *currentSharedInfo; + gctINT dirtyX, dirtyY, right, bottom; + + /* Expand the dirty rectangle stored in the node to include the rectangle passed in. */ + gcmkONERROR(gckOS_CopyFromUserData( + Kernel->os, + &newSharedInfo, + Interface->u.SetSharedInfo.nodeData, + gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO) + )); + + if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) + { + currentSharedInfo = &node->VidMem.sharedInfo; + } + else + { + currentSharedInfo = &node->Virtual.sharedInfo; + } + + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "Node = %p Stored rectangle (l=%d, t=%d, w=%d, h=%d)", node, + currentSharedInfo->SrcOrigin.x, currentSharedInfo->SrcOrigin.y, + currentSharedInfo->RectSize.width, currentSharedInfo->RectSize.height); + + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "To combine with (l=%d, t=%d, w=%d, h=%d)", + newSharedInfo.SrcOrigin.x, newSharedInfo.SrcOrigin.y, + newSharedInfo.RectSize.width, newSharedInfo.RectSize.height); + + if ((currentSharedInfo->RectSize.width == 0) || (currentSharedInfo->RectSize.height == 0)) + { /* Setting it for the first time */ + currentSharedInfo->SrcOrigin.x = newSharedInfo.SrcOrigin.x; + currentSharedInfo->SrcOrigin.y = newSharedInfo.SrcOrigin.y; + currentSharedInfo->RectSize.width = newSharedInfo.RectSize.width; + currentSharedInfo->RectSize.height = newSharedInfo.RectSize.height; + } + else + { + /* Expand the stored rectangle to include newly locked rectangle */ + dirtyX = (newSharedInfo.SrcOrigin.x < currentSharedInfo->SrcOrigin.x) ? newSharedInfo.SrcOrigin.x : currentSharedInfo->SrcOrigin.x; + right = gcmMAX((currentSharedInfo->SrcOrigin.x + currentSharedInfo->RectSize.width), (newSharedInfo.SrcOrigin.x + newSharedInfo.RectSize.width)); + currentSharedInfo->RectSize.width = right - dirtyX; + currentSharedInfo->SrcOrigin.x = dirtyX; + + dirtyY = (newSharedInfo.SrcOrigin.y < currentSharedInfo->SrcOrigin.y) ? newSharedInfo.SrcOrigin.y : currentSharedInfo->SrcOrigin.y; + bottom = gcmMAX((currentSharedInfo->SrcOrigin.y + currentSharedInfo->RectSize.height), (newSharedInfo.SrcOrigin.y + newSharedInfo.RectSize.height)); + currentSharedInfo->RectSize.height = bottom - dirtyY; + currentSharedInfo->SrcOrigin.y = dirtyY; + } + + gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "Combined rectangle (l=%d, t=%d, w=%d, h=%d)", + currentSharedInfo->SrcOrigin.x, currentSharedInfo->SrcOrigin.y, + currentSharedInfo->RectSize.width, currentSharedInfo->RectSize.height); + } + break; + } } break; diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c index a9489eaf20ad..ec9c8ee2ee56 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c @@ -1905,6 +1905,13 @@ gckCOMMAND_Commit( EventQueue = nextEventRecord; } + if (Command->kernel->eventObj->queueHead == gcvNULL) + { + /* Commit done event by which work thread knows all jobs done. */ + gcmkVERIFY_OK( + gckEVENT_CommitDone(Command->kernel->eventObj, gcvKERNEL_PIXEL)); + } + /* Submit events. */ gcmkONERROR(gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE)); diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c index 6c9a65b923db..1efdc5f10368 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c @@ -742,8 +742,13 @@ gckEVENT_AllocateRecord( gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT); gcmkVERIFY_ARGUMENT(Record != gcvNULL); + /* Acquire the mutex. */ + gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE)); + acquired = gcvTRUE; + /* Test if we are below the allocation threshold. */ - if (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD)) + if ( (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD)) || + (Event->freeEventCount == 0) ) { /* Allocate a bunch of records. */ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1) @@ -755,25 +760,13 @@ gckEVENT_AllocateRecord( record = pointer; - /* Acquire the mutex. */ - gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE)); - acquired = gcvTRUE; - /* Push it on the free list. */ record->next = Event->freeEventList; Event->freeEventList = record; Event->freeEventCount += 1; - - /* Release the mutex. */ - gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex)); - acquired = gcvFALSE; } } - /* Acquire the mutex. */ - gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE)); - acquired = gcvTRUE; - *Record = Event->freeEventList; Event->freeEventList = Event->freeEventList->next; Event->freeEventCount -= 1; @@ -852,6 +845,7 @@ gckEVENT_AddList( || (Interface->command == gcvHAL_SIGNAL) || (Interface->command == gcvHAL_UNMAP_USER_MEMORY) || (Interface->command == gcvHAL_TIMESTAMP) + || (Interface->command == gcvHAL_COMMIT_DONE) ); /* Validate the source. */ @@ -1253,6 +1247,52 @@ OnError: /******************************************************************************* ** +** gckEVENT_CommitDone +** +** Schedule an event to wake up work thread when commit is done by GPU. +** +** INPUT: +** +** gckEVENT Event +** Pointer to an gckEVENT object. +** +** gceKERNEL_WHERE FromWhere +** Place in the pipe where the event needs to be generated. +** +** OUTPUT: +** +** Nothing. +*/ +gceSTATUS +gckEVENT_CommitDone( + IN gckEVENT Event, + IN gceKERNEL_WHERE FromWhere + ) +{ + gceSTATUS status; + gcsHAL_INTERFACE iface; + + gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT); + + iface.command = gcvHAL_COMMIT_DONE; + + /* Append it to the queue. */ + gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE)); + + /* Success. */ + gcmkFOOTER_NO(); + return gcvSTATUS_OK; + +OnError: + /* Return the status. */ + gcmkFOOTER(); + return status; +} +/******************************************************************************* +** ** gckEVENT_Submit ** ** Submit the current event queue to the GPU. @@ -2208,6 +2248,9 @@ gckEVENT_Notify( } break; + case gcvHAL_COMMIT_DONE: + break; + default: /* Invalid argument. */ gcmkTRACE_ZONE_N( diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c index 2c282f861b18..f3fdc7530c42 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c @@ -266,6 +266,9 @@ gckVIDMEM_ConstructVirtual( #endif node->Virtual.freed = gcvFALSE; + + gcmkONERROR(gckOS_ZeroMemory(&node->Virtual.sharedInfo, gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO))); + /* Create the mutex. */ gcmkONERROR( gckOS_CreateMutex(os, &node->Virtual.mutex)); @@ -514,6 +517,8 @@ gckVIDMEM_Construct( node->VidMem.locked = 0; + gcmkONERROR(gckOS_ZeroMemory(&node->VidMem.sharedInfo, gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO))); + #ifdef __QNXNTO__ #if gcdUSE_VIDMEM_PER_PID node->VidMem.processID = memory->pid; diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h index bc20a4331031..2dfa3e74f5de 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h @@ -2116,6 +2116,12 @@ gckEVENT_Unlock( ); gceSTATUS +gckEVENT_CommitDone( + IN gckEVENT Event, + IN gceKERNEL_WHERE FromWhere + ); + +gceSTATUS gckEVENT_Submit( IN gckEVENT Event, IN gctBOOL Wait, diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h index c1711fa6484d..03631fe1528f 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h @@ -118,6 +118,7 @@ typedef struct _gcsTLS gcoHARDWARE hardware2D; #if gcdENABLE_VG gcoVGHARDWARE vg; + gcoVG engineVG; #endif /* gcdENABLE_VG */ gctPOINTER context; gctTLS_DESTRUCTOR destructor; @@ -1620,6 +1621,20 @@ gcoSURF_QueryVidMemNode( OUT gctUINT_PTR Bytes ); +/* Set usage attribute of a surface. */ +gceSTATUS +gcoSURF_SetUsage( + IN gcoSURF Surface, + IN gceSURF_USAGE Usage + ); + +/* Return usage attribute of a surface. */ +gceSTATUS +gcoSURF_QueryUsage( + IN gcoSURF Surface, + OUT gceSURF_USAGE *Usage + ); + /* Set the color type of the surface. */ gceSTATUS gcoSURF_SetColorType( @@ -1832,6 +1847,14 @@ gcoSURF_SetOffset( IN gctUINT Offset ); +gceSTATUS +gcoSURF_NODE_Cache( + IN gcsSURF_NODE_PTR Node, + IN gctPOINTER Logical, + IN gctSIZE_T Bytes, + IN gceCACHEOPERATION Operation + ); + /******************************************************************************\ ********************************* gcoDUMP Object ******************************** \******************************************************************************/ diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h index aaf50c42e9b8..37715ffdd504 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h @@ -428,6 +428,7 @@ gceUNIFORM_FLAGS; #define gcdUNIFORM_KERNEL_ARG_MASK (gcvUNIFORM_KERNEL_ARG | \ gcvUNIFORM_KERNEL_ARG_LOCAL | \ gcvUNIFORM_KERNEL_ARG_SAMPLER | \ + gcvUNIFORM_KERNEL_ARG_PRIVATE | \ gcvUNIFORM_KERNEL_ARG_CONSTANT) /******************************************************************************* diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h index a16a60d0bfb5..505a23d93b46 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h @@ -147,7 +147,9 @@ typedef enum _gceHAL_COMMAND_CODES /* Shared info for each process */ gcvHAL_GET_SHARED_INFO, gcvHAL_SET_SHARED_INFO, - gcvHAL_QUERY_COMMAND_BUFFER + gcvHAL_QUERY_COMMAND_BUFFER, + + gcvHAL_COMMIT_DONE, } gceHAL_COMMAND_CODES; @@ -859,7 +861,6 @@ typedef struct _gcsHAL_INTERFACE #endif -#if gcdENABLE_SHARED_INFO struct _gcsHAL_GET_SHARED_INFO { IN gctUINT32 pid; @@ -869,6 +870,7 @@ typedef struct _gcsHAL_INTERFACE /* fix size */ OUT gctUINT8_PTR nodeData; gctSIZE_T size; + IN gceVIDMEM_NODE_SHARED_INFO_TYPE infoType; } GetSharedInfo; @@ -879,9 +881,9 @@ typedef struct _gcsHAL_INTERFACE IN gctUINT8_PTR data; IN gctUINT8_PTR nodeData; IN gctSIZE_T size; + IN gceVIDMEM_NODE_SHARED_INFO_TYPE infoType; } SetSharedInfo; -#endif } u; } diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h index 5ae49e05dfab..165234a579fa 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h @@ -330,13 +330,6 @@ gcoSURF_ExportRenderTarget( IN gcoSURF SrcSurface ); -/* Export render target by given key. */ -gceSTATUS -gcoSURF_ExportRenderTargetByKey( - IN gcoSURF Key, - IN gcoSURF SrcSurface -); - /* Import the render target. */ gceSTATUS gcoSURF_ImportRenderTarget( @@ -344,14 +337,6 @@ gcoSURF_ImportRenderTarget( IN gcoSURF SrcSurface ); -/* Import the render target by given key. */ -gceSTATUS -gcoSURF_ImportRenderTargetByKey( - IN gctUINT32 Pid, - IN gcoSURF Key, - IN gcoSURF SrcSurface -); - /* Save the Resolve info to kernel. */ gceSTATUS gcoSURF_PrepareRemoteResolveRect( @@ -361,6 +346,13 @@ gcoSURF_PrepareRemoteResolveRect( IN gcsPOINT_PTR RectSize ); +/* Resolve using the rectangle info previously saved in the vid mem node. */ +gceSTATUS +gcoSURF_ResolveFromStoredRect( + IN gcoSURF SrcSurface, + IN gcoSURF DestSurface + ); + /* Using the info that Process Pid saved to do resolve. */ gceSTATUS gcoSURF_RemoteResolveRect( @@ -369,8 +361,7 @@ gcoSURF_RemoteResolveRect( IN gctBOOL *resolveDiscarded ); -/* - Return the "resolve submitted indicator" signal. */ +/* Return the "resolve submitted indicator" signal. */ gceSTATUS gcoSURF_GetRTSignal( IN gcoSURF RTSurface, @@ -401,14 +392,6 @@ gcoSURF_CPUCacheOperation( IN gceCACHEOPERATION Operation ); -gceSTATUS -gcoSURF_NODE_Cache( - IN gcsSURF_NODE_PTR Node, - IN gctPOINTER Logical, - IN gctSIZE_T Bytes, - IN gceCACHEOPERATION Operation - ); - /******************************************************************************\ ******************************** gcoINDEX Object ******************************* \******************************************************************************/ @@ -1843,7 +1826,8 @@ gcoHAL_GetSharedInfo( OUT gctUINT8_PTR Data, IN gctSIZE_T Bytes, IN gcuVIDMEM_NODE_PTR Node, - OUT gctUINT8_PTR NodeData + OUT gctUINT8_PTR NodeData, + IN gceVIDMEM_NODE_SHARED_INFO_TYPE SharedInfoType ); gceSTATUS @@ -1852,7 +1836,8 @@ gcoHAL_SetSharedInfo( IN gctUINT8_PTR Data, IN gctSIZE_T Bytes, IN gcuVIDMEM_NODE_PTR Node, - IN gctUINT8_PTR NodeData + IN gctUINT8_PTR NodeData, + IN gceVIDMEM_NODE_SHARED_INFO_TYPE SharedInfoType ); #ifdef __cplusplus diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h index 9ade98fa0b13..f28675448dae 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h @@ -128,6 +128,7 @@ typedef enum _gceFEATURE gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT, gcvFEATURE_2D_ROTATION_STALL_FIX, gcvFEATURE_2D_MULTI_SOURCE_BLT_EX, + gcvFEATURE_BUG_FIXES10, } gceFEATURE; @@ -160,6 +161,13 @@ typedef enum _gceCACHEOPERATION } gceCACHEOPERATION; +typedef enum _gceVIDMEM_NODE_SHARED_INFO_TYPE +{ + gcvVIDMEM_INFO_GENERIC, + gcvVIDMEM_INFO_DIRTY_RECTANGLE +} +gceVIDMEM_NODE_SHARED_INFO_TYPE; + /* Surface types. */ typedef enum _gceSURF_TYPE { @@ -205,6 +213,14 @@ typedef enum _gceSURF_TYPE } gceSURF_TYPE; +typedef enum _gceSURF_USAGE +{ + gcvSURF_USAGE_UNKNOWN, + gcvSURF_USAGE_RESOLVE_AFTER_CPU, + gcvSURF_USAGE_RESOLVE_AFTER_3D +} +gceSURF_USAGE; + typedef enum _gceSURF_COLOR_TYPE { gcvSURF_COLOR_UNKNOWN = 0, diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h index fdfc07bf0e32..fc97c78d5d80 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h @@ -524,17 +524,6 @@ # define gcdENABLE_TS_DOUBLE_BUFFER 1 #endif - -/* - gcdENABLE_SHARED_INFO - - When non-zero, enable process store some shared data in kernel - which can be got by other processes - */ -#ifndef gcdENABLE_SHARED_INFO -# define gcdENABLE_SHARED_INFO 1 -#endif - /* gcd6000_SUPPORT @@ -624,16 +613,46 @@ #endif /* - gcdSYNC_CPU_APP_WITH_COMPOSITOR + gcdCOPYBLT_OPTIMIZATION - Synchronize access to a linear buffer between CPU app and compositor (i.e. GPU - 2D, 3D or CE). + Combine dirty areas resulting from Android's copyBlt. */ -#ifndef gcdSYNC_CPU_APP_WITH_COMPOSITOR -# define gcdSYNC_CPU_APP_WITH_COMPOSITOR 0 +#ifndef gcdCOPYBLT_OPTIMIZATION +# define gcdCOPYBLT_OPTIMIZATION 0 #endif +/* + gcdGPU_LINEAR_BUFFER_ENABLED + + Use linear buffer for GPU apps so HWC can do 2D composition. +*/ +#ifndef gcdGPU_LINEAR_BUFFER_ENABLED +# define gcdGPU_LINEAR_BUFFER_ENABLED 0 +#endif + +/* + gcdSHARED_RESOLVE_BUFFER_ENABLED + + Use shared resolve buffer for all app buffers. +*/ +#ifndef gcdSHARED_RESOLVE_BUFFER_ENABLED +# define gcdSHARED_RESOLVE_BUFFER_ENABLED 0 +#endif + +/* + gcdUSE_TRIANGLE_STRIP_PATCH + */ #ifndef gcdUSE_TRIANGLE_STRIP_PATCH -# define gcdUSE_TRIANGLE_STRIP_PATCH 1 +# define gcdUSE_TRIANGLE_STRIP_PATCH 1 +#endif + +/* + gcdENABLE_OUTER_CACHE_PATCH + + Enable the outer cache patch. +*/ +#ifndef gcdENABLE_OUTER_CACHE_PATCH +# define gcdENABLE_OUTER_CACHE_PATCH 0 #endif #endif /* __gc_hal_options_h_ */ diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h index 6605f4fccb5b..6213ffaaef8f 100644 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h @@ -28,9 +28,9 @@ #define gcvVERSION_MINOR 6 -#define gcvVERSION_PATCH 2 +#define gcvVERSION_PATCH 3 -#define gcvVERSION_BUILD 1251 +#define gcvVERSION_BUILD 1280 #define gcvVERSION_DATE __DATE__ diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h index a9b633e5d858..d6ceba73e41e 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h @@ -46,7 +46,7 @@ typedef va_list gctARGUMENTS; va_end(Arguments) #define gcmkDECLARE_LOCK(__spinLock__) \ - static spinlock_t __spinLock__ = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(__spinLock__); #define gcmkLOCKSECTION(__spinLock__) \ spin_lock(&__spinLock__) diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c index e7cc92f74e7b..e4ef19b8c654 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c @@ -511,6 +511,13 @@ long drv_ioctl( } } + /* Redo system call after pending signal is handled. */ + if (status == gcvSTATUS_INTERRUPTED) + { + gcmkFOOTER(); + return -ERESTARTSYS; + } + if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY)) { /* Special case for mapped memory. */ diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c index ba4f032039b8..c22aa460d2f4 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c @@ -5468,6 +5468,7 @@ outer_func( return gcvSTATUS_OK; } +#if gcdENABLE_OUTER_CACHE_PATCH /******************************************************************************* ** _HandleOuterCache ** @@ -5561,6 +5562,7 @@ OnError: return status; } #endif +#endif /******************************************************************************* ** gckOS_CacheClean @@ -5619,7 +5621,11 @@ gckOS_CacheClean( #if defined(CONFIG_OUTER_CACHE) /* Outer cache. */ +#if gcdENABLE_OUTER_CACHE_PATCH _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN); +#else + outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes); +#endif #endif #elif defined(CONFIG_MIPS) @@ -5694,7 +5700,11 @@ gckOS_CacheInvalidate( #if defined(CONFIG_OUTER_CACHE) /* Outer cache. */ +#if gcdENABLE_OUTER_CACHE_PATCH _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE); +#else + outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes); +#endif #endif #elif defined(CONFIG_MIPS) @@ -5762,7 +5772,11 @@ gckOS_CacheFlush( #if defined(CONFIG_OUTER_CACHE) /* Outer cache. */ +#if gcdENABLE_OUTER_CACHE_PATCH _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH); +#else + outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes); +#endif #endif #elif defined(CONFIG_MIPS) diff --git a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c index 1e05cc5808b5..aa9fdaf27cdc 100644 --- a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c +++ b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c @@ -52,8 +52,8 @@ static u32 truncate(u32 up, /* 0: down; else: up */ return d; } -/*static unsigned int f_calc(unsigned int pfs, unsigned int bpp, unsigned int *write) -{[> return input_f <] +static unsigned int f_calc(unsigned int pfs, unsigned int bpp, unsigned int *write) +{/* return input_f */ unsigned int f_calculated = 0; switch (pfs) { case IPU_PIX_FMT_YVU422P: @@ -129,7 +129,7 @@ static unsigned int m_calc(unsigned int pfs) } return m_calculated; -}*/ +} /* Stripe parameters calculator */ @@ -214,14 +214,14 @@ int ipu_calc_stripes_sizes(const unsigned int input_frame_width, /* M, F calculations */ /* read back pfs from params */ - input_f = 16; + input_f = f_calc(input_pixelformat, 0, NULL); input_m = 16; /* BPP should be used in the out_F calc */ /* Temporarily not used */ /* out_F = F_calc(idmac->pfs, idmac->bpp, NULL); */ output_f = 16; - output_m = 16; + output_m = m_calc(output_pixelformat); if ((input_frame_width < 4) || (output_frame_width < 4)) @@ -370,7 +370,6 @@ int ipu_calc_stripes_sizes(const unsigned int input_frame_width, left->output_column = 0; right->output_column = onw; } - return status; } EXPORT_SYMBOL(ipu_calc_stripes_sizes); diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index 133c2a65c48c..e7713199abcb 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -688,9 +688,16 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel ipu->ic_use_count++; ipu->csi_channel[params->csi_prp_enc_mem.csi] = channel; - /*Without SMFC, CSI only support parallel data source*/ - ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET + - params->csi_prp_enc_mem.csi)); + if (params->csi_prp_enc_mem.mipi_en) { + ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET + + params->csi_prp_enc_mem.csi)); + _ipu_csi_set_mipi_di(ipu, + params->csi_prp_enc_mem.mipi_vc, + params->csi_prp_enc_mem.mipi_id, + params->csi_prp_enc_mem.csi); + } else + ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET + + params->csi_prp_enc_mem.csi)); /*CSI0/1 feed into IC*/ ipu_conf &= ~IPU_CONF_IC_INPUT; @@ -721,9 +728,16 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel ipu->ic_use_count++; ipu->csi_channel[params->csi_prp_vf_mem.csi] = channel; - /*Without SMFC, CSI only support parallel data source*/ - ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET + - params->csi_prp_vf_mem.csi)); + if (params->csi_prp_vf_mem.mipi_en) { + ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET + + params->csi_prp_vf_mem.csi)); + _ipu_csi_set_mipi_di(ipu, + params->csi_prp_vf_mem.mipi_vc, + params->csi_prp_vf_mem.mipi_id, + params->csi_prp_vf_mem.csi); + } else + ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET + + params->csi_prp_vf_mem.csi)); /*CSI0/1 feed into IC*/ ipu_conf &= ~IPU_CONF_IC_INPUT; @@ -2317,6 +2331,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi) return -EINVAL; } + _ipu_get(ipu); _ipu_lock(ipu); ipu->csi_use_count[csi]++; @@ -2328,6 +2343,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi) ipu_cm_write(ipu, reg | IPU_CONF_CSI1_EN, IPU_CONF); } _ipu_unlock(ipu); + _ipu_put(ipu); return 0; } EXPORT_SYMBOL(ipu_enable_csi); @@ -2349,7 +2365,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi) dev_err(ipu->dev, "Wrong csi num_%d\n", csi); return -EINVAL; } - + _ipu_get(ipu); _ipu_lock(ipu); ipu->csi_use_count[csi]--; if (ipu->csi_use_count[csi] == 0) { @@ -2360,6 +2376,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi) ipu_cm_write(ipu, reg & ~IPU_CONF_CSI1_EN, IPU_CONF); } _ipu_unlock(ipu); + _ipu_put(ipu); return 0; } EXPORT_SYMBOL(ipu_disable_csi); diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.c b/drivers/mxc/mipi/mxc_mipi_csi2.c index 89592a84745c..1f051dff88bd 100644 --- a/drivers/mxc/mipi/mxc_mipi_csi2.c +++ b/drivers/mxc/mipi/mxc_mipi_csi2.c @@ -17,6 +17,9 @@ */ #include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdesc.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/err.h> @@ -24,14 +27,10 @@ #include <linux/console.h> #include <linux/io.h> #include <linux/bitops.h> -#include <linux/ipu.h> -#include <linux/mxcfb.h> -#include <linux/regulator/consumer.h> -#include <linux/backlight.h> -#include <linux/spinlock.h> #include <linux/delay.h> #include <linux/fsl_devices.h> +#include <mach/devices-common.h> #include <mach/hardware.h> #include <mach/clock.h> #include <mach/mipi_csi2.h> @@ -40,6 +39,18 @@ static struct mipi_csi2_info *gmipi_csi2; +void _mipi_csi2_lock(struct mipi_csi2_info *info) +{ + if (!in_irq() && !in_softirq()) + mutex_lock(&info->mutex_lock); +} + +void _mipi_csi2_unlock(struct mipi_csi2_info *info) +{ + if (!in_irq() && !in_softirq()) + mutex_unlock(&info->mutex_lock); +} + static inline void mipi_csi2_write(struct mipi_csi2_info *info, unsigned value, unsigned offset) { writel(value, info->mipi_csi2_base + offset); @@ -51,6 +62,76 @@ static inline unsigned int mipi_csi2_read(struct mipi_csi2_info *info, unsigned } /*! + * This function is called to enable the mipi csi2 interface. + * + * @param info mipi csi2 hander + * @return Returns setted value + */ +bool mipi_csi2_enable(struct mipi_csi2_info *info) +{ + bool status; + + _mipi_csi2_lock(info); + + if (!info->mipi_en) { + info->mipi_en = true; + clk_enable(info->dphy_clk); + } else + mipi_dbg("mipi csi2 already enabled!\n"); + + status = info->mipi_en; + + _mipi_csi2_unlock(info); + + return status; +} +EXPORT_SYMBOL(mipi_csi2_enable); + +/*! + * This function is called to disable the mipi csi2 interface. + * + * @param info mipi csi2 hander + * @return Returns setted value + */ +bool mipi_csi2_disable(struct mipi_csi2_info *info) +{ + bool status; + + _mipi_csi2_lock(info); + + if (info->mipi_en) { + info->mipi_en = false; + clk_disable(info->dphy_clk); + } else + mipi_dbg("mipi csi2 already disabled!\n"); + + status = info->mipi_en; + + _mipi_csi2_unlock(info); + + return status; +} +EXPORT_SYMBOL(mipi_csi2_disable); + +/*! + * This function is called to get mipi csi2 disable/enable status. + * + * @param info mipi csi2 hander + * @return Returns mipi csi2 status + */ +bool mipi_csi2_get_status(struct mipi_csi2_info *info) +{ + bool status; + + _mipi_csi2_lock(info); + status = info->mipi_en; + _mipi_csi2_unlock(info); + + return status; +} +EXPORT_SYMBOL(mipi_csi2_get_status); + +/*! * This function is called to set mipi lanes. * * @param info mipi csi2 hander @@ -58,9 +139,14 @@ static inline unsigned int mipi_csi2_read(struct mipi_csi2_info *info, unsigned */ unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info) { + unsigned int lanes; + + _mipi_csi2_lock(info); mipi_csi2_write(info, info->lanes - 1, CSI2_N_LANES); + lanes = mipi_csi2_read(info, CSI2_N_LANES); + _mipi_csi2_unlock(info); - return mipi_csi2_read(info, CSI2_N_LANES); + return lanes; } EXPORT_SYMBOL(mipi_csi2_set_lanes); @@ -71,11 +157,16 @@ EXPORT_SYMBOL(mipi_csi2_set_lanes); * @return Returns setted value */ unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info, - unsigned int datatype) + unsigned int datatype) { + unsigned int dtype; + + _mipi_csi2_lock(info); info->datatype = datatype; + dtype = info->datatype; + _mipi_csi2_unlock(info); - return info->datatype; + return dtype; } EXPORT_SYMBOL(mipi_csi2_set_datatype); @@ -87,7 +178,13 @@ EXPORT_SYMBOL(mipi_csi2_set_datatype); */ unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info) { - return info->datatype; + unsigned int dtype; + + _mipi_csi2_lock(info); + dtype = info->datatype; + _mipi_csi2_unlock(info); + + return dtype; } EXPORT_SYMBOL(mipi_csi2_get_datatype); @@ -99,7 +196,13 @@ EXPORT_SYMBOL(mipi_csi2_get_datatype); */ unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info) { - return mipi_csi2_read(info, CSI2_PHY_STATE); + unsigned int status; + + _mipi_csi2_lock(info); + status = mipi_csi2_read(info, CSI2_PHY_STATE); + _mipi_csi2_unlock(info); + + return status; } EXPORT_SYMBOL(mipi_csi2_dphy_status); @@ -111,7 +214,13 @@ EXPORT_SYMBOL(mipi_csi2_dphy_status); */ unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info) { - return mipi_csi2_read(info, CSI2_ERR1); + unsigned int err1; + + _mipi_csi2_lock(info); + err1 = mipi_csi2_read(info, CSI2_ERR1); + _mipi_csi2_unlock(info); + + return err1; } EXPORT_SYMBOL(mipi_csi2_get_error1); @@ -123,7 +232,13 @@ EXPORT_SYMBOL(mipi_csi2_get_error1); */ unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info) { - return mipi_csi2_read(info, CSI2_ERR2); + unsigned int err2; + + _mipi_csi2_lock(info); + err2 = mipi_csi2_read(info, CSI2_ERR2); + _mipi_csi2_unlock(info); + + return err2; } EXPORT_SYMBOL(mipi_csi2_get_error2); @@ -159,6 +274,8 @@ EXPORT_SYMBOL(mipi_csi2_pixelclk_disable); */ int mipi_csi2_reset(struct mipi_csi2_info *info) { + _mipi_csi2_lock(info); + mipi_csi2_write(info, 0x0, CSI2_PHY_SHUTDOWNZ); mipi_csi2_write(info, 0x0, CSI2_DPHY_RSTZ); mipi_csi2_write(info, 0x0, CSI2_RESETN); @@ -177,6 +294,8 @@ int mipi_csi2_reset(struct mipi_csi2_info *info) mipi_csi2_write(info, 0xffffffff, CSI2_DPHY_RSTZ); mipi_csi2_write(info, 0xffffffff, CSI2_RESETN); + _mipi_csi2_unlock(info); + return 0; } EXPORT_SYMBOL(mipi_csi2_reset); @@ -199,7 +318,13 @@ EXPORT_SYMBOL(mipi_csi2_get_info); */ int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info) { - return info->ipu_id; + int ipu_id; + + _mipi_csi2_lock(info); + ipu_id = info->ipu_id; + _mipi_csi2_unlock(info); + + return ipu_id; } EXPORT_SYMBOL(mipi_csi2_get_bind_ipu); @@ -210,7 +335,13 @@ EXPORT_SYMBOL(mipi_csi2_get_bind_ipu); */ unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info) { - return info->csi_id; + unsigned int csi_id; + + _mipi_csi2_lock(info); + csi_id = info->csi_id; + _mipi_csi2_unlock(info); + + return csi_id; } EXPORT_SYMBOL(mipi_csi2_get_bind_csi); @@ -221,7 +352,13 @@ EXPORT_SYMBOL(mipi_csi2_get_bind_csi); */ unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info) { - return info->v_channel; + unsigned int v_channel; + + _mipi_csi2_lock(info); + v_channel = info->v_channel; + _mipi_csi2_unlock(info); + + return v_channel; } EXPORT_SYMBOL(mipi_csi2_get_virtual_channel); @@ -254,8 +391,12 @@ static int mipi_csi2_probe(struct platform_device *pdev) goto alloc_failed; } + /* initialize mutex */ + mutex_init(&gmipi_csi2->mutex_lock); + /* get mipi csi2 informaiton */ gmipi_csi2->pdev = pdev; + gmipi_csi2->mipi_en = false; gmipi_csi2->ipu_id = plat_data->ipu_id; gmipi_csi2->csi_id = plat_data->csi_id; gmipi_csi2->v_channel = plat_data->v_channel; @@ -295,6 +436,8 @@ static int mipi_csi2_probe(struct platform_device *pdev) /* get mipi csi2 dphy version */ mipi_csi2_dphy_ver = mipi_csi2_read(gmipi_csi2, CSI2_VERSION); + clk_disable(gmipi_csi2->dphy_clk); + platform_set_drvdata(pdev, gmipi_csi2); dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed\n"); @@ -320,7 +463,6 @@ static int __devexit mipi_csi2_remove(struct platform_device *pdev) iounmap(gmipi_csi2->mipi_csi2_base); /* disable mipi dphy clk */ - clk_disable(gmipi_csi2->dphy_clk); clk_put(gmipi_csi2->dphy_clk); clk_put(gmipi_csi2->pixel_clk); @@ -360,7 +502,7 @@ static void __exit mipi_csi2_cleanup(void) platform_driver_unregister(&mipi_csi2_driver); } -module_init(mipi_csi2_init); +subsys_initcall(mipi_csi2_init); module_exit(mipi_csi2_cleanup); MODULE_AUTHOR("Freescale Semiconductor, Inc."); diff --git a/drivers/mxc/mipi/mxc_mipi_csi2.h b/drivers/mxc/mipi/mxc_mipi_csi2.h index d7c4ba1e36da..9bccff7d6ce2 100644 --- a/drivers/mxc/mipi/mxc_mipi_csi2.h +++ b/drivers/mxc/mipi/mxc_mipi_csi2.h @@ -28,15 +28,18 @@ /* driver private data */ struct mipi_csi2_info { - int ipu_id; + bool mipi_en; + int ipu_id; unsigned int csi_id; unsigned int v_channel; unsigned int lanes; unsigned int datatype; - struct clk *dphy_clk; - struct clk *pixel_clk; - unsigned int *mipi_csi2_base; - struct platform_device *pdev; + struct clk *dphy_clk; + struct clk *pixel_clk; + unsigned int *mipi_csi2_base; + struct platform_device *pdev; + + struct mutex mutex_lock; }; #endif diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 2022af73e194..3ca487da1272 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -246,7 +246,7 @@ static void fec_stop(struct net_device *dev); #define FEC_MMFR_TA (2 << 16) #define FEC_MMFR_DATA(v) (v & 0xffff) -#define FEC_MII_TIMEOUT 1000 /* us */ +#define FEC_MII_TIMEOUT 2000 /* us */ /* Transmitter timeout */ #define TX_TIMEOUT (2 * HZ) @@ -898,9 +898,13 @@ static int fec_enet_mii_init(struct platform_device *pdev) */ fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000) << 1; - if (cpu_is_mx6q()) - /* FIXME: hard code to 0x1a for clock issue */ - fep->phy_speed = 0x11a; + if (cpu_is_mx6q()) { + /* FIXME: non-1588 MII clk: 66MHz, 1588 mode : 40MHz */ + if (fep->ptimer_present) + fep->phy_speed = 0xe; + else + fep->phy_speed = 0x11a; + } writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 70c1da61d2e8..094ce699f9eb 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -50,9 +50,11 @@ #include <asm/io.h> #include <asm/irq.h> +#include <mach/dma.h> #include <mach/hardware.h> #include <mach/imx-uart.h> + /* Register definitions */ #define URXD0 0x0 /* Receiver Register */ #define URTX0 0x40 /* Transmitter Register */ @@ -82,6 +84,7 @@ #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ #define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_ICD_REG(x) (((x) & 3) << 10) /* idle condition detect */ #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ #define UCR1_IREN (1<<7) /* Infrared interface enable */ @@ -90,6 +93,7 @@ #define UCR1_SNDBRK (1<<4) /* Send break */ #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ #define MX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, mx1 only */ +#define UCR1_ATDMAEN (1<<2) /* Aging DMA Timer Enable */ #define UCR1_DOZE (1<<1) /* Doze */ #define UCR1_UARTEN (1<<0) /* UART enabled */ #define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ @@ -102,6 +106,7 @@ #define UCR2_STPB (1<<6) /* Stop */ #define UCR2_WS (1<<5) /* Word size */ #define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_ATEN (1<<3) /* Aging Timer Enable */ #define UCR2_TXEN (1<<2) /* Transmitter enabled */ #define UCR2_RXEN (1<<1) /* Receiver enabled */ #define UCR2_SRST (1<<0) /* SW reset */ @@ -126,6 +131,7 @@ #define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ #define UCR4_WKEN (1<<7) /* Wake interrupt enable */ #define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IDDMAEN (1<<6) /* DMA IDLE Condition Detected */ #define UCR4_IRSC (1<<5) /* IR special case */ #define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ #define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ @@ -196,6 +202,17 @@ struct imx_port { unsigned int irda_inv_tx:1; unsigned short trcv_delay; /* transceiver delay */ struct clk *clk; + + /* DMA fields */ + int enable_dma; + struct imx_dma_data dma_data; + struct dma_chan *dma_chan_rx, *dma_chan_tx; + struct scatterlist rx_sgl, tx_sgl[2]; + void *rx_buf; + unsigned int rx_bytes, tx_bytes; + struct work_struct tsk_dma_rx, tsk_dma_tx; + unsigned int dma_tx_nents; + bool dma_is_rxing; }; #ifdef CONFIG_IRDA @@ -345,6 +362,79 @@ static inline void imx_transmit_buffer(struct imx_port *sport) imx_stop_tx(&sport->port); } +static void dma_tx_callback(void *data) +{ + struct imx_port *sport = data; + struct scatterlist *sgl = &sport->tx_sgl[0]; + struct circ_buf *xmit = &sport->port.state->xmit; + + dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + + /* update the stat */ + spin_lock(&sport->port.lock); + xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1); + sport->port.icount.tx += sport->tx_bytes; + spin_unlock(&sport->port.lock); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&sport->port); + schedule_work(&sport->tsk_dma_tx); +} + +static void dma_tx_work(struct work_struct *w) +{ + struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx); + struct circ_buf *xmit = &sport->port.state->xmit; + struct scatterlist *sgl = &sport->tx_sgl[0]; + struct dma_async_tx_descriptor *desc; + struct dma_chan *chan = sport->dma_chan_tx; + enum dma_status status; + unsigned long flags; + int ret; + + status = chan->device->device_tx_status(chan, (dma_cookie_t)NULL, NULL); + if (DMA_IN_PROGRESS == status) + return; + + spin_lock_irqsave(&sport->port.lock, flags); + sport->tx_bytes = uart_circ_chars_pending(xmit); + if (sport->tx_bytes > 0) { + if (xmit->tail > xmit->head) { + sport->dma_tx_nents = 2; + sg_init_table(sgl, 2); + sg_set_buf(sgl, xmit->buf + xmit->tail, + UART_XMIT_SIZE - xmit->tail); + sg_set_buf(&sgl[1], xmit->buf, xmit->head); + } else { + sport->dma_tx_nents = 1; + sg_init_one(sgl, xmit->buf + xmit->tail, + sport->tx_bytes); + } + spin_unlock_irqrestore(&sport->port.lock, flags); + + ret = dma_map_sg(sport->port.dev, sgl, + sport->dma_tx_nents, DMA_TO_DEVICE); + if (ret == 0) { + pr_err("DMA mapping error for TX.\n"); + return; + } + desc = chan->device->device_prep_slave_sg(chan, sgl, + sport->dma_tx_nents, DMA_TO_DEVICE, 0); + if (!desc) { + pr_err("We cannot prepare for the TX slave dma!\n"); + return; + } + desc->callback = dma_tx_callback; + desc->callback_param = sport; + + /* fire it */ + dmaengine_submit(desc); + return; + } + spin_unlock_irqrestore(&sport->port.lock, flags); + return; +} + /* * interrupts disabled on entry */ @@ -364,8 +454,10 @@ static void imx_start_tx(struct uart_port *port) writel(temp, sport->port.membase + UCR1); } - temp = readl(sport->port.membase + UCR1); - writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); + if (!sport->enable_dma) { + temp = readl(sport->port.membase + UCR1); + writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); + } if (USE_IRDA(sport)) { temp = readl(sport->port.membase + UCR1); @@ -377,6 +469,11 @@ static void imx_start_tx(struct uart_port *port) writel(temp, sport->port.membase + UCR4); } + if (sport->enable_dma) { + schedule_work(&sport->tsk_dma_tx); + return; + } + if (readl(sport->port.membase + UTS) & UTS_TXEMPTY) imx_transmit_buffer(sport); } @@ -489,6 +586,28 @@ out: return IRQ_HANDLED; } +/* + * We wait for the RXFIFO is filled with some data, and then + * arise a DMA operation to receive the data. + */ +static void imx_dma_rxint(struct imx_port *sport) +{ + unsigned long temp; + + temp = readl(sport->port.membase + USR2); + if ((temp & USR2_RDR) && !sport->dma_is_rxing) { + sport->dma_is_rxing = true; + + /* disable the `Recerver Ready Interrrupt` */ + temp = readl(sport->port.membase + UCR1); + temp &= ~(UCR1_RRDYEN); + writel(temp, sport->port.membase + UCR1); + + /* tell the DMA to receive the data. */ + schedule_work(&sport->tsk_dma_rx); + } +} + static irqreturn_t imx_int(int irq, void *dev_id) { struct imx_port *sport = dev_id; @@ -496,8 +615,12 @@ static irqreturn_t imx_int(int irq, void *dev_id) sts = readl(sport->port.membase + USR1); - if (sts & USR1_RRDY) - imx_rxint(irq, dev_id); + if (sts & USR1_RRDY) { + if (sport->enable_dma) + imx_dma_rxint(sport); + else + imx_rxint(irq, dev_id); + } if (sts & USR1_TRDY && readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) @@ -597,6 +720,180 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) return 0; } +static bool imx_uart_filter(struct dma_chan *chan, void *param) +{ + struct imx_port *sport = param; + + if (!imx_dma_is_general_purpose(chan)) + return false; + chan->private = &sport->dma_data; + return true; +} + +#define RX_BUF_SIZE (PAGE_SIZE) +static int start_rx_dma(struct imx_port *sport); + +static void dma_rx_work(struct work_struct *w) +{ + struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx); + struct tty_struct *tty = sport->port.state->port.tty; + + if (sport->rx_bytes) { + tty_insert_flip_string(tty, sport->rx_buf, sport->rx_bytes); + tty_flip_buffer_push(tty); + sport->rx_bytes = 0; + } + + if (sport->dma_is_rxing) + start_rx_dma(sport); +} + +/* + * There are two kinds RX DMA interrupts: + * [1] the RX DMA buffer is full. + * [2] the Aging timer reached its final value(enabled the UCR4_IDDMAEN). + */ +static void dma_rx_callback(void *data) +{ + struct imx_port *sport = data; + struct dma_chan *chan = sport->dma_chan_rx; + unsigned int count; + struct tty_struct *tty; + struct scatterlist *sgl; + struct dma_tx_state state; + enum dma_status status; + + tty = sport->port.state->port.tty; + sgl = &sport->rx_sgl; + + /* unmap it first */ + dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE); + + status = chan->device->device_tx_status(chan, + (dma_cookie_t)NULL, &state); + count = RX_BUF_SIZE - state.residue; + if (count) { + sport->rx_bytes = count; + schedule_work(&sport->tsk_dma_rx); + } else { + unsigned long temp; + + /* Enable the interrupt when the RXFIFO is not empty. */ + temp = readl(sport->port.membase + UCR1); + temp |= UCR1_RRDYEN; + writel(temp, sport->port.membase + UCR1); + sport->dma_is_rxing = false; + } +} + +static int start_rx_dma(struct imx_port *sport) +{ + struct scatterlist *sgl = &sport->rx_sgl; + struct dma_chan *chan = sport->dma_chan_rx; + struct dma_async_tx_descriptor *desc; + int ret; + + sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE); + ret = dma_map_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE); + if (ret == 0) { + pr_err("DMA mapping error for RX.\n"); + return -EINVAL; + } + desc = chan->device->device_prep_slave_sg(chan, + sgl, 1, DMA_FROM_DEVICE, 0); + if (!desc) { + pr_err("We cannot prepare for the RX slave dma!\n"); + return -EINVAL; + } + desc->callback = dma_rx_callback; + desc->callback_param = sport; + + dmaengine_submit(desc); + return 0; +} + +static void imx_uart_dma_exit(struct imx_port *sport) +{ + if (sport->dma_chan_rx) { + dma_release_channel(sport->dma_chan_rx); + sport->dma_chan_rx = NULL; + + kfree(sport->rx_buf); + sport->rx_buf = NULL; + } + + if (sport->dma_chan_tx) { + dma_release_channel(sport->dma_chan_tx); + sport->dma_chan_tx = NULL; + } +} + +/* see the "i.MX61 SDMA Scripts User Manual.doc" for the parameters */ +static int imx_uart_dma_init(struct imx_port *sport) +{ + struct imxuart_platform_data *pdata = sport->port.dev->platform_data; + struct dma_slave_config slave_config; + dma_cap_mask_t mask; + int ret; + + /* prepare for RX : */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + sport->dma_data.priority = DMA_PRIO_HIGH; + sport->dma_data.dma_request = pdata->dma_req_rx; + sport->dma_data.peripheral_type = IMX_DMATYPE_UART; + + sport->dma_chan_rx = dma_request_channel(mask, imx_uart_filter, sport); + if (!sport->dma_chan_rx) { + pr_err("cannot get the DMA channel.\n"); + ret = -EINVAL; + goto err; + } + + slave_config.direction = DMA_FROM_DEVICE; + slave_config.src_addr = sport->port.mapbase + URXD0; + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.src_maxburst = RXTL; /* fix me */ + ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config); + if (ret) { + pr_err("error in RX dma configuration.\n"); + goto err; + } + + sport->rx_buf = kzalloc(PAGE_SIZE, GFP_DMA); + if (!sport->rx_buf) { + pr_err("cannot alloc DMA buffer.\n"); + ret = -ENOMEM; + goto err; + } + sport->rx_bytes = 0; + + /* prepare for TX : */ + sport->dma_data.dma_request = pdata->dma_req_tx; + sport->dma_chan_tx = dma_request_channel(mask, imx_uart_filter, sport); + if (!sport->dma_chan_tx) { + pr_err("cannot get the TX DMA channel!\n"); + ret = -EINVAL; + goto err; + } + + slave_config.direction = DMA_TO_DEVICE; + slave_config.dst_addr = sport->port.mapbase + URTX0; + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.dst_maxburst = TXTL; /* fix me */ + ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config); + if (ret) { + pr_err("error in TX dma configuration."); + goto err; + } + + return 0; +err: + imx_uart_dma_exit(sport); + return ret; +} + /* half the RX buffer size */ #define CTSTL 16 @@ -607,7 +904,9 @@ static int imx_startup(struct uart_port *port) unsigned long flags, temp; struct tty_struct *tty; +#ifndef CONFIG_SERIAL_CORE_CONSOLE imx_setup_ufcr(sport, 0); +#endif /* disable the DREN bit (Data Ready interrupt enable) before * requesting IRQs @@ -669,6 +968,19 @@ static int imx_startup(struct uart_port *port) } } + /* Enable the SDMA for uart. */ + if (sport->enable_dma) { + int ret; + ret = imx_uart_dma_init(sport); + if (ret) + goto error_out3; + + sport->port.flags |= UPF_LOW_LATENCY; + INIT_WORK(&sport->tsk_dma_tx, dma_tx_work); + INIT_WORK(&sport->tsk_dma_rx, dma_rx_work); + } + + spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -676,6 +988,11 @@ static int imx_startup(struct uart_port *port) temp = readl(sport->port.membase + UCR1); temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; + if (sport->enable_dma) { + temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN; + /* ICD, wait for more than 32 frames, but it still to short. */ + temp |= UCR1_ICD_REG(3); + } if (USE_IRDA(sport)) { temp |= UCR1_IREN; @@ -719,10 +1036,15 @@ static int imx_startup(struct uart_port *port) writel(temp, sport->port.membase + UCR3); } + if (sport->enable_dma) { + temp = readl(sport->port.membase + UCR4); + temp |= UCR4_IDDMAEN; + writel(temp, sport->port.membase + UCR4); + } + /* * Enable modem status interrupts */ - spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -756,10 +1078,13 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -788,12 +1113,17 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); + spin_unlock_irqrestore(&sport->port.lock, flags); + + if (sport->enable_dma) + imx_uart_dma_exit(sport); } static void @@ -952,6 +1282,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); + } static const char *imx_type(struct uart_port *port) @@ -1072,7 +1403,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) { struct imx_port *sport = imx_ports[co->index]; unsigned int old_ucr1, old_ucr2, ucr1; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2 and then disable interrupts */ @@ -1098,6 +1431,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count) writel(old_ucr1, sport->port.membase + UCR1); writel(old_ucr2, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); } /* @@ -1319,6 +1653,9 @@ static int serial_imx_probe(struct platform_device *pdev) sport->have_rtscts = 1; if (pdata && (pdata->flags & IMXUART_USE_DCEDTE)) sport->use_dcedte = 1; + if (pdata && (pdata->flags & IMXUART_SDMA)) + sport->enable_dma = 1; + #ifdef CONFIG_IRDA if (pdata && (pdata->flags & IMXUART_IRDA)) sport->use_irda = 1; diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index cd649a416a96..e84ede66ad9c 100644 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -865,8 +865,13 @@ static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) ? (1 << (ep_index(ep) + 16)) : (1 << (ep_index(ep))); - /* check if the pipe is empty */ - if (!(list_empty(&ep->queue))) { + /* + * check if + * - the request is empty, and + * - the request is not the status request for ep0 + */ + if (!(list_empty(&ep->queue)) && + !((ep_index(ep) == 0) && (req->req.length == 0))) { /* Add td to the end */ struct fsl_req *lastreq; lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); @@ -1128,10 +1133,6 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) spin_lock_irqsave(&ep->udc->lock, flags); stopped = ep->stopped; udc = ep->udc; - if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) { - spin_unlock_irqrestore(&ep->udc->lock, flags); - return -ESHUTDOWN; - } /* Stop the ep before we deal with the queue */ ep->stopped = 1; @@ -2053,8 +2054,10 @@ static int reset_queues(struct fsl_udc *udc) for (pipe = 0; pipe < udc->max_pipes; pipe++) udc_reset_ep_queue(udc, pipe); + spin_unlock(&udc->lock); /* report disconnect; the driver is already quiesced */ udc->driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); return 0; } @@ -2097,22 +2100,79 @@ static void reset_irq(struct fsl_udc *udc) udc->usb_state = USB_STATE_DEFAULT; } -static void fsl_gadget_event(struct work_struct *work) +#define FSL_DP_CHANGE_TIMEOUT (msecs_to_jiffies(1000)) /* 1000 ms */ +static void gadget_wait_line_to_se0(void) +{ + unsigned long timeout; + timeout = jiffies + FSL_DP_CHANGE_TIMEOUT; + /* Wait for DP to SE0 */ + while (!((fsl_readl(&dr_regs->portsc1) & + (u32)((1 << 10) | (1 << 11))) == PORTSCX_LINE_STATUS_SE0)) { + if (time_after(jiffies, timeout)) { + pr_warning(KERN_ERR "wait dp to SE0 timeout, please check" + " your hardware design!\n"); + break; + } + msleep(10); + } +} + +#define FSL_WAIT_CLASS_DRIVER_TIMEOUT (msecs_to_jiffies(3000)) /* 3s */ +static void gadget_wait_class_driver_finish(void) +{ + unsigned long timeout; + struct fsl_udc *udc = udc_controller; + struct fsl_ep *ep; + int i = 2; + timeout = jiffies + FSL_WAIT_CLASS_DRIVER_TIMEOUT; + /* for non-control endpoints */ + while (i < (int)(udc_controller->max_ep)) { + ep = &udc->eps[i++]; + if (ep->stopped == 0) { + if (time_after(timeout, jiffies)) { + i = 2; + msleep(10); + continue; + } else { + pr_warning(KERN_WARNING "We have waited 3s, but the class driver" + " has still not finishes!\n"); + break; + } + } + } +} + +static void fsl_gadget_disconnect_event(struct work_struct *work) { struct fsl_udc *udc = udc_controller; unsigned long flags; + struct fsl_usb2_platform_data *pdata; u32 tmp; - if (udc->driver) - udc->driver->disconnect(&udc->gadget); + pdata = udc->pdata; + + /* enable pulldown dp */ + if (pdata->gadget_discharge_dp) + pdata->gadget_discharge_dp(true); + /* + * Some boards are very slow change line state from J to SE0 for DP, + * So, we need to discharge DP, otherwise there is a wakeup interrupt + * after we enable the wakeup function. + */ + gadget_wait_line_to_se0(); + + /* Disable pulldown dp */ + if (pdata->gadget_discharge_dp) + pdata->gadget_discharge_dp(false); + + /* + * Wait class drivers finish, an well-behaviour class driver should + * call ep_disable when it is notified to be disconnected. + */ + gadget_wait_class_driver_finish(); + spin_lock_irqsave(&udc->lock, flags); - /* update port status */ - fsl_udc_speed_update(udc); - spin_unlock_irqrestore(&udc->lock, flags); - udc->stopped = 1; - /* enable wake up */ - dr_wake_up_enable(udc, true); /* here we need to enable the B_SESSION_IRQ * to enable the following device attach */ @@ -2120,6 +2180,10 @@ static void fsl_gadget_event(struct work_struct *work) if (!(tmp & (OTGSC_B_SESSION_VALID_IRQ_EN))) fsl_writel(tmp | (OTGSC_B_SESSION_VALID_IRQ_EN), &dr_regs->otgsc); + udc->stopped = 1; + /* enable wake up */ + dr_wake_up_enable(udc, true); + spin_unlock_irqrestore(&udc->lock, flags); /* close USB PHY clock */ dr_phy_low_power_mode(udc, true); /* close dr controller clock */ @@ -2169,11 +2233,14 @@ bool try_wake_up_udc(struct fsl_udc *udc) fsl_writel(tmp & (~OTGSC_B_SESSION_VALID_IRQ_EN), &dr_regs->otgsc); - /*here we need delay 30 ms for avoid exception usb vbus falling interrupt - Once we clear the RS bit, D+ D- need about 20 ms to SE0 modet ,during this period - we can not enable device wake up - */ - schedule_delayed_work(&udc->gadget_delay_work, msecs_to_jiffies(30)); + + /* update port status */ + fsl_udc_speed_update(udc); + spin_unlock(&udc->lock); + if (udc->driver) + udc->driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); + schedule_work(&udc->gadget_disconnect_schedule); return false; } } @@ -2782,7 +2849,15 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index, ep->ep.name = ep->name; ep->ep.ops = &fsl_ep_ops; - ep->stopped = 0; + /* + * For ep0, the endpoint is enabled after controller initialization + * For non-ep0, the endpoint is stopped default, and will be enabled + * by class driver when needed. + */ + if (index) + ep->stopped = 1; + else + ep->stopped = 0; /* for ep0: maxP defined in desc * for other eps, maxP is set by epautoconfig() called by gadget layer @@ -2959,7 +3034,7 @@ static int __devinit fsl_udc_probe(struct platform_device *pdev) } } - INIT_DELAYED_WORK(&udc_controller->gadget_delay_work, fsl_gadget_event); + INIT_WORK(&udc_controller->gadget_disconnect_schedule, fsl_gadget_disconnect_event); #ifdef POSTPONE_FREE_LAST_DTD last_free_td = NULL; #endif diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h index eb92e470a7f3..00c8e8a8cdd7 100644 --- a/drivers/usb/gadget/arcotg_udc.h +++ b/drivers/usb/gadget/arcotg_udc.h @@ -232,8 +232,8 @@ struct usb_sys_interface { /* bit 11-10 are line status */ #define PORTSCX_LINE_STATUS_SE0 (0x00000000) -#define PORTSCX_LINE_STATUS_JSTATE (0x00000400) -#define PORTSCX_LINE_STATUS_KSTATE (0x00000800) +#define PORTSCX_LINE_STATUS_KSTATE (0x00000400) +#define PORTSCX_LINE_STATUS_JSTATE (0x00000800) #define PORTSCX_LINE_STATUS_UNDEF (0x00000C00) #define PORTSCX_LINE_STATUS_BIT_POS (10) @@ -624,7 +624,7 @@ struct fsl_udc { struct completion *done; /* to make sure release() is done */ u32 iram_buffer[IRAM_PPH_NTD]; void *iram_buffer_v[IRAM_PPH_NTD]; - struct delayed_work gadget_delay_work; + struct work_struct gadget_disconnect_schedule; }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index c23b2185ff8f..d843277d68ec 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3163,7 +3163,6 @@ static int fsg_main_thread(void *fsg_) complete_and_exit(&fsg->thread_notifier, 0); } - /*-------------------------------------------------------------------------*/ @@ -3202,6 +3201,15 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) DBG(fsg, "unbind\n"); clear_bit(REGISTERED, &fsg->atomic_bitflags); + /* If the thread isn't already dead, tell it to exit now */ + if (fsg->state != FSG_STATE_TERMINATED) { + raise_exception(fsg, FSG_STATE_EXIT); + wait_for_completion(&fsg->thread_notifier); + + /* The cleanup routine waits for this completion also */ + complete(&fsg->thread_notifier); + } + /* Unregister the sysfs attribute files and the LUNs */ for (i = 0; i < fsg->nluns; ++i) { curlun = &fsg->luns[i]; @@ -3215,15 +3223,6 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) } } - /* If the thread isn't already dead, tell it to exit now */ - if (fsg->state != FSG_STATE_TERMINATED) { - raise_exception(fsg, FSG_STATE_EXIT); - wait_for_completion(&fsg->thread_notifier); - - /* The cleanup routine waits for this completion also */ - complete(&fsg->thread_notifier); - } - /* Free the data buffers */ for (i = 0; i < FSG_NUM_BUFFERS; ++i) kfree(fsg->buffhds[i].buf); diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index a30815cba3f1..be8e0160a197 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -168,11 +168,11 @@ static void fsl_otg_wait_stable_vbus(bool on) fsl_otg_clk_gate(true); /* Wait for vbus change to B_SESSION_VALID complete */ timeout = jiffies + FSL_VBUS_CHANGE_TIMEOUT; - while ((le32_to_cpu(usb_dr_regs->otgsc)&OTGSC_INTSTS_B_SESSION_VALID) == !on) { + while ((le32_to_cpu(usb_dr_regs->otgsc)&OTGSC_STS_B_SESSION_VALID) != (on << 11)) { if (time_after(jiffies, timeout)) { printk(KERN_ERR"wait otg vbus change timeout! \n"); fsl_otg_clk_gate(false); - break; + return; } msleep(10); } @@ -619,8 +619,11 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) * so suspend the host after a short delay. */ otg_dev->host_working = 1; - if (otg_dev->fsm.id) + + if (otg_dev->fsm.id) { + otg_dev->host_first_call = true; schedule_otg_work(&otg_dev->otg_event, 100); + } else { /* if the device is already at the port */ otg_drv_vbus(&otg_dev->fsm, 1); @@ -733,8 +736,12 @@ static void fsl_otg_event(struct work_struct *work) if (fsm->id) { /* switch to gadget */ fsl_otg_start_host(fsm, 0); otg_drv_vbus(fsm, 0); - fsl_otg_wait_stable_vbus(false); - fsl_otg_wait_dischrg_vbus(); + if (og->host_first_call == false) { + fsl_otg_wait_dischrg_vbus(); + fsl_otg_wait_stable_vbus(false); + } else { + og->host_first_call = false; + } b_session_irq_enable(false); fsl_otg_start_gadget(fsm, 1); } else { /* switch to host */ @@ -943,6 +950,7 @@ static int fsl_otg_conf(struct platform_device *pdev) fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; fsl_otg_tc->otg.dev = &pdev->dev; + fsl_otg_tc->host_first_call = false; fsl_otg_dev = fsl_otg_tc; diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h index a8536815d0bf..d3d382bd8e32 100644 --- a/drivers/usb/otg/fsl_otg.h +++ b/drivers/usb/otg/fsl_otg.h @@ -385,6 +385,8 @@ struct fsl_otg { /*used for usb host */ struct work_struct work_wq; u8 host_working; + /*Used for host init call,we need to avoid discharge Vbus when usb cable connect to PC*/ + bool host_first_call; int irq; }; diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 79bf1f40bca5..7642172ba844 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -66,7 +66,10 @@ static int pwm_backlight_check_fb(struct backlight_device *bl, struct fb_info *info) { char *id = info->fix.id; - if (!strcmp(id, "DISP3 BG")) + if (!strcmp(id, "DISP3 BG") || + !strcmp(id, "DISP3 BG - DI1") || + !strcmp(id, "DISP4 BG") || + !strcmp(id, "DISP4 BG - DI1")) return 1; else return 0; diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c index e68efb88abbb..0b5c2f06722b 100644 --- a/drivers/video/mxc/mxc_ipuv3_fb.c +++ b/drivers/video/mxc/mxc_ipuv3_fb.c @@ -85,7 +85,7 @@ struct mxcfb_info { u32 pseudo_palette[16]; bool mode_found; - bool wait4vsync; + volatile bool wait4vsync; struct semaphore flip_sem; struct semaphore alpha_flip_sem; struct completion vsync_complete; @@ -233,8 +233,7 @@ static int _setup_disp_channel2(struct fb_info *fbi) } fbi->var.xoffset = 0; - base = (fbi->var.yoffset * fbi->var.xres_virtual + fbi->var.xoffset); - base = (fbi->var.bits_per_pixel) * base / 8; + base = (fbi->var.yoffset * fb_stride + fbi->var.xoffset); base += fbi->fix.smem_start; retval = ipu_init_channel_buffer(mxc_fbi->ipu, @@ -242,10 +241,11 @@ static int _setup_disp_channel2(struct fb_info *fbi) bpp_to_pixfmt(fbi), fbi->var.xres, fbi->var.yres, fb_stride, - IPU_ROTATE_NONE, - base, + fbi->var.rotate, base, base, + fbi->var.accel_flags & + FB_ACCEL_DOUBLE_FLAG ? 0 : base, 0, 0); if (retval) { dev_err(fbi->device, @@ -259,7 +259,7 @@ static int _setup_disp_channel2(struct fb_info *fbi) IPU_PIX_FMT_GENERIC, fbi->var.xres, fbi->var.yres, fbi->var.xres, - IPU_ROTATE_NONE, + fbi->var.rotate, mxc_fbi->alpha_phy_addr1, mxc_fbi->alpha_phy_addr0, 0, @@ -574,6 +574,9 @@ static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->yres = bg_yres - pos_y; } + if (var->rotate > IPU_ROTATE_VERT_FLIP) + var->rotate = IPU_ROTATE_NONE; + if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; @@ -928,7 +931,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) init_completion(&mxc_fbi->vsync_complete); ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq); - mxc_fbi->wait4vsync = 1; + mxc_fbi->wait4vsync = true; ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq); retval = wait_for_completion_interruptible_timeout( &mxc_fbi->vsync_complete, 1 * HZ); @@ -936,7 +939,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) dev_err(fbi->device, "MXCFB_WAIT_FOR_VSYNC: timeout %d\n", retval); - mxc_fbi->wait4vsync = 0; + mxc_fbi->wait4vsync = false; retval = -ETIME; } else if (retval > 0) { retval = 0; @@ -1155,6 +1158,7 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) u_int y_bottom; unsigned long base, active_alpha_phy_addr = 0; bool loc_alpha_en = false; + int fb_stride; int i; if (info->var.yoffset == var->yoffset) @@ -1184,8 +1188,20 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) if (y_bottom > info->var.yres_virtual) return -EINVAL; - base = (var->yoffset * var->xres_virtual + var->xoffset); - base = (var->bits_per_pixel) * base / 8; + switch (bpp_to_pixfmt(info)) { + case IPU_PIX_FMT_YUV420P2: + case IPU_PIX_FMT_YVU420P: + case IPU_PIX_FMT_NV12: + case IPU_PIX_FMT_YUV422P: + case IPU_PIX_FMT_YVU422P: + case IPU_PIX_FMT_YUV420P: + fb_stride = info->var.xres_virtual; + break; + default: + fb_stride = info->fix.line_length; + } + + base = (var->yoffset * fb_stride + var->xoffset); base += info->fix.smem_start; /* Check if DP local alpha is enabled and find the graphic fb */ @@ -1361,7 +1377,7 @@ static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id) if (mxc_fbi->wait4vsync) { complete(&mxc_fbi->vsync_complete); ipu_disable_irq(mxc_fbi->ipu, irq); - mxc_fbi->wait4vsync = 0; + mxc_fbi->wait4vsync = false; } else { up(&mxc_fbi->flip_sem); ipu_disable_irq(mxc_fbi->ipu, irq); diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c index 95083f2ebd3a..09930158fb0e 100644 --- a/drivers/video/mxc_hdmi.c +++ b/drivers/video/mxc_hdmi.c @@ -138,6 +138,8 @@ struct mxc_hdmi { struct i2c_client *hdmi_i2c; +extern const struct fb_videomode mxc_cea_mode[64]; + /*! * this submodule is responsible for the video data synchronization. * for example, for RGB 4:4:4 input, the data map is defined as @@ -1226,6 +1228,9 @@ static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi, ret = mxc_edid_read(hdmi_i2c->adapter, hdmi_i2c->addr, hdmi->edid, &hdmi->edid_cfg, fbi); + if (ret < 0) + return ret; + if (!memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN)) ret = -2; return ret; @@ -1298,9 +1303,27 @@ static void mxc_hdmi_disable(struct mxc_hdmi *hdmi) clk_disable(hdmi->hdmi_iahb_clk); } +static void mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi) +{ + u32 i; + const struct fb_videomode *mode; + + fb_destroy_modelist(&hdmi->fbi->modelist); + + for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) { + mode = &mxc_cea_mode[i]; + if ((mode->xres == hdmi->fbi->var.xres) && + (mode->yres == hdmi->fbi->var.yres) && + !(mode->vmode & FB_VMODE_INTERLACED)) + fb_add_videomode(mode, &hdmi->fbi->modelist); + } +} + static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) { int ret; + struct fb_videomode m; + const struct fb_videomode *mode; dev_dbg(&hdmi->pdev->dev, "cable connected\n"); @@ -1308,14 +1331,10 @@ static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) /* edid read */ ret = mxc_hdmi_read_edid(hdmi, hdmi->fbi); - if (ret == -1) - dev_err(&hdmi->pdev->dev, "read edid fail\n"); - else if (ret == -2) + if (ret == -2) dev_info(&hdmi->pdev->dev, "same edid\n"); else if (hdmi->fbi->monspecs.modedb_len > 0) { int i; - const struct fb_videomode *mode; - struct fb_videomode m; fb_destroy_modelist(&hdmi->fbi->modelist); @@ -1340,11 +1359,24 @@ static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) fb_var_to_videomode(&m, &hdmi->fbi->var); mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist); + if (mode) + fb_videomode_to_var(&hdmi->fbi->var, mode); - fb_videomode_to_var(&hdmi->fbi->var, mode); - hdmi->need_mode_change = true; - } else + hdmi->need_mode_change = mode ? true : false; + } else { + /* If not EDID data readed, setup default modelist */ dev_info(&hdmi->pdev->dev, "No modes read from edid\n"); + mxc_hdmi_default_modelist(hdmi); + + fb_var_to_videomode(&m, &hdmi->fbi->var); + mode = fb_find_nearest_mode(&m, + &hdmi->fbi->modelist); + if (mode) + fb_videomode_to_var(&hdmi->fbi->var, mode); + + hdmi->need_mode_change = mode ? true : false; + } + return 0; } @@ -1593,6 +1625,9 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp) int irq = platform_get_irq(hdmi->pdev, 0); bool found = false; u8 val; + const struct fb_videomode *mode; + struct fb_videomode m; + struct fb_var_screeninfo var; if (!plat || irq < 0) return -ENODEV; @@ -1658,13 +1693,19 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp) /* try to read edid */ ret = mxc_hdmi_read_edid(hdmi, hdmi->fbi); - if (ret < 0) - dev_warn(&hdmi->pdev->dev, "Can not read edid\n"); - else if (hdmi->fbi->monspecs.modedb_len > 0) { + if (ret < 0) { + /* If not EDID data readed, setup default modelist */ + dev_info(&hdmi->pdev->dev, "No modes read from edid\n"); + mxc_hdmi_default_modelist(hdmi); + + fb_var_to_videomode(&m, &hdmi->fbi->var); + mode = fb_find_nearest_mode(&m, + &hdmi->fbi->modelist); + + fb_videomode_to_var(&hdmi->fbi->var, mode); + hdmi->need_mode_change = true; + } else if (hdmi->fbi->monspecs.modedb_len > 0) { int i; - const struct fb_videomode *mode; - struct fb_videomode m; - struct fb_var_screeninfo var; for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) { /* diff --git a/firmware/imx/sdma/sdma-imx6q-to1.bin.ihex b/firmware/imx/sdma/sdma-imx6q-to1.bin.ihex index d180a30e6916..04ae9928afde 100644 --- a/firmware/imx/sdma/sdma-imx6q-to1.bin.ihex +++ b/firmware/imx/sdma/sdma-imx6q-to1.bin.ihex @@ -1,106 +1,99 @@ -:1000000053444D4101000000000000001C000000AE -:1000100023000000A8000000DC05000082020000B0 +:1000000053444D4101000000010000001C000000AD +:1000100023000000A80000006A0500008202000022 :10002000FFFFFFFF00000000FFFFFFFFFFFFFFFFDC :10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 -:10004000FFFFFFFFFFFFFFFF31030000FFFFFFFF88 -:10005000EB0200003F190000FFFFFFFF0804000053 -:10006000FFFFFFFFC0030000FFFFFFFFFFFFFFFFD9 -:10007000FFFFFFFFAB020000FFFFFFFF7B0300005D +:10004000FFFFFFFFB61800006A1A00004B04000013 +:10005000EB0200004A190000FF180000080400002D +:1000600095040000C0030000C105000070050000F9 +:1000700009040000AB020000E30400007B03000061 :10008000FFFFFFFFFFFFFFFF4C0400006E040000B6 -:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 -:1000A0000000000000180000700D11051555CD5A14 -:1000B000FD5F010B6606017C17036706027C1703D0 -:1000C00017036806047C1703170317031703C55BA0 -:1000D0008D073CC1637D4EC1617C081DD75ADF5B33 -:1000E000E75CEF5DF75E8803700E1106FF0A1102F0 -:1000F000FF1ABC02800CD402017C8A04A4022E5593 -:10010000B905004D057CFE55BB05004D017C2B98C3 -:10011000FF55E7507800017C081D216DF755056DEE -:10012000081DF75D7DD81F7F080818681C7C286DA6 -:100130001A7F0824027C004A1B7DFF55E750780097 -:10014000017D081D056DEF55016D081DEF5D080867 -:100150001868097C286D077F004CD17C0000269828 -:10016000DF5BE75C880307000C68E7545404E75C36 -:100170008B00D752DF53E75459C1107C4EC10E7C1F -:10018000DF5BFF527803017D081A016D056A0808DC -:100190001868E67C286AE47FD75219987DD8000059 -:1001A0001598CF55D26DC755C86DDE6D010206009A -:1001B000E3C1DB57E35FE357F352016A8F00D500D9 -:1001C000017D8D00A005EB5D7804037D79042C7D15 -:1001D000367C79041F7CEE56000F6006057D0965AC -:1001E000437E0A62417EA4980A623E7E09653C7E97 -:1001F00012051205AD026007037DFB55D36DAF9864 -:10020000FB55041DD36DC86A2F7F011F03200048D2 -:10021000E47CD798FB55D76D150005780962C86A4C -:100220000962C86AD76DD698FB55D76D15001500C1 -:1002300005780A62C86A0A62C86AD76DD698FB5503 -:10024000D76D15001500150005780B62C86A0B62A2 -:10025000C86AD76D097CDF6D077F0000EB55004D44 -:10026000077DFAC1E3578A980700CC680C6813C26F -:100270000AC28798D9C1E3C1DB57E35FE357F35262 -:10028000216A8F00D500017D8D00A005EB5DFB5636 -:100290007804037D79042A7D317C7904207C700BFD -:1002A0001103EB53000F6003057D0965377E0A6279 -:1002B000357E0A990A62327E0965307E1205120582 -:1002C000AD026007027C065A1299265A277F011F49 -:1002D00003200048E87C700B110313533399150079 -:1002E00004780962065A0962265A329915001500E7 -:1002F00004780A62065A0A62265A329915001500D5 -:10030000150004780B62065A0B62265A077C00001F -:10031000EB55004D067DFAC1E357ED9807000C68D8 -:1003200013C20AC2EA98700B110313536C07017CC5 -:10033000D9C1FB5E8A066B07017CD9C1F35EDB592C -:10034000D3588F0110010F398B003CC12B7DC05A4F -:10035000C85B4EC1277C88038906E35CFF0D11054D -:10036000FF1DBC053E07004D187D700811007E077B -:10037000097D7D07027D28526A99F852DB54BC0240 -:10038000CC02097C7C07027D28527399F852D35421 -:10039000BC02CC02097D000461998B00C052C85395 -:1003A00059C1D67D00025199FF08BF007F07157D16 -:1003B0008804D500017D8D00A005EB5D8F0212023F -:1003C0001202FF3ADA05027C3E079C99A402DD0284 -:1003D000027D3E079C995E079C99EB559805EB5D65 -:1003E000F352FB546A07267D6C07017DD9996B0790 -:1003F000577C6907047D6807027D010EB399935805 -:10040000D600017D8E009355A005935DA00602786D -:100410000255045D1D7C004E087C6907037D025572 -:10042000177EC099045D147F890693500048017DB2 -:10043000AB99249A150006780255045D4F070255C2 -:10044000245D2F07017C249A17006F07017C01208F -:1004500093559D0007002BDA7999D36C6907047DC9 -:100460006807027D010EE8999358D600017D8E0041 -:100470009355A005935DA00602780255C86D0F7CC8 -:10048000004E087C6907037D0255097EF599C86D09 -:10049000067F890693500048017DE099249A1E9AB0 -:1004A000C36A6907047D6807027D010E0B9A9358A1 -:1004B000D600017D8E009355A005935DA0060278BD -:1004C000C865045D0F7C004E087C6907037DC86524 -:1004D000097E189A045D067F890693500048017DC5 -:1004E000039A249A93559D000700FF6C2BDA7999A3 -:1004F0000000E354EB55004D017C79996199E35478 -:10050000EB55FF0A1102FF1A7F07027CA005389AFB -:100510009D008C05BA05A0051002BA04AD04540470 -:100520000600E3C1DB57FB52C36AF352056A8F0032 -:10053000D500017D8D00A005EB5D7804037D790475 -:100540002B7D1E7C7904337CEE56000FFB55600733 -:10055000027DC36D599A041DC36DC8623B7E60065F -:10056000027D10021202096A357F1202096A327F87 -:100570001202096A2F7F011F03200048E77C8D9A31 -:10058000FB55C76D1500150015000578C8620B6A8C -:10059000C8620B6AC76D8C9AFB55C76D15001500B4 -:1005A0000578C8620A6AC8620A6AC76D8C9AFB55E8 -:1005B000C76D15000578C862096AC862096AC76D07 -:1005C000097C286A077F0000EB55004D057DFAC1C4 -:1005D000DB57439A77C254040AC23E9AD9C1E3C199 -:1005E000DB57F352056A8F00D500017D8D00A00511 -:1005F000FB567804037D7904297D1F7C79042E7CC9 -:10060000E35D700D1105ED55000F6007027D065288 -:10061000B69A2652337E6005027D10021202096AE4 -:100620002D7F1202096A2A7F1202096A277F011FA1 -:1006300003200048EA7CE355E19A150015001500F7 -:10064000047806520B6A26520B6AE09A15001500D0 -:10065000047806520A6A26520A6AE09A150004785B -:100660000652096A2652096A097C286A077F000037 -:10067000DB57004D057DFAC1DB579F9A77C25404C2 -:040680000AC29C9A74 +:10009000FFFFFFFF00180000FFFFFFFFFFFFFFFF54 +:1000A0000000000000180000E3C1DB57E35FE357E6 +:1000B000F352016A8F00D500017D8D00A005EB5D34 +:1000C0007804037D79042C7D367C79041F7CEE5600 +:1000D000000F6006057D0965437E0A62417E209817 +:1000E0000A623E7E09653C7E12051205AD0260077C +:1000F000037DFB55D36D2B98FB55041DD36DC86A4A +:100100002F7F011F03200048E47C5398FB55D76DD7 +:10011000150005780962C86A0962C86AD76D5298E5 +:10012000FB55D76D1500150005780A62C86A0A628A +:10013000C86AD76D5298FB55D76D1500150015008C +:1001400005780B62C86A0B62C86AD76D097CDF6DDF +:10015000077F0000EB55004D077DFAC1E357069875 +:100160000700CC680C6813C20AC20398D9C1E3C166 +:10017000DB57E35FE357F352216A8F00D500017D1F +:100180008D00A005EB5DFB567804037D79042A7D84 +:10019000317C7904207C700B1103EB53000F60035A +:1001A000057D0965377E0A62357E86980A62327E51 +:1001B0000965307E12051205AD026007027C065A01 +:1001C0008E98265A277F011F03200048E87C700B79 +:1001D00011031353AF98150004780962065A096297 +:1001E000265AAE981500150004780A62065A0A626B +:1001F000265AAE9815001500150004780B62065AB1 +:100200000B62265A077C0000EB55004D067DFAC1B3 +:10021000E357699807000C6813C20AC26698700B0E +:10022000110313536C07017CD9C1FB5E8A066B076F +:10023000017CD9C1F35EDB59D3588F0110010F390E +:100240008B003CC12B7DC05AC85B4EC1277C880304 +:100250008906E35CFF0D1105FF1DBC053E07004D3F +:10026000187D700811007E07097D7D07027D2852E8 +:10027000E698F852DB54BC02CC02097C7C07027D74 +:100280002852EF98F852D354BC02CC02097D0004E6 +:10029000DD988B00C052C85359C1D67D0002CD985D +:1002A000FF08BF007F07157D8804D500017D8D0004 +:1002B000A005EB5D8F0212021202FF3ADA05027C02 +:1002C0003E071899A402DD02027D3E0718995E07D9 +:1002D0001899EB559805EB5DF352FB546A07267DA0 +:1002E0006C07017D55996B07577C6907047D68078A +:1002F000027D010E2F999358D600017D8E009355F3 +:10030000A005935DA00602780255045D1D7C004E99 +:10031000087C6907037D0255177E3C99045D147FB4 +:10032000890693500048017D2799A0991500067809 +:100330000255045D4F070255245D2F07017CA099EB +:1003400017006F07017C012093559D000700A7D976 +:10035000F598D36C6907047D6807027D010E6499E6 +:100360009358D600017D8E009355A005935DA0069D +:1003700002780255C86D0F7C004E087C6907037D2A +:100380000255097E7199C86D067F89069350004811 +:10039000017D5C99A0999A99C36A6907047D6807F1 +:1003A000027D010E87999358D600017D8E009355EA +:1003B000A005935DA0060278C865045D0F7C004E21 +:1003C000087C6907037DC865097E9499045D067FF2 +:1003D000890693500048017D7F99A09993559D000F +:1003E0000700FF6CA7D9F5980000E354EB55004DCA +:1003F000017CF598DD98E354EB55FF0A1102FF1AD2 +:100400007F07027CA005B4999D008C05BA05A00564 +:100410001002BA04AD0454040600E3C1DB57FB52DA +:10042000C36AF352056A8F00D500017D8D00A005D7 +:10043000EB5D7804037D79042B7D1E7C7904337C8D +:10044000EE56000FFB556007027DC36DD599041D64 +:10045000C36DC8623B7E6006027D10021202096A0B +:10046000357F1202096A327F1202096A2F7F011F4B +:1004700003200048E77C099AFB55C76D150015005D +:1004800015000578C8620B6AC8620B6AC76D089AC6 +:10049000FB55C76D150015000578C8620A6AC86269 +:1004A0000A6AC76D089AFB55C76D15000578C862C2 +:1004B000096AC862096AC76D097C286A077F00005B +:1004C000EB55004D057DFAC1DB57BF9977C2540447 +:1004D0000AC2BA99D9C1E3C1DB57F352056A8F004A +:1004E000D500017D8D00A005FB567804037D7904BD +:1004F000297D1F7C79042E7CE35D700D1105ED557F +:10050000000F6007027D0652329A2652337E600544 +:10051000027D10021202096A2D7F1202096A2A7FE7 +:100520001202096A277F011F03200048EA7CE35575 +:100530005D9A150015001500047806520B6A2652C4 +:100540000B6A5C9A15001500047806520A6A265256 +:100550000A6A5C9A150004780652096A2652096AEA +:10056000097C286A077F0000DB57004D057DFAC132 +:10057000DB571B9A77C254040AC2189AE3C1DB57AF +:10058000F352056AFB568E02941AC36AC862690266 +:100590001D7D941EC36ED36EC8624802C86A94263D +:1005A000C36E981EC36EC8629826C36E6002097C33 +:1005B000C8626E02247D096A1E7F0125004D257DDB +:1005C0007D9A286A187F04627AC2B19AE36E8F001E +:1005D000D805017D8D00A005C8626E02107D096AF4 +:1005E0000A7F0120F97C286A067F0000004D0D7DFE +:1005F000FAC1DB576E9A070004620C6AAE9A286A49 +:10060000FA7F04627AC258045404286AF47F0AC24A +:020610006B9AE3 :00000001FF diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 0fd119586716..f31ce0bf42c9 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1047,6 +1047,8 @@ void __mark_inode_dirty(struct inode *inode, int flags) */ if (!was_dirty) { bdi = inode_to_bdi(inode); + if (!bdi) + goto out; if (bdi_cap_writeback_dirty(bdi)) { WARN(!test_bit(BDI_registered, &bdi->state), diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index cb2bcc1a47c0..cc1d8574dc7f 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -119,6 +119,7 @@ struct fsl_usb2_platform_data { enum usb_wakeup_event (*is_wakeup_event)(struct fsl_usb2_platform_data *); void (*wakeup_handler)(struct fsl_usb2_platform_data *); void (*hsic_post_ops)(void); + void (*gadget_discharge_dp) (bool); struct fsl_usb2_wakeup_platform_data *wakeup_pdata; struct platform_device *pdev; @@ -253,6 +254,7 @@ struct fsl_mxc_camera_platform_data { u32 mclk; u32 csi; void (*pwdn)(int pwdn); + void (*io_init)(void); }; struct mpc8xx_pcmcia_ops { @@ -363,6 +365,8 @@ struct mxs_perfmon_bit_config { struct mxs_platform_perfmon_data { struct mxs_perfmon_bit_config *bit_config_tab; int bit_config_cnt; + void (*plt_init) (void); + void (*plt_exit) (void); }; #endif /* _FSL_DEVICE_H_ */ diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index f3788b5bc9fb..bff6b667a7b1 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -57,7 +57,7 @@ config SND_SOC_IMX_SGTL5000 config SND_SOC_IMX_CS42888 tristate "SoC Audio support for i.MX boards with cs42888" - depends on I2C && (MACH_MX6Q_ARM2 || MACH_MX53_ARD) + depends on I2C && (MACH_MX6Q_ARM2 || MACH_MX6Q_SABREAUTO || MACH_MX53_ARD) select SND_SOC_CS42888 select SND_MXC_SOC_MX2 help |