From 4311e45350ad9199a62e5f37b211cee7de4dfb19 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Sat, 5 Nov 2016 21:34:20 +0100 Subject: apalis-tk1: integrate adv7280-m, ap1302, ov5640 and tc358743 support Integrate SoC camera support for the following CSI-2 codecs/sensors: - Analog Devices ADV7280-M, analog camera decoder with deinterlacer, PAL/NTSC@60fps - ON Semiconductor (formerly Aptina) AP1302 ISP + AR1820 image sensor, 13Mpx, 1080p@30fps - OmniVision OV5640, 5Mpx sensor, 1080p@30fps - Toshiba TC358743 HDMI to CSI-2 bridge, 1080p@60fps Signed-off-by: Marcel Ziswiler Acked-by: Dominik Sliwa --- arch/arm/configs/apalis-tk1_defconfig | 23 +-- arch/arm/mach-tegra/board-apalis-tk1-sensors.c | 259 ++++++++++++++++++++++--- 2 files changed, 241 insertions(+), 41 deletions(-) diff --git a/arch/arm/configs/apalis-tk1_defconfig b/arch/arm/configs/apalis-tk1_defconfig index db018c8081e1..67eb86ee8fc3 100644 --- a/arch/arm/configs/apalis-tk1_defconfig +++ b/arch/arm/configs/apalis-tk1_defconfig @@ -287,31 +287,16 @@ CONFIG_V4L_PLATFORM_DRIVERS=y # CONFIG_TEGRA_RPC is not set CONFIG_TEGRA_NVAVP=y CONFIG_TEGRA_NVAVP_AUDIO=y -CONFIG_VIDEO_OV5640=y -CONFIG_VIDEO_AR0832=y -CONFIG_VIDEO_IMX091=y -CONFIG_VIDEO_IMX135=y -CONFIG_VIDEO_AR0261=y -CONFIG_VIDEO_AR0330=y -CONFIG_VIDEO_AR1335=y -CONFIG_VIDEO_IMX132=y -CONFIG_VIDEO_OV9772=y -CONFIG_VIDEO_OV4689=y -CONFIG_TORCH_SSL3250A=y -CONFIG_MAX77665_FLASH=y -CONFIG_TORCH_MAX77387=y -CONFIG_TORCH_AS364X=y -CONFIG_VIDEO_AD5816=y -CONFIG_VIDEO_DW9718=y -CONFIG_VIDEO_IMX179=y -CONFIG_VIDEO_IMX185=y -CONFIG_VIDEO_CAMERA=y CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_PLATFORM=m CONFIG_VIDEO_TEGRA=m +CONFIG_SOC_CAMERA_AP1302=m CONFIG_SOC_CAMERA_AR0261=m CONFIG_SOC_CAMERA_AR0330=m CONFIG_SOC_CAMERA_IMX135=m +CONFIG_SOC_CAMERA_OV5640=m +CONFIG_SOC_CAMERA_TC358743=m +CONFIG_SOC_CAMERA_ADV7280=m # CONFIG_VGA_ARB is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_FB=y diff --git a/arch/arm/mach-tegra/board-apalis-tk1-sensors.c b/arch/arm/mach-tegra/board-apalis-tk1-sensors.c index ae28fc72a12f..bf650e0dc58b 100644 --- a/arch/arm/mach-tegra/board-apalis-tk1-sensors.c +++ b/arch/arm/mach-tegra/board-apalis-tk1-sensors.c @@ -120,7 +120,7 @@ static void apalis_tk1_soc_camera_del(struct soc_camera_device *icd) static struct platform_device apalis_tk1_soc_camera_device = { .name = "soc-camera-pdrv", - .id = 1, + .id = 0, .dev = { .platform_data = &apalis_tk1_soc_camera_link, }, @@ -159,7 +159,7 @@ static struct soc_camera_link imx135_iclink = { static struct platform_device apalis_tk1_imx135_soc_camera_device = { .name = "soc-camera-pdrv", - .id = 0, + .id = 1, .dev = { .platform_data = &imx135_iclink, }, @@ -198,7 +198,7 @@ static struct soc_camera_link ar0261_iclink = { static struct platform_device apalis_tk1_ar0261_soc_camera_device = { .name = "soc-camera-pdrv", - .id = 1, + .id = 2, .dev = { .platform_data = &ar0261_iclink, }, @@ -237,31 +237,13 @@ static struct soc_camera_link ar0330_iclink = { static struct platform_device apalis_tk1_ar0330_soc_camera_device = { .name = "soc-camera-pdrv", - .id = 0, + .id = 3, .dev = { .platform_data = &ar0330_iclink, }, }; #endif -static struct regulator *apalis_tk1_vcmvdd; - -static int apalis_tk1_get_extra_regulators(void) -{ - if (!apalis_tk1_vcmvdd) { - apalis_tk1_vcmvdd = regulator_get(NULL, "avdd_af1_cam"); - if (WARN_ON(IS_ERR(apalis_tk1_vcmvdd))) { - pr_err("%s: can't get regulator avdd_af1_cam: %ld\n", - __func__, PTR_ERR(apalis_tk1_vcmvdd)); - regulator_put(apalis_tk1_vcmvdd); - apalis_tk1_vcmvdd = NULL; - return -ENODEV; - } - } - - return 0; -} - static struct tegra_io_dpd csia_io = { .name = "CSIA", .io_dpd_reg_index = 0, @@ -280,6 +262,222 @@ static struct tegra_io_dpd csie_io = { .io_dpd_bit = 12, }; +#if IS_ENABLED(CONFIG_SOC_CAMERA_AP1302) +static int apalis_tk1_ap1302_power(struct device *dev, int enable) +{ + if(enable) { + /* disable CSIA IOs DPD mode to turn on camera for apalis_tk1 */ + tegra_io_dpd_disable(&csia_io); + tegra_io_dpd_disable(&csib_io); + } else { + tegra_io_dpd_enable(&csia_io); + tegra_io_dpd_enable(&csib_io); + } + return 0; +} + +static struct i2c_board_info apalis_tk1_ap1302_camera_i2c_device = { + I2C_BOARD_INFO("ap1302", 0x3c), +}; + +static struct tegra_camera_platform_data apalis_tk1_ap1302_camera_platform_data = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_A, + .lanes = 4, + .continuous_clk = 0, +}; + +static struct soc_camera_link ap1302_iclink = { + .bus_id = 0, /* This must match the .id of tegra_vi01_device */ + .board_info = &apalis_tk1_ap1302_camera_i2c_device, + .module_name = "ap1302", + .i2c_adapter_id = 2, + .power = apalis_tk1_ap1302_power, + .priv = &apalis_tk1_ap1302_camera_platform_data, +}; + +static struct platform_device apalis_tk1_ap1302_soc_camera_device = { + .name = "soc-camera-pdrv", + .id = 4, + .dev = { + .platform_data = &ap1302_iclink, + }, +}; +#endif + +#if IS_ENABLED(CONFIG_SOC_CAMERA_OV5640) +static int apalis_tk1_ov5640_power(struct device *dev, int enable) + { + if(enable) { + tegra_io_dpd_disable(&csia_io); + } else { + tegra_io_dpd_enable(&csia_io); + } + return 0; + } + +static struct i2c_board_info apalis_tk1_ov5640_camera_i2c_device = { + I2C_BOARD_INFO("ov5640", 0x3c), +}; + +static struct tegra_camera_platform_data apalis_tk1_ov5640_camera_platform_data = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_A, + .lanes = 2, + .continuous_clk = 0, +}; + +static struct soc_camera_link ov5640_iclink = { + .bus_id = 0, /* This must match the .id of tegra_vi01_device */ + .board_info = &apalis_tk1_ov5640_camera_i2c_device, + .module_name = "ov5640", + .i2c_adapter_id = 2, + .power = apalis_tk1_ov5640_power, + .priv = &apalis_tk1_ov5640_camera_platform_data, +}; + +static struct platform_device apalis_tk1_ov5640_soc_camera_device = { + .name = "soc-camera-pdrv", + .id = 5, + .dev = { + .platform_data = &ov5640_iclink, + }, +}; +#endif + +#if IS_ENABLED(CONFIG_SOC_CAMERA_TC358743) +static int apalis_tk1_tc358743_power(struct device *dev, int enable) +{ + if(enable) { + tegra_io_dpd_disable(&csia_io); + } else { + tegra_io_dpd_enable(&csia_io); + } + return 0; +} + +static struct i2c_board_info apalis_tk1_tc358743_camera_i2c_device = { + I2C_BOARD_INFO("tc358743", 0x0f), +}; + +static struct tegra_camera_platform_data apalis_tk1_tc358743_camera_platform_data = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_A, + .lanes = 2, + .continuous_clk = 1, +}; + +static struct soc_camera_link tc358743_iclink = { + .bus_id = 0, /* This must match the .id of tegra_vi01_device */ + .board_info = &apalis_tk1_tc358743_camera_i2c_device, + .module_name = "tc358743", + .i2c_adapter_id = 2, /* change to 1 if you have auvidea's B100 HDMI to CSI-2 Bridge */ + .power = apalis_tk1_tc358743_power, + .priv = &apalis_tk1_tc358743_camera_platform_data, +}; + +static struct platform_device apalis_tk1_tc358743_soc_camera_device = { + .name = "soc-camera-pdrv", + .id = 6, + .dev = { + .platform_data = &tc358743_iclink, + }, +}; +#endif + +#if IS_ENABLED(CONFIG_SOC_CAMERA_ADV7280) +static int apalis_tk1_adv7280_power(struct device *dev, int enable) +{ + if(enable) { + tegra_io_dpd_disable(&csie_io); + } else { + tegra_io_dpd_enable(&csie_io); + } + return 0; +} + + +static struct i2c_board_info apalis_tk1_adv7280_camera_i2c_device_a = { + I2C_BOARD_INFO("adv7280", 0x20), +}; + +static struct tegra_camera_platform_data apalis_tk1_adv7280_camera_platform_data_a = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_A, + .lanes = 1, + .continuous_clk = 0, +}; + +static struct soc_camera_link adv7280_iclink_a = { + .bus_id = 0, /* This must match the .id of tegra_vi01_device */ + .board_info = &apalis_tk1_adv7280_camera_i2c_device_a, + .module_name = "adv7280", + .i2c_adapter_id = 2, + .power = apalis_tk1_adv7280_power, + .priv = &apalis_tk1_adv7280_camera_platform_data_a, +}; + +static struct platform_device apalis_tk1_adv7280_soc_camera_device_a = { + .name = "soc-camera-pdrv", + .id = 7, + .dev = { + .platform_data = &adv7280_iclink_a, + }, +}; + +/* second ADV7280M connected to CSI CIL-E */ +static struct i2c_board_info apalis_tk1_adv7280_camera_i2c_device_b = { + I2C_BOARD_INFO("adv7280", 0x21), +}; + +static struct tegra_camera_platform_data apalis_tk1_adv7280_camera_platform_data_b = { + .flip_v = 0, + .flip_h = 0, + .port = TEGRA_CAMERA_PORT_CSI_C, + .lanes = 1, + .continuous_clk = 0, +}; + +static struct soc_camera_link adv7280_iclink_b = { + .bus_id = 0, /* This must match the .id of tegra_vi01_device */ + .board_info = &apalis_tk1_adv7280_camera_i2c_device_b, + .module_name = "adv7280", + .i2c_adapter_id = 2, + .power = apalis_tk1_adv7280_power, + .priv = &apalis_tk1_adv7280_camera_platform_data_b, +}; + +static struct platform_device apalis_tk1_adv7280_soc_camera_device_b = { + .name = "soc-camera-pdrv", + .id = 8, + .dev = { + .platform_data = &adv7280_iclink_b, + }, +}; +#endif + +static struct regulator *apalis_tk1_vcmvdd; + +static int apalis_tk1_get_extra_regulators(void) +{ + if (!apalis_tk1_vcmvdd) { + apalis_tk1_vcmvdd = regulator_get(NULL, "avdd_af1_cam"); + if (WARN_ON(IS_ERR(apalis_tk1_vcmvdd))) { + pr_err("%s: can't get regulator avdd_af1_cam: %ld\n", + __func__, PTR_ERR(apalis_tk1_vcmvdd)); + regulator_put(apalis_tk1_vcmvdd); + apalis_tk1_vcmvdd = NULL; + return -ENODEV; + } + } + + return 0; +} + static int apalis_tk1_ar0330_front_power_on(struct ar0330_power_rail *pw) { int err; @@ -1469,6 +1667,23 @@ static int apalis_tk1_camera_init(void) platform_device_register(&apalis_tk1_ar0330_soc_camera_device); #endif +#if IS_ENABLED(CONFIG_SOC_CAMERA_AP1302) + platform_device_register(&apalis_tk1_ap1302_soc_camera_device); +#endif + +#if IS_ENABLED(CONFIG_SOC_CAMERA_OV5640) + platform_device_register(&apalis_tk1_ov5640_soc_camera_device); +#endif + +#if IS_ENABLED(CONFIG_SOC_CAMERA_TC358743) + platform_device_register(&apalis_tk1_tc358743_soc_camera_device); +#endif + +#if IS_ENABLED(CONFIG_SOC_CAMERA_ADV7280) + platform_device_register(&apalis_tk1_adv7280_soc_camera_device_a); + platform_device_register(&apalis_tk1_adv7280_soc_camera_device_b); +#endif + return 0; } -- cgit v1.2.3