ARM: at91: add Atmel ISI and ov2640 support on sam9m10g45 board
This patch adds: - ov2640 sensor in at91sam9m10g45ek board - support to use PCK as ISI_MCK. PCK's parent is managed at SoC level, e.g. at91sam9g45_devices.c Signed-off-by: Josh Wu <josh.wu@atmel.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
parent
45bb9e6fb2
commit
343754f506
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/i2c-gpio.h>
|
#include <linux/i2c-gpio.h>
|
||||||
#include <linux/atmel-mci.h>
|
#include <linux/atmel-mci.h>
|
||||||
@ -28,7 +29,10 @@
|
|||||||
#include <mach/at_hdmac.h>
|
#include <mach/at_hdmac.h>
|
||||||
#include <mach/atmel-mci.h>
|
#include <mach/atmel-mci.h>
|
||||||
|
|
||||||
|
#include <media/atmel-isi.h>
|
||||||
|
|
||||||
#include "generic.h"
|
#include "generic.h"
|
||||||
|
#include "clock.h"
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
@ -870,6 +874,96 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
|
|||||||
void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
|
void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* Image Sensor Interface
|
||||||
|
* -------------------------------------------------------------------- */
|
||||||
|
#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
|
||||||
|
static u64 isi_dmamask = DMA_BIT_MASK(32);
|
||||||
|
static struct isi_platform_data isi_data;
|
||||||
|
|
||||||
|
struct resource isi_resources[] = {
|
||||||
|
[0] = {
|
||||||
|
.start = AT91SAM9G45_BASE_ISI,
|
||||||
|
.end = AT91SAM9G45_BASE_ISI + SZ_16K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.start = AT91SAM9G45_ID_ISI,
|
||||||
|
.end = AT91SAM9G45_ID_ISI,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device at91sam9g45_isi_device = {
|
||||||
|
.name = "atmel_isi",
|
||||||
|
.id = 0,
|
||||||
|
.dev = {
|
||||||
|
.dma_mask = &isi_dmamask,
|
||||||
|
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||||
|
.platform_data = &isi_data,
|
||||||
|
},
|
||||||
|
.resource = isi_resources,
|
||||||
|
.num_resources = ARRAY_SIZE(isi_resources),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_lookup isi_mck_lookups[] = {
|
||||||
|
CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
void __init at91_add_device_isi(struct isi_platform_data *data,
|
||||||
|
bool use_pck_as_mck)
|
||||||
|
{
|
||||||
|
struct clk *pck;
|
||||||
|
struct clk *parent;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
isi_data = *data;
|
||||||
|
|
||||||
|
at91_set_A_periph(AT91_PIN_PB20, 0); /* ISI_D0 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB21, 0); /* ISI_D1 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB22, 0); /* ISI_D2 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB23, 0); /* ISI_D3 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB24, 0); /* ISI_D4 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB25, 0); /* ISI_D5 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB26, 0); /* ISI_D6 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB27, 0); /* ISI_D7 */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB28, 0); /* ISI_PCK */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB30, 0); /* ISI_HSYNC */
|
||||||
|
at91_set_A_periph(AT91_PIN_PB29, 0); /* ISI_VSYNC */
|
||||||
|
at91_set_B_periph(AT91_PIN_PB8, 0); /* ISI_PD8 */
|
||||||
|
at91_set_B_periph(AT91_PIN_PB9, 0); /* ISI_PD9 */
|
||||||
|
at91_set_B_periph(AT91_PIN_PB10, 0); /* ISI_PD10 */
|
||||||
|
at91_set_B_periph(AT91_PIN_PB11, 0); /* ISI_PD11 */
|
||||||
|
|
||||||
|
platform_device_register(&at91sam9g45_isi_device);
|
||||||
|
|
||||||
|
if (use_pck_as_mck) {
|
||||||
|
at91_set_B_periph(AT91_PIN_PB31, 0); /* ISI_MCK (PCK1) */
|
||||||
|
|
||||||
|
pck = clk_get(NULL, "pck1");
|
||||||
|
parent = clk_get(NULL, "plla");
|
||||||
|
|
||||||
|
BUG_ON(IS_ERR(pck) || IS_ERR(parent));
|
||||||
|
|
||||||
|
if (clk_set_parent(pck, parent)) {
|
||||||
|
pr_err("Failed to set PCK's parent\n");
|
||||||
|
} else {
|
||||||
|
/* Register PCK as ISI_MCK */
|
||||||
|
isi_mck_lookups[0].clk = pck;
|
||||||
|
clkdev_add_table(isi_mck_lookups,
|
||||||
|
ARRAY_SIZE(isi_mck_lookups));
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_put(pck);
|
||||||
|
clk_put(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void __init at91_add_device_isi(struct isi_platform_data *data,
|
||||||
|
bool use_pck_as_mck) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* LCD Controller
|
* LCD Controller
|
||||||
|
@ -24,11 +24,13 @@
|
|||||||
#include <linux/gpio_keys.h>
|
#include <linux/gpio_keys.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/atmel-mci.h>
|
#include <linux/atmel-mci.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <video/atmel_lcdc.h>
|
#include <video/atmel_lcdc.h>
|
||||||
|
#include <media/soc_camera.h>
|
||||||
|
#include <media/atmel-isi.h>
|
||||||
|
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
@ -184,6 +186,71 @@ static void __init ek_add_device_nand(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISI
|
||||||
|
*/
|
||||||
|
static struct isi_platform_data __initdata isi_data = {
|
||||||
|
.frate = ISI_CFG1_FRATE_CAPTURE_ALL,
|
||||||
|
/* to use codec and preview path simultaneously */
|
||||||
|
.full_mode = 1,
|
||||||
|
.data_width_flags = ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10,
|
||||||
|
/* ISI_MCK is provided by programmable clock or external clock */
|
||||||
|
.mck_hz = 25000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* soc-camera OV2640
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_SOC_CAMERA_OV2640) || \
|
||||||
|
defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
|
||||||
|
static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)
|
||||||
|
{
|
||||||
|
/* ISI board for ek using default 8-bits connection */
|
||||||
|
return SOCAM_DATAWIDTH_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_camera_power(struct device *dev, int on)
|
||||||
|
{
|
||||||
|
/* enable or disable the camera */
|
||||||
|
pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
|
||||||
|
at91_set_gpio_output(AT91_PIN_PD13, !on);
|
||||||
|
|
||||||
|
if (!on)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* If enabled, give a reset impulse */
|
||||||
|
at91_set_gpio_output(AT91_PIN_PD12, 0);
|
||||||
|
msleep(20);
|
||||||
|
at91_set_gpio_output(AT91_PIN_PD12, 1);
|
||||||
|
msleep(100);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_camera = {
|
||||||
|
I2C_BOARD_INFO("ov2640", 0x30),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct soc_camera_link iclink_ov2640 = {
|
||||||
|
.bus_id = 0,
|
||||||
|
.board_info = &i2c_camera,
|
||||||
|
.i2c_adapter_id = 0,
|
||||||
|
.power = i2c_camera_power,
|
||||||
|
.query_bus_param = isi_camera_query_bus_param,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device isi_ov2640 = {
|
||||||
|
.name = "soc-camera-pdrv",
|
||||||
|
.id = 0,
|
||||||
|
.dev = {
|
||||||
|
.platform_data = &iclink_ov2640,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LCD Controller
|
* LCD Controller
|
||||||
*/
|
*/
|
||||||
@ -377,7 +444,12 @@ static struct gpio_led ek_pwm_led[] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct platform_device *devices[] __initdata = {
|
||||||
|
#if defined(CONFIG_SOC_CAMERA_OV2640) || \
|
||||||
|
defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
|
||||||
|
&isi_ov2640,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
static void __init ek_board_init(void)
|
static void __init ek_board_init(void)
|
||||||
{
|
{
|
||||||
@ -399,6 +471,8 @@ static void __init ek_board_init(void)
|
|||||||
ek_add_device_nand();
|
ek_add_device_nand();
|
||||||
/* I2C */
|
/* I2C */
|
||||||
at91_add_device_i2c(0, NULL, 0);
|
at91_add_device_i2c(0, NULL, 0);
|
||||||
|
/* ISI, using programmable clock as ISI_MCK */
|
||||||
|
at91_add_device_isi(&isi_data, true);
|
||||||
/* LCD Controller */
|
/* LCD Controller */
|
||||||
at91_add_device_lcdc(&ek_lcdc_data);
|
at91_add_device_lcdc(&ek_lcdc_data);
|
||||||
/* Touch Screen */
|
/* Touch Screen */
|
||||||
@ -410,6 +484,8 @@ static void __init ek_board_init(void)
|
|||||||
/* LEDs */
|
/* LEDs */
|
||||||
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
||||||
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
|
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
|
||||||
|
/* Other platform devices */
|
||||||
|
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
|
MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user