|
@@ -1,17 +1,16 @@
|
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
|
/*
|
|
|
* Renesas System Solutions Asia Pte. Ltd - Migo-R
|
|
|
*
|
|
|
* Copyright (C) 2008 Magnus Damm
|
|
|
- *
|
|
|
- * This file is subject to the terms and conditions of the GNU General Public
|
|
|
- * License. See the file "COPYING" in the main directory of this archive
|
|
|
- * for more details.
|
|
|
*/
|
|
|
+#include <linux/clkdev.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/input.h>
|
|
|
#include <linux/input/sh_keysc.h>
|
|
|
+#include <linux/memblock.h>
|
|
|
#include <linux/mmc/host.h>
|
|
|
#include <linux/mtd/physmap.h>
|
|
|
#include <linux/mfd/tmio.h>
|
|
@@ -23,10 +22,11 @@
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/clk.h>
|
|
|
#include <linux/gpio.h>
|
|
|
+#include <linux/gpio/machine.h>
|
|
|
#include <linux/videodev2.h>
|
|
|
#include <linux/sh_intc.h>
|
|
|
#include <video/sh_mobile_lcdc.h>
|
|
|
-#include <media/drv-intf/sh_mobile_ceu.h>
|
|
|
+#include <media/drv-intf/renesas-ceu.h>
|
|
|
#include <media/i2c/ov772x.h>
|
|
|
#include <media/soc_camera.h>
|
|
|
#include <media/i2c/tw9910.h>
|
|
@@ -45,6 +45,9 @@
|
|
|
* 0x18000000 8GB 8 NAND Flash (K9K8G08U0A)
|
|
|
*/
|
|
|
|
|
|
+#define CEU_BUFFER_MEMORY_SIZE (4 << 20)
|
|
|
+static phys_addr_t ceu_dma_membase;
|
|
|
+
|
|
|
static struct smc91x_platdata smc91x_info = {
|
|
|
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
|
|
|
};
|
|
@@ -301,65 +304,24 @@ static struct platform_device migor_lcdc_device = {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-static struct clk *camera_clk;
|
|
|
-static DEFINE_MUTEX(camera_lock);
|
|
|
-
|
|
|
-static void camera_power_on(int is_tw)
|
|
|
-{
|
|
|
- mutex_lock(&camera_lock);
|
|
|
-
|
|
|
- /* Use 10 MHz VIO_CKO instead of 24 MHz to work
|
|
|
- * around signal quality issues on Panel Board V2.1.
|
|
|
- */
|
|
|
- camera_clk = clk_get(NULL, "video_clk");
|
|
|
- clk_set_rate(camera_clk, 10000000);
|
|
|
- clk_enable(camera_clk); /* start VIO_CKO */
|
|
|
-
|
|
|
- /* use VIO_RST to take camera out of reset */
|
|
|
- mdelay(10);
|
|
|
- if (is_tw) {
|
|
|
- gpio_set_value(GPIO_PTT2, 0);
|
|
|
- gpio_set_value(GPIO_PTT0, 0);
|
|
|
- } else {
|
|
|
- gpio_set_value(GPIO_PTT0, 1);
|
|
|
- }
|
|
|
- gpio_set_value(GPIO_PTT3, 0);
|
|
|
- mdelay(10);
|
|
|
- gpio_set_value(GPIO_PTT3, 1);
|
|
|
- mdelay(10); /* wait to let chip come out of reset */
|
|
|
-}
|
|
|
-
|
|
|
-static void camera_power_off(void)
|
|
|
-{
|
|
|
- clk_disable(camera_clk); /* stop VIO_CKO */
|
|
|
- clk_put(camera_clk);
|
|
|
-
|
|
|
- gpio_set_value(GPIO_PTT3, 0);
|
|
|
- mutex_unlock(&camera_lock);
|
|
|
-}
|
|
|
-
|
|
|
-static int ov7725_power(struct device *dev, int mode)
|
|
|
-{
|
|
|
- if (mode)
|
|
|
- camera_power_on(0);
|
|
|
- else
|
|
|
- camera_power_off();
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int tw9910_power(struct device *dev, int mode)
|
|
|
-{
|
|
|
- if (mode)
|
|
|
- camera_power_on(1);
|
|
|
- else
|
|
|
- camera_power_off();
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
|
|
|
- .flags = SH_CEU_FLAG_USE_8BIT_BUS,
|
|
|
+static struct ceu_platform_data ceu_pdata = {
|
|
|
+ .num_subdevs = 2,
|
|
|
+ .subdevs = {
|
|
|
+ { /* [0] = ov772x */
|
|
|
+ .flags = 0,
|
|
|
+ .bus_width = 8,
|
|
|
+ .bus_shift = 0,
|
|
|
+ .i2c_adapter_id = 0,
|
|
|
+ .i2c_address = 0x21,
|
|
|
+ },
|
|
|
+ { /* [1] = tw9910 */
|
|
|
+ .flags = 0,
|
|
|
+ .bus_width = 8,
|
|
|
+ .bus_shift = 0,
|
|
|
+ .i2c_adapter_id = 0,
|
|
|
+ .i2c_address = 0x45,
|
|
|
+ },
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static struct resource migor_ceu_resources[] = {
|
|
@@ -373,18 +335,32 @@ static struct resource migor_ceu_resources[] = {
|
|
|
.start = evt2irq(0x880),
|
|
|
.flags = IORESOURCE_IRQ,
|
|
|
},
|
|
|
- [2] = {
|
|
|
- /* place holder for contiguous memory */
|
|
|
- },
|
|
|
};
|
|
|
|
|
|
static struct platform_device migor_ceu_device = {
|
|
|
- .name = "sh_mobile_ceu",
|
|
|
- .id = 0, /* "ceu0" clock */
|
|
|
+ .name = "renesas-ceu",
|
|
|
+ .id = 0, /* ceu.0 */
|
|
|
.num_resources = ARRAY_SIZE(migor_ceu_resources),
|
|
|
.resource = migor_ceu_resources,
|
|
|
.dev = {
|
|
|
- .platform_data = &sh_mobile_ceu_info,
|
|
|
+ .platform_data = &ceu_pdata,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+/* Powerdown/reset gpios for CEU image sensors */
|
|
|
+static struct gpiod_lookup_table ov7725_gpios = {
|
|
|
+ .dev_id = "0-0021",
|
|
|
+ .table = {
|
|
|
+ GPIO_LOOKUP("sh7722_pfc", GPIO_PTT0, "pwdn", GPIO_ACTIVE_HIGH),
|
|
|
+ GPIO_LOOKUP("sh7722_pfc", GPIO_PTT3, "rstb", GPIO_ACTIVE_LOW),
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static struct gpiod_lookup_table tw9910_gpios = {
|
|
|
+ .dev_id = "0-0045",
|
|
|
+ .table = {
|
|
|
+ GPIO_LOOKUP("sh7722_pfc", GPIO_PTT2, "pdn", GPIO_ACTIVE_HIGH),
|
|
|
+ GPIO_LOOKUP("sh7722_pfc", GPIO_PTT3, "rstb", GPIO_ACTIVE_LOW),
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -423,6 +399,15 @@ static struct platform_device sdhi_cn9_device = {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
+static struct ov772x_camera_info ov7725_info = {
|
|
|
+ .flags = 0,
|
|
|
+};
|
|
|
+
|
|
|
+static struct tw9910_video_info tw9910_info = {
|
|
|
+ .buswidth = 8,
|
|
|
+ .mpout = TW9910_MPO_FIELD,
|
|
|
+};
|
|
|
+
|
|
|
static struct i2c_board_info migor_i2c_devices[] = {
|
|
|
{
|
|
|
I2C_BOARD_INFO("rs5c372b", 0x32),
|
|
@@ -434,51 +419,13 @@ static struct i2c_board_info migor_i2c_devices[] = {
|
|
|
{
|
|
|
I2C_BOARD_INFO("wm8978", 0x1a),
|
|
|
},
|
|
|
-};
|
|
|
-
|
|
|
-static struct i2c_board_info migor_i2c_camera[] = {
|
|
|
{
|
|
|
I2C_BOARD_INFO("ov772x", 0x21),
|
|
|
+ .platform_data = &ov7725_info,
|
|
|
},
|
|
|
{
|
|
|
I2C_BOARD_INFO("tw9910", 0x45),
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
-static struct ov772x_camera_info ov7725_info;
|
|
|
-
|
|
|
-static struct soc_camera_link ov7725_link = {
|
|
|
- .power = ov7725_power,
|
|
|
- .board_info = &migor_i2c_camera[0],
|
|
|
- .i2c_adapter_id = 0,
|
|
|
- .priv = &ov7725_info,
|
|
|
-};
|
|
|
-
|
|
|
-static struct tw9910_video_info tw9910_info = {
|
|
|
- .buswidth = SOCAM_DATAWIDTH_8,
|
|
|
- .mpout = TW9910_MPO_FIELD,
|
|
|
-};
|
|
|
-
|
|
|
-static struct soc_camera_link tw9910_link = {
|
|
|
- .power = tw9910_power,
|
|
|
- .board_info = &migor_i2c_camera[1],
|
|
|
- .i2c_adapter_id = 0,
|
|
|
- .priv = &tw9910_info,
|
|
|
-};
|
|
|
-
|
|
|
-static struct platform_device migor_camera[] = {
|
|
|
- {
|
|
|
- .name = "soc-camera-pdrv",
|
|
|
- .id = 0,
|
|
|
- .dev = {
|
|
|
- .platform_data = &ov7725_link,
|
|
|
- },
|
|
|
- }, {
|
|
|
- .name = "soc-camera-pdrv",
|
|
|
- .id = 1,
|
|
|
- .dev = {
|
|
|
- .platform_data = &tw9910_link,
|
|
|
- },
|
|
|
+ .platform_data = &tw9910_info,
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -486,12 +433,9 @@ static struct platform_device *migor_devices[] __initdata = {
|
|
|
&smc91x_eth_device,
|
|
|
&sh_keysc_device,
|
|
|
&migor_lcdc_device,
|
|
|
- &migor_ceu_device,
|
|
|
&migor_nor_flash_device,
|
|
|
&migor_nand_flash_device,
|
|
|
&sdhi_cn9_device,
|
|
|
- &migor_camera[0],
|
|
|
- &migor_camera[1],
|
|
|
};
|
|
|
|
|
|
extern char migor_sdram_enter_start;
|
|
@@ -501,6 +445,8 @@ extern char migor_sdram_leave_end;
|
|
|
|
|
|
static int __init migor_devices_setup(void)
|
|
|
{
|
|
|
+ struct clk *video_clk;
|
|
|
+
|
|
|
/* register board specific self-refresh code */
|
|
|
sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
|
|
|
&migor_sdram_enter_start,
|
|
@@ -620,20 +566,8 @@ static int __init migor_devices_setup(void)
|
|
|
gpio_request(GPIO_FN_VIO_D9, NULL);
|
|
|
gpio_request(GPIO_FN_VIO_D8, NULL);
|
|
|
|
|
|
- gpio_request(GPIO_PTT3, NULL); /* VIO_RST */
|
|
|
- gpio_direction_output(GPIO_PTT3, 0);
|
|
|
- gpio_request(GPIO_PTT2, NULL); /* TV_IN_EN */
|
|
|
- gpio_direction_output(GPIO_PTT2, 1);
|
|
|
- gpio_request(GPIO_PTT0, NULL); /* CAM_EN */
|
|
|
-#ifdef CONFIG_SH_MIGOR_RTA_WVGA
|
|
|
- gpio_direction_output(GPIO_PTT0, 0);
|
|
|
-#else
|
|
|
- gpio_direction_output(GPIO_PTT0, 1);
|
|
|
-#endif
|
|
|
__raw_writew(__raw_readw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */
|
|
|
|
|
|
- platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
|
|
|
-
|
|
|
/* SIU: Port B */
|
|
|
gpio_request(GPIO_FN_SIUBOLR, NULL);
|
|
|
gpio_request(GPIO_FN_SIUBOBT, NULL);
|
|
@@ -647,9 +581,36 @@ static int __init migor_devices_setup(void)
|
|
|
*/
|
|
|
__raw_writew(__raw_readw(PORT_MSELCRA) | 1, PORT_MSELCRA);
|
|
|
|
|
|
+ /*
|
|
|
+ * Use 10 MHz VIO_CKO instead of 24 MHz to work around signal quality
|
|
|
+ * issues on Panel Board V2.1.
|
|
|
+ */
|
|
|
+ video_clk = clk_get(NULL, "video_clk");
|
|
|
+ if (!IS_ERR(video_clk)) {
|
|
|
+ clk_set_rate(video_clk, clk_round_rate(video_clk, 10000000));
|
|
|
+ clk_put(video_clk);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Add a clock alias for ov7725 xclk source. */
|
|
|
+ clk_add_alias("xclk", "0-0021", "video_clk", NULL);
|
|
|
+
|
|
|
+ /* Register GPIOs for video sources. */
|
|
|
+ gpiod_add_lookup_table(&ov7725_gpios);
|
|
|
+ gpiod_add_lookup_table(&tw9910_gpios);
|
|
|
+
|
|
|
i2c_register_board_info(0, migor_i2c_devices,
|
|
|
ARRAY_SIZE(migor_i2c_devices));
|
|
|
|
|
|
+ /* Initialize CEU platform device separately to map memory first */
|
|
|
+ device_initialize(&migor_ceu_device.dev);
|
|
|
+ arch_setup_pdev_archdata(&migor_ceu_device);
|
|
|
+ dma_declare_coherent_memory(&migor_ceu_device.dev,
|
|
|
+ ceu_dma_membase, ceu_dma_membase,
|
|
|
+ ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1,
|
|
|
+ DMA_MEMORY_EXCLUSIVE);
|
|
|
+
|
|
|
+ platform_device_add(&migor_ceu_device);
|
|
|
+
|
|
|
return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
|
|
|
}
|
|
|
arch_initcall(migor_devices_setup);
|
|
@@ -665,10 +626,24 @@ static int migor_mode_pins(void)
|
|
|
return MODE_PIN0 | MODE_PIN1 | MODE_PIN5;
|
|
|
}
|
|
|
|
|
|
+/* Reserve a portion of memory for CEU buffers */
|
|
|
+static void __init migor_mv_mem_reserve(void)
|
|
|
+{
|
|
|
+ phys_addr_t phys;
|
|
|
+ phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
|
|
|
+
|
|
|
+ phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
|
|
|
+ memblock_free(phys, size);
|
|
|
+ memblock_remove(phys, size);
|
|
|
+
|
|
|
+ ceu_dma_membase = phys;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* The Machine Vector
|
|
|
*/
|
|
|
static struct sh_machine_vector mv_migor __initmv = {
|
|
|
.mv_name = "Migo-R",
|
|
|
.mv_mode_pins = migor_mode_pins,
|
|
|
+ .mv_mem_reserve = migor_mv_mem_reserve,
|
|
|
};
|