Re: New media framework user space usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I succesfully got out images reliably. I just the nokia-tree and mixed
up your mt9t031 and Laurent's mt9t001 code. It's just a barebone that
gets images in default size. It's not cleaned up yet, but I post what
I have.

Greetings,

Bastian


2010/12/6 Guennadi Liakhovetski <g.liakhovetski@xxxxxx>:
> On Thu, 4 Nov 2010, Laurent Pinchart wrote:
>
>> Hi Bastian,
>
> Hi Bastian, all
>
> Have you or anyone ben successful getting mt9p031 to work with the omap3
> ISP driver? If so - can I have the code? Or even if it never worked -
> could you post the latest version of your driver and platform bindings?
>
> Thanks
> Guennadi
>
>>
>> On Tuesday 02 November 2010 11:31:28 Bastian Hecht wrote:
>> > >> I am the first guy needing a 12 bit-bus?
>> > >
>> > > Yes you are :-) You will need to implement 12 bit support in the ISP
>> > > driver, or start by hacking the sensor driver to report a 10 bit format
>> > > (2 bits will be lost but you should still be able to capture an image).
>> >
>> > Isn't that an "officially" supported procedure to drop the least
>> > significant bits?
>> > You gave me the isp configuration
>> > .bus = { .parallel = {
>> >                        .data_lane_shift        = 1,
>> > ...
>> > that instructs the isp to use 10 of the 12 bits.
>>
>> If you don't need the full 12 bits, sure, that should work.
>>
>> > >> Second thing is, the yavta app now gets stuck while dequeuing a buffer.
>> > >>
>> > >> strace ./yavta -f SGRBG10 -s 2592x1944 -n 4 --capture=4 --skip 3 -F
>> > >> /dev/video2 ...
>> > >> ioctl(3, VIDIOC_QBUF, 0xbec111cc)       = 0
>> > >> ioctl(3, VIDIOC_QBUF, 0xbec111cc)       = 0
>> > >> ioctl(3, VIDIOC_QBUF, 0xbec111cc)       = 0
>> > >> ioctl(3, VIDIOC_QBUF, 0xbec111cc)       = 0
>> > >> ioctl(3, VIDIOC_STREAMON, 0xbec11154)   = 0
>> > >> ioctl(3, VIDIOC_DQBUF
>> > >>
>> > >> strace gets stuck in mid of this line.
>> >
>> > Somehow the ISP_ENABLE_IRQ register was reset at some point that is
>> > unclear to me. When I put it on again manually yavta succeeds to read
>> > the frames.
>>
>> That's weird. Let me know if you can reproduce the problem.
>>
>> > Unfortunately the image consists of black pixels only. We found out that the
>> > 2.8V voltage regulator got broken in the course of development - the 1.8V
>> > logic still worked but the ADC did not...
>> >
>> > But the heck - I was never that close :)
>>
>> --
>> Regards,
>>
>> Laurent Pinchart
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
>
/*
 * arch/arm/mach-omap2/board-bastix.c
 *
 * Copyright (C) 2010 Bastian Hecht <hechtb@xxxxxxxxx>
 * 
 * based on
 *
 * Copyright (C) 2008 Nokia Corporation
 *
 * Contact: Sakari Ailus <sakari.ailus@xxxxxxxxx>
 *          Tuukka Toivonen <tuukka.o.toivonen@xxxxxxxxx>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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 St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/i2c.h>
#include <linux/i2c/twl.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>

#include <asm/gpio.h>
#include <plat/control.h>

#include "../../../drivers/media/video/isp/isp.h"
#include "../../../drivers/media/video/isp/ispreg.h"

#include <media/mt9t001.h>

#include "devices.h"


#define GPIO_DIR_OUTPUT		0


//  IGEP CAM BUS NUM
#define BASTIX_CAM_I2C_BUS_NUM		2

static int __init cam_init(void)
{
	return 0;
}

static int bastix_configure_interface(struct v4l2_subdev *subdev,
                                             int width, int height)
{
        struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);

        //isp_set_pixel_clock(isp, 0);

        return 0;
}

static struct mt9t001_platform_data bastix_mt9p031_platform_data = {
	.clk_pol	= 0,
};


static struct i2c_board_info bastix_camera_i2c_devices[] = {
	{
		I2C_BOARD_INFO(MT9P031_NAME, MT9P031_I2C_ADDR),
		.platform_data = &bastix_mt9p031_platform_data,
	},
};

static struct v4l2_subdev_i2c_board_info bastix_camera_mt9p031[] = {
	{
		.board_info = &bastix_camera_i2c_devices[0],
		.i2c_adapter_id = BASTIX_CAM_I2C_BUS_NUM,
	},
	{ NULL, 0, },
};

static struct isp_v4l2_subdevs_group bastix_camera_subdevs[] = {
	{
		.subdevs = bastix_camera_mt9p031,
		.interface = ISP_INTERFACE_PARALLEL,
                .bus = { .parallel = {
                       .data_lane_shift        = 1,
                       .clk_pol                = 0,
                       .bridge                 = ISPCTRL_PAR_BRIDGE_DISABLE,
		} },
	},
	{ NULL, 0, },
};

static struct isp_platform_data bastix_isp_platform_data = {
	.subdevs = bastix_camera_subdevs,
};

static int __init bastix_camera_init(void)
{
	int err;

	printk(KERN_ALERT "address of isp_platform_data in boardconfig: %x\n", &bastix_isp_platform_data);
	err = cam_init();
	if (err)
		return err;

	omap3isp_device.dev.platform_data = &bastix_isp_platform_data;

	return platform_device_register(&omap3isp_device);
}

static void __exit bastix_camera_exit(void)
{
	platform_device_unregister(&omap3isp_device);
}

module_init(bastix_camera_init);
module_exit(bastix_camera_exit);

MODULE_LICENSE("GPL");
/*
 * Copyright (C) 2009 Integration Software and Electronic Engineering.
 *
 * Modified from mach-omap2/board-generic.c
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>

#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>

#include <plat/board.h>
#include <plat/common.h>
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/onenand.h>

#include "mux.h"
#include "hsmmc.h"
#include "sdram-numonyx-m65kxxxxam.h"

#define IGEP2_SMSC911X_CS       5
#define IGEP2_SMSC911X_GPIO     176
#define IGEP2_GPIO_USBH_NRESET  24
#define IGEP2_GPIO_LED0_GREEN 	26
#define IGEP2_GPIO_LED0_RED 	27
#define IGEP2_GPIO_LED1_RED   	28
#define IGEP2_GPIO_DVI_PUP	170
#define IGEP2_GPIO_WIFI_NPD 	94
#define IGEP2_GPIO_WIFI_NRESET 	95

#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)

#define ONENAND_MAP             0x20000000

/* NAND04GR4E1A ( x2 Flash built-in COMBO POP MEMORY )
 * Since the device is equipped with two DataRAMs, and two-plane NAND
 * Flash memory array, these two component enables simultaneous program
 * of 4KiB. Plane1 has only even blocks such as block0, block2, block4
 * while Plane2 has only odd blocks such as block1, block3, block5.
 * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
 */

static struct mtd_partition igep2_onenand_partitions[] = {
	{
		.name           = "X-Loader",
		.offset         = 0,
		.size           = 2 * (64*(2*2048))
	},
	{
		.name           = "U-Boot",
		.offset         = MTDPART_OFS_APPEND,
		.size           = 6 * (64*(2*2048)),
	},
	{
		.name           = "Environment",
		.offset         = MTDPART_OFS_APPEND,
		.size           = 2 * (64*(2*2048)),
	},
	{
		.name           = "Kernel",
		.offset         = MTDPART_OFS_APPEND,
		.size           = 12 * (64*(2*2048)),
	},
	{
		.name           = "File System",
		.offset         = MTDPART_OFS_APPEND,
		.size           = MTDPART_SIZ_FULL,
	},
};

static int igep2_onenand_setup(void __iomem *onenand_base, int freq)
{
       /* nothing is required to be setup for onenand as of now */
       return 0;
}

static struct omap_onenand_platform_data igep2_onenand_data = {
	.parts = igep2_onenand_partitions,
	.nr_parts = ARRAY_SIZE(igep2_onenand_partitions),
	.onenand_setup = igep2_onenand_setup,
	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
};

static struct platform_device igep2_onenand_device = {
	.name		= "omap2-onenand",
	.id		= -1,
	.dev = {
		.platform_data = &igep2_onenand_data,
	},
};

void __init igep2_flash_init(void)
{
	u8		cs = 0;
	u8		onenandcs = GPMC_CS_NUM + 1;

	while (cs < GPMC_CS_NUM) {
		u32 ret = 0;
		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);

		/* Check if NAND/oneNAND is configured */
		if ((ret & 0xC00) == 0x800)
			/* NAND found */
			pr_err("IGEP v2: Unsupported NAND found\n");
		else {
			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
				/* ONENAND found */
				onenandcs = cs;
		}
		cs++;
	}
	if (onenandcs > GPMC_CS_NUM) {
		pr_err("IGEP v2: Unable to find configuration in GPMC\n");
		return;
	}

	if (onenandcs < GPMC_CS_NUM) {
		igep2_onenand_data.cs = onenandcs;
		if (platform_device_register(&igep2_onenand_device) < 0)
			pr_err("IGEP v2: Unable to register OneNAND device\n");
	}
}

#else
void __init igep2_flash_init(void) {}
#endif

#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)

#include <linux/smsc911x.h>

static struct smsc911x_platform_config igep2_smsc911x_config = {
	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS  ,
	.phy_interface	= PHY_INTERFACE_MODE_MII,
};

static struct resource igep2_smsc911x_resources[] = {
	{
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= OMAP_GPIO_IRQ(IGEP2_SMSC911X_GPIO),
		.end	= OMAP_GPIO_IRQ(IGEP2_SMSC911X_GPIO),
		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
	},
};

static struct platform_device igep2_smsc911x_device = {
	.name		= "smsc911x",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(igep2_smsc911x_resources),
	.resource	= igep2_smsc911x_resources,
	.dev		= {
		.platform_data = &igep2_smsc911x_config,
	},
};

static inline void __init igep2_init_smsc911x(void)
{
	unsigned long cs_mem_base;

	if (gpmc_cs_request(IGEP2_SMSC911X_CS, SZ_16M, &cs_mem_base) < 0) {
		pr_err("IGEP v2: Failed request for GPMC mem for smsc911x\n");
		gpmc_cs_free(IGEP2_SMSC911X_CS);
		return;
	}

	igep2_smsc911x_resources[0].start = cs_mem_base + 0x0;
	igep2_smsc911x_resources[0].end   = cs_mem_base + 0xff;

	if ((gpio_request(IGEP2_SMSC911X_GPIO, "SMSC911X IRQ") == 0) &&
	    (gpio_direction_input(IGEP2_SMSC911X_GPIO) == 0)) {
		gpio_export(IGEP2_SMSC911X_GPIO, 0);
	} else {
		pr_err("IGEP v2: Could not obtain gpio for for SMSC911X IRQ\n");
		return;
	}

	platform_device_register(&igep2_smsc911x_device);
}

#else
static inline void __init igep2_init_smsc911x(void) { }
#endif

static struct omap_board_config_kernel igep2_config[] __initdata = {
};

static struct regulator_consumer_supply igep2_vmmc1_supply = {
	.supply		= "vmmc",
};

static struct regulator_consumer_supply igep2_vmmc2_supply = {
	.supply		= "vmmc",
};

/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
static struct regulator_init_data igep2_vmmc1 = {
	.constraints = {
		.min_uV			= 1850000,
		.max_uV			= 3150000,
		.valid_modes_mask	= REGULATOR_MODE_NORMAL
					| REGULATOR_MODE_STANDBY,
		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
					| REGULATOR_CHANGE_MODE
					| REGULATOR_CHANGE_STATUS,
	},
	.num_consumer_supplies  = 1,
	.consumer_supplies      = &igep2_vmmc1_supply,
};

/* VMMC2 for OMAP VDD_MMC2 (i/o) and MMC2 WIFI */
static struct regulator_init_data igep2_vmmc2 = {
	.constraints = {
		.min_uV			= 1850000,
		.max_uV			= 3150000,
		.valid_modes_mask	= REGULATOR_MODE_NORMAL
					| REGULATOR_MODE_STANDBY,
		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
					| REGULATOR_CHANGE_MODE
					| REGULATOR_CHANGE_STATUS,
	},
	.num_consumer_supplies  = 1,
	.consumer_supplies      = &igep2_vmmc2_supply,
};

static struct omap2_hsmmc_info mmc[] = {
	{
		.mmc		= 1,
		.wires		= 4,
		.gpio_cd	= -EINVAL,
		.gpio_wp	= -EINVAL,
	},
	{
		.mmc		= 2,
		.wires		= 4,
		.gpio_cd	= -EINVAL,
		.gpio_wp	= -EINVAL,
	},
	{}      /* Terminator */
};

static int igep2_twl_gpio_setup(struct device *dev,
		unsigned gpio, unsigned ngpio)
{
	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
	mmc[0].gpio_cd = gpio + 0;
	omap2_hsmmc_init(mmc);

	/* link regulators to MMC adapters ... we "know" the
	 * regulators will be set up only *after* we return.
	*/
	igep2_vmmc1_supply.dev = mmc[0].dev;
	igep2_vmmc2_supply.dev = mmc[1].dev;

	return 0;
};

static struct twl4030_gpio_platform_data igep2_gpio_data = {
	.gpio_base	= OMAP_MAX_GPIO_LINES,
	.irq_base	= TWL4030_GPIO_IRQ_BASE,
	.irq_end	= TWL4030_GPIO_IRQ_END,
	.use_leds	= false,
	.setup		= igep2_twl_gpio_setup,
};

static struct twl4030_usb_data igep2_usb_data = {
	.usb_mode	= T2_USB_MODE_ULPI,
};

static int igep2_enable_dvi(struct omap_dss_device *dssdev)
{
	gpio_direction_output(IGEP2_GPIO_DVI_PUP, 1);

	return 0;
}

static void igep2_disable_dvi(struct omap_dss_device *dssdev)
{
	gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);
}

static struct omap_dss_device igep2_dvi_device = {
	.type			= OMAP_DISPLAY_TYPE_DPI,
	.name			= "dvi",
	.driver_name		= "generic_panel",
	.phy.dpi.data_lines	= 24,
	.platform_enable	= igep2_enable_dvi,
	.platform_disable	= igep2_disable_dvi,
};

static struct omap_dss_device *igep2_dss_devices[] = {
	&igep2_dvi_device
};

static struct omap_dss_board_info igep2_dss_data = {
	.num_devices	= ARRAY_SIZE(igep2_dss_devices),
	.devices	= igep2_dss_devices,
	.default_device	= &igep2_dvi_device,
};

static struct platform_device igep2_dss_device = {
	.name	= "omapdss",
	.id	= -1,
	.dev	= {
		.platform_data = &igep2_dss_data,
	},
};

static struct regulator_consumer_supply igep2_vpll2_supply = {
	.supply	= "vdds_dsi",
	.dev	= &igep2_dss_device.dev,
};

static struct regulator_init_data igep2_vpll2 = {
	.constraints = {
		.name			= "VDVI",
		.min_uV			= 1800000,
		.max_uV			= 1800000,
		.apply_uV		= true,
		.valid_modes_mask	= REGULATOR_MODE_NORMAL
					| REGULATOR_MODE_STANDBY,
		.valid_ops_mask		= REGULATOR_CHANGE_MODE
					| REGULATOR_CHANGE_STATUS,
	},
	.num_consumer_supplies	= 1,
	.consumer_supplies	= &igep2_vpll2_supply,
};

static void __init igep2_display_init(void)
{
	if (gpio_request(IGEP2_GPIO_DVI_PUP, "GPIO_DVI_PUP") &&
	    gpio_direction_output(IGEP2_GPIO_DVI_PUP, 1))
		pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n");
}

#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
#include <linux/leds.h>

static struct gpio_led igep2_gpio_leds[] = {
	{
		.name = "led0:red",
		.gpio = IGEP2_GPIO_LED0_RED,
	},
	{
		.name = "led0:green",
		.default_trigger = "heartbeat",
		.gpio = IGEP2_GPIO_LED0_GREEN,
	},
	{
		.name = "led1:red",
		.gpio = IGEP2_GPIO_LED1_RED,
	},
};

static struct gpio_led_platform_data igep2_led_pdata = {
	.leds           = igep2_gpio_leds,
	.num_leds       = ARRAY_SIZE(igep2_gpio_leds),
};

static struct platform_device igep2_led_device = {
	 .name   = "leds-gpio",
	 .id     = -1,
	 .dev    = {
		 .platform_data  =  &igep2_led_pdata,
	},
};

static void __init igep2_init_led(void)
{
	platform_device_register(&igep2_led_device);
}

#else
static inline void igep2_init_led(void) {}
#endif

static struct platform_device *igep2_devices[] __initdata = {
	&igep2_dss_device,
};

static void __init igep2_init_irq(void)
{
	omap_board_config = igep2_config;
	omap_board_config_size = ARRAY_SIZE(igep2_config);
	omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
	omap_init_irq();
	omap_gpio_init();
}

static struct twl4030_codec_audio_data igep2_audio_data = {
	.audio_mclk = 26000000,
};

static struct twl4030_codec_data igep2_codec_data = {
	.audio_mclk = 26000000,
	.audio = &igep2_audio_data,
};

static struct twl4030_platform_data igep2_twldata = {
	.irq_base	= TWL4030_IRQ_BASE,
	.irq_end	= TWL4030_IRQ_END,

	/* platform_data for children goes here */
	.usb		= &igep2_usb_data,
	.codec		= &igep2_codec_data,
	.gpio		= &igep2_gpio_data,
	.vmmc1          = &igep2_vmmc1,
	.vmmc2		= &igep2_vmmc2,
	.vpll2		= &igep2_vpll2,

};

static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
	{
		I2C_BOARD_INFO("twl4030", 0x48),
		.flags		= I2C_CLIENT_WAKE,
		.irq		= INT_34XX_SYS_NIRQ,
		.platform_data	= &igep2_twldata,
	},
};

static int __init igep2_i2c_init(void)
{
	omap_register_i2c_bus(1, 2600, igep2_i2c_boardinfo,
                        ARRAY_SIZE(igep2_i2c_boardinfo));

	/* register camera i2c bus */
	omap_register_i2c_bus(2, 100, NULL, 0);

	/* Bus 3 is attached to the DVI port where devices like the pico DLP
	 * projector don't work reliably with 400kHz */
	omap_register_i2c_bus(3, 100, NULL, 0);
	return 0;
}

static struct omap_musb_board_data musb_board_data = {
	.interface_type		= MUSB_INTERFACE_ULPI,
	.mode			= MUSB_OTG,
	.power			= 100,
};

static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,

	.phy_reset = true,
	.reset_gpio_port[0] = IGEP2_GPIO_USBH_NRESET,
	.reset_gpio_port[1] = -EINVAL,
	.reset_gpio_port[2] = -EINVAL,
};
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
        // CAM_I2C2
        OMAP3_MUX(I2C2_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(I2C2_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),

	// CAM_HS in down dis
	// CAM_VS in down dis
        OMAP3_MUX(CAM_HS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN | OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_VS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN | OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),

	// CAM_D* in down dis
	OMAP3_MUX(CAM_D0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
        OMAP3_MUX(CAM_D7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
        OMAP3_MUX(CAM_D8, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
        OMAP3_MUX(CAM_D9, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
        OMAP3_MUX(CAM_D10, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(CAM_D11, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),

	// CAM_STROBE out GPIO down goes to aptina_trigger
        OMAP3_MUX(CAM_STROBE, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),

        OMAP3_MUX(CAM_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),



	// CAM_RESET 
//        OMAP3_MUX(CSI2_DX0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
//        OMAP3_MUX(CSI2_DY0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
//          OMAP3_MUX(CSI2_DX1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
//          OMAP3_MUX(CSI2_DY1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN |  OMAP_PIN_OFF_INPUT_PULLDOWN | OMAP_PIN_OFF_WAKEUPENABLE),
  



	/*
	CAM_WEN   NC
	CAM_FLD   NC
	CAM_PDN   NC
	CAM_XCLKB NC
	CAM_XCLKA passt
	CAM_PCLK  passt
	*/


	/*
        //  GO SPI!!!
        OMAP3_MUX(MCBSP1_CLKR, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
        OMAP3_MUX(MCBSP1_DR, OMAP_MUX_MODE2 | OMAP_PIN_INPUT),
        OMAP3_MUX(MCBSP1_FSX, OMAP_MUX_MODE2 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(MCBSP1_DX, OMAP_MUX_MODE2 | OMAP_PIN_OUTPUT),
        
        MCBSP1_CLKR, -> clk
        MCBSP1_DR    -> somi
        MCBSP1_FSX   -> cs0
        MCBSP1_DX,   -> simo
        
	*/
        { .reg_offset = OMAP_MUX_TERMINATOR },
};
#else
        #error "BUT I WANNA CONFIGURE MY GPIOS!!! -Basti"
#endif



static void __init igep2_init(void)
{
	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
	printk(KERN_ALERT "muxing done\n");
	igep2_i2c_init();
	platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
	omap_serial_init();
	usb_musb_init(&musb_board_data);
	usb_ehci_init(&ehci_pdata);

	igep2_flash_init();
	igep2_init_led();
	igep2_display_init();
	igep2_init_smsc911x();

	/* GPIO userspace leds */
#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
	if ((gpio_request(IGEP2_GPIO_LED0_RED, "led0:red") == 0) &&
	    (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
		gpio_export(IGEP2_GPIO_LED0_RED, 0);
		gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
	} else
		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");

	if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "led0:green") == 0) &&
	    (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
		gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
		gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
	} else
		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");

	if ((gpio_request(IGEP2_GPIO_LED1_RED, "led1:red") == 0) &&
	    (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
		gpio_export(IGEP2_GPIO_LED1_RED, 0);
		gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
	} else
		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
#endif

	/* GPIO W-LAN + Bluetooth combo module */
	if ((gpio_request(IGEP2_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
	    (gpio_direction_output(IGEP2_GPIO_WIFI_NPD, 1) == 0)) {
		gpio_export(IGEP2_GPIO_WIFI_NPD, 0);
/* 		gpio_set_value(IGEP2_GPIO_WIFI_NPD, 0); */
	} else
		pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NPD\n");

	if ((gpio_request(IGEP2_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
	    (gpio_direction_output(IGEP2_GPIO_WIFI_NRESET, 1) == 0)) {
		gpio_export(IGEP2_GPIO_WIFI_NRESET, 0);
		gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 0);
		udelay(10);
		gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 1);
	} else
		pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NRESET\n");
}

static void __init igep2_map_io(void)
{
	omap2_set_globals_343x();
	omap34xx_map_common_io();
}

MACHINE_START(IGEP0020, "IGEP v2 board")
	.phys_io	= 0x48000000,
	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
	.boot_params	= 0x80000100,
	.map_io		= igep2_map_io,
	.init_irq	= igep2_init_irq,
	.init_machine	= igep2_init,
	.timer		= &omap_timer,
MACHINE_END
/*
 * Driver for MT9P031 CMOS Image Sensor from Micron
 *
 * Copyright (C) 2010, Bastian Hecht <hechtb@xxxxxxxxx>
 *
 * Based on the MT9T001 and MT9T031 drivers from
 *
 * Guennadi Liakhovetski, DENX Software Engineering <lg@xxxxxxx>
 * Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/delay.h>
#include "../../../drivers/media/video/isp/isp.h"
#include "../../../drivers/media/video/isp/ispreg.h"


#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/videodev2.h>

//#include <media/soc_camera.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-device.h>

#include "isp/isp.h"

#include <linux/debugfs.h>

/*
 * mt9p031 i2c address 0x5d (0xBA read, 0xBB write) same as mt9t031
 * The platform has to define i2c_board_info and link to it from
 * struct soc_camera_link
 */

/* mt9p031 selected register addresses */
#define MT9P031_CHIP_VERSION		0x00
#define MT9P031_ROW_START		0x01
#define MT9P031_COLUMN_START		0x02
#define MT9P031_WINDOW_HEIGHT		0x03
#define MT9P031_WINDOW_WIDTH		0x04
#define MT9P031_HORIZONTAL_BLANKING	0x05
#define MT9P031_VERTICAL_BLANKING	0x06
#define MT9P031_OUTPUT_CONTROL		0x07
#define MT9P031_SHUTTER_WIDTH_UPPER	0x08
#define MT9P031_SHUTTER_WIDTH		0x09
#define MT9P031_PIXEL_CLOCK_CONTROL	0x0a
#define MT9P031_FRAME_RESTART		0x0b
#define MT9P031_SHUTTER_DELAY		0x0c
#define MT9P031_RESET			0x0d
#define MT9P031_READ_MODE_1		0x1e
#define MT9P031_READ_MODE_2		0x20
#define MT9P031_ROW_ADDRESS_MODE	0x22
#define MT9P031_COLUMN_ADDRESS_MODE	0x23
#define MT9P031_GLOBAL_GAIN		0x35
#define MT9P031_TEST_ENABLE		0xa0
#define MT9P031_TEST_GREEN		0xa1
#define MT9P031_TEST_RED		0xa2
#define MT9P031_TEST_BLUE		0xa3

//#define MT9T031_CHIP_ENABLE		0xF8 // PDN is pin signal. no i2c register

#define MT9P031_MAX_HEIGHT		1944 // adapted
#define MT9P031_MAX_WIDTH		2592 // adapted
#define MT9P031_MIN_HEIGHT		2  // could be 0
#define MT9P031_MIN_WIDTH		18 // could be 0
#define MT9P031_HORIZONTAL_BLANK	0  // adapted R0x05
#define MT9P031_VERTICAL_BLANK		25 // adapted R0x06
#define MT9P031_COLUMN_SKIP		16 // adapted
#define MT9P031_ROW_SKIP		54 // adapted

#define MT9P031_CHIP_VERSION_VALUE	0x1801
#define MT9P031_XCLK_RATE		8*1000*1000
/*
#define MT9T031_BUS_PARAM	(SOCAM_PCLK_SAMPLE_RISING |	\
	SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH |	\
	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |	\
	SOCAM_MASTER | SOCAM_DATAWIDTH_10)
*/

void isp_print_status(struct isp_device *isp);
void ispccdc_print_status(struct isp_ccdc_device *ccdc);
int isp_reset(struct isp_device *isp);

struct mt9p031 {
	struct v4l2_subdev subdev;
        struct media_entity_pad pad;

	struct v4l2_mbus_framefmt format;

	struct v4l2_rect rect;	/* Sensor window */
	int model;	/* V4L2_IDENT_MT9P031* codes from v4l2-chip-ident.h */
	u16 xskip;
	u16 yskip;
	unsigned int gain;
	unsigned short y_skip_top;	/* Lines to skip at the top */
	unsigned int exposure;
	unsigned char autoexposure;
	u8  reg_debug_nr;
	u16 reg_debug_value;
};

static struct mt9p031 *to_mt9p031(const struct i2c_client *client)
{
	return container_of(i2c_get_clientdata(client), struct mt9p031, subdev);
}

static int reg_read(struct i2c_client *client, const u8 reg)
{
	s32 data = i2c_smbus_read_word_data(client, reg);
	return data < 0 ? data : swab16(data);
}

static int reg_write(struct i2c_client *client, const u8 reg,
		     const u16 data)
{
	return i2c_smbus_write_word_data(client, reg, swab16(data));
}

static int reg_set(struct i2c_client *client, const u8 reg,
		   const u16 data)
{
	int ret;

	ret = reg_read(client, reg);
	if (ret < 0)
		return ret;
	return reg_write(client, reg, ret | data);
}

static int reg_clear(struct i2c_client *client, const u8 reg,
		     const u16 data)
{
	int ret;

	ret = reg_read(client, reg);
	if (ret < 0)
		return ret;
	return reg_write(client, reg, ret & ~data);
}

static int set_shutter(struct i2c_client *client, const u32 data)
{
	int ret;

	ret = reg_write(client, MT9P031_SHUTTER_WIDTH_UPPER, data >> 16);

	if (ret >= 0)
		ret = reg_write(client, MT9P031_SHUTTER_WIDTH, data & 0xffff);

	return ret;
}

static int get_shutter(struct i2c_client *client, u32 *data)
{
	int ret;

	ret = reg_read(client, MT9P031_SHUTTER_WIDTH_UPPER);
	*data = ret << 16;

	if (ret >= 0)
		ret = reg_read(client, MT9P031_SHUTTER_WIDTH);
	*data |= ret & 0xffff;

	return ret < 0 ? ret : 0;
}

static int mt9p031_idle(struct i2c_client *client)
{
	
        int ret;
	printk(KERN_ALERT "ignoring chip reset\n");
	return 0;
        /* Disable chip output, synchronous option update */
        ret = reg_write(client, MT9P031_RESET, 1);
        if (ret >= 0)
                ret = reg_write(client, MT9P031_RESET, 0);
        if (ret >= 0)
                ret = reg_clear(client, MT9P031_OUTPUT_CONTROL, 2);

        return ret >= 0 ? 0 : -EIO;
}

///////////////////////////////////////////////////////////////////////////////// STUB
static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
                                  struct v4l2_subdev_fh *fh,
                                  struct v4l2_subdev_pad_mbus_code_enum *code)
{
	printk(KERN_ALERT "pad_op 0\n");
        return 0;
}

static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
                                   struct v4l2_subdev_fh *fh,
                                   struct v4l2_subdev_frame_size_enum *fse)
{
	printk(KERN_ALERT "pad_op 1\n");
       	return 0;
}

static int mt9t001_get_format(struct v4l2_subdev *subdev,
                              struct v4l2_subdev_fh *fh, unsigned int pad,
                              struct v4l2_mbus_framefmt *format,
                              enum v4l2_subdev_format which)
{	
	int reg;
        struct i2c_client *client = v4l2_get_subdevdata(subdev);
        struct mt9p031 *mt9p031 = to_mt9p031(client);
	*format = mt9p031->format;
	printk(KERN_ALERT "pad_op 4\n");
        struct isp_device *isp = v4l2_dev_to_isp_device(mt9p031->subdev.v4l2_dev);
        isp_print_status(isp);
	ispccdc_print_status(&isp->isp_ccdc);

	//printk(KERN_ALERT "turning on test pattern\n");
	//reg_write(client, MT9P031_TEST_ENABLE, 1 );
        //reg_write(client, MT9P031_TEST_GREEN,  4095);
        //reg_write(client, MT9P031_TEST_RED,  1000);
        //reg_write(client, MT9P031_TEST_BLUE,  100);

	//reg = reg_read(client, MT9P031_OUTPUT_CONTROL);
	//reg |= 2; // chip enable
	//reg_write(client, MT9P031_OUTPUT_CONTROL, reg);
        return 0;
}

static int mt9t001_set_format(struct v4l2_subdev *subdev,
                              struct v4l2_subdev_fh *fh, unsigned int pad,
                              struct v4l2_mbus_framefmt *format,
                              enum v4l2_subdev_format which)
{	
	printk(KERN_ALERT "pad_op 5\n");       
        return 0;
}
static int mt9t001_get_crop(struct v4l2_subdev *subdev,
                            struct v4l2_subdev_fh *fh,
                            struct v4l2_subdev_pad_crop *crop)
{	
	printk(KERN_ALERT "pad_op 6\n");
        return 0;
}

static int mt9t001_set_crop(struct v4l2_subdev *subdev,
                            struct v4l2_subdev_fh *fh,
                            struct v4l2_subdev_pad_crop *crop)
{	
	printk(KERN_ALERT "pad_op 7\n");       
        return 0;
}


///////////////////////////////////////////////////////////////////////////////// END STUB


static int mt9p031_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int ret;
	printk(KERN_ALERT "s_stream is it! enable: %d\n", enable);
	return 0;
	if (enable)
		/* Switch to master "normal" mode */
		ret = reg_set(client, MT9P031_OUTPUT_CONTROL, 2);
	else
		/* Stop sensor readout */
		ret = reg_clear(client, MT9P031_OUTPUT_CONTROL, 2);

	if (ret < 0)
		return -EIO;

	return 0;
}

enum {
        MT9P031_CTRL_VFLIP,
        MT9P031_CTRL_HFLIP,
        MT9P031_CTRL_GAIN,
        MT9P031_CTRL_EXPOSURE,
        MT9P031_CTRL_EXPOSURE_AUTO,
};

static const struct v4l2_queryctrl mt9p031_controls[] = {
	[MT9P031_CTRL_VFLIP] = {
		.id		= V4L2_CID_VFLIP,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Flip Vertically",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 0,
	},
	[MT9P031_CTRL_HFLIP] = {
		.id		= V4L2_CID_HFLIP,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Flip Horizontally",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 0,
	},
	[MT9P031_CTRL_GAIN] = {
		.id		= V4L2_CID_GAIN,
		.type		= V4L2_CTRL_TYPE_INTEGER,
		.name		= "Gain",
		.minimum	= 0,
		.maximum	= 127,
		.step		= 1,
		.default_value	= 64,
		.flags		= V4L2_CTRL_FLAG_SLIDER,
	},
	[MT9P031_CTRL_EXPOSURE] = {
		.id		= V4L2_CID_EXPOSURE,
		.type		= V4L2_CTRL_TYPE_INTEGER,
		.name		= "Exposure",
		.minimum	= 1,
		.maximum	= 255,
		.step		= 1,
		.default_value	= 255,
		.flags		= V4L2_CTRL_FLAG_SLIDER,
	},
	[MT9P031_CTRL_EXPOSURE_AUTO] = {
		.id		= V4L2_CID_EXPOSURE_AUTO,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Automatic Exposure",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 1,
	}
};



static int mt9p031_g_chip_ident(struct v4l2_subdev *sd,
				struct v4l2_dbg_chip_ident *id)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct mt9p031 *mt9p031 = to_mt9p031(client);

	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
		return -EINVAL;

	if (id->match.addr != client->addr)
		return -ENODEV;

	id->ident	= mt9p031->model;
	id->revision	= 0;

	return 0;
}

static int mt9p031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct mt9p031 *mt9p031 = to_mt9p031(client);
	int data;
	printk(KERN_ALERT "mt g_ctrl\n");
	switch (ctrl->id) {
	case V4L2_CID_VFLIP:
		data = reg_read(client, MT9P031_READ_MODE_2);
		if (data < 0)
			return -EIO;
		ctrl->value = !!(data & 0x8000);
		break;
	case V4L2_CID_HFLIP:
		data = reg_read(client, MT9P031_READ_MODE_2);
		if (data < 0)
			return -EIO;
		ctrl->value = !!(data & 0x4000);
		break;
	case V4L2_CID_EXPOSURE_AUTO:
		ctrl->value = mt9p031->autoexposure;
		break;
	case V4L2_CID_GAIN:
		ctrl->value = mt9p031->gain;
		break;
	case V4L2_CID_EXPOSURE:
		ctrl->value = mt9p031->exposure;
		break;
	}
	return 0;
}

static int mt9p031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	printk(KERN_ALERT "s_ctrl\n");
	return 0;
}


static struct dev_pm_ops mt9p031_dev_pm_ops = {
/*
	.runtime_suspend	= mt9t031_runtime_suspend,
	.runtime_resume		= mt9t031_runtime_resume,
*/
};

static struct device_type mt9p031_dev_type = {
	.name	= "MT9P031",
	.pm	= &mt9p031_dev_pm_ops,
};

/*
 * Interface active, can use i2c. If it fails, it can indeed mean, that
 * this wasn't our capture interface, so, we wait for the right one
 */
static int mt9p031_video_probe(struct i2c_client *client)
{
	struct mt9p031 *mt9p031 = to_mt9p031(client);
	s32 data;
	int ret;

	//struct isp_device *isp = v4l2_dev_to_isp_device(mt9p031->subdev.v4l2_dev);	
	//printk(KERN_ALERT "Set up xlck\n");
	//isp_set_xclk(isp, MT9P031_XCLK_RATE, 0);
	//msleep(100);
	/* Enable the chip */
	//data = reg_write(client, MT9P031_CHIP_ENABLE, 1);
	//dev_dbg(&client->dev, "write: %d\n", data);

	/* Read out the chip version register */
	data = reg_read(client, MT9P031_CHIP_VERSION);

	switch (data) {
	case MT9P031_CHIP_VERSION_VALUE:
		mt9p031->model = V4L2_IDENT_MT9P031;
		break;
	default:
		dev_err(&client->dev,
			"No MT9P031 chip detected, register read %x\n", data);
		return -ENODEV;
	}

	dev_info(&client->dev, "Detected a MT9P031 chip ID %x\n", data);

	ret = mt9p031_idle(client);
	if (ret < 0)
		dev_err(&client->dev, "Failed to initialise the camera\n");
	else
		dev_info(&client->dev, "reset succesful\n");//vdev->dev.type = &mt9p031_dev_type;

	/* mt9t031_idle() has reset the chip to default. */
	mt9p031->exposure = 255;
	mt9p031->gain = 64;

	return ret;
}

static int mt9p031_open(struct v4l2_subdev *subdev, u32 i)
{
        printk(KERN_ALERT "mt9p031 open\n");
        return 0;
}
static int mt9p031_query_ctrl(struct v4l2_subdev *subdev,
                              struct v4l2_queryctrl *qc)
{
        return 0;
}



static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
	.g_ctrl		= mt9p031_g_ctrl,
	.s_ctrl		= mt9p031_s_ctrl,
	.g_chip_ident	= mt9p031_g_chip_ident,
	.init           = mt9p031_open,
        .queryctrl      = mt9p031_query_ctrl,

};

static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
	.s_stream	= mt9p031_s_stream,
};


static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
        .enum_mbus_code = mt9t001_enum_mbus_code,
        .enum_frame_size = mt9t001_enum_frame_size,
        .get_fmt = mt9t001_get_format,
        .set_fmt = mt9t001_set_format,
        .get_crop = mt9t001_get_crop,
        .set_crop = mt9t001_set_crop,
};


static struct v4l2_subdev_ops mt9p031_subdev_ops = {
	.core	= &mt9p031_subdev_core_ops,
	.video	= &mt9p031_subdev_video_ops,
	.pad	= &mt9p031_subdev_pad_ops,
};

static int debugfs_open(struct inode* node, struct file* filp)
{
	printk(KERN_ALERT "debugfs_regs openend\n");
	filp->private_data = node->i_private;
	return 0;
}

static ssize_t debugfs_read(struct file* filp, char __user* buf, size_t count, loff_t *fpos)
{
	int i=0;
	int len=0;
	int reg;
	struct i2c_client *client = filp->private_data;
	if(!client)
		return 0;

	printk(KERN_ALERT "reading debugfs\n");
        printk(KERN_ALERT "clientaddr: %x\n", client);

	struct mt9p031 *mt9p031 = to_mt9p031(client);
	struct isp_device *isp = v4l2_dev_to_isp_device(mt9p031->subdev.v4l2_dev);
	isp_print_status(isp);
	if(mt9p031->reg_debug_nr)
	{
		printk(KERN_ALERT "setting reg %x to %x\n", mt9p031->reg_debug_nr, mt9p031->reg_debug_value);
		reg_write(client, mt9p031->reg_debug_nr, mt9p031->reg_debug_value);
	}
	//isp_reset(isp);
	for(i=0;i<255 && (len+20) < count; i++)
	{
		reg = reg_read(client, i);
		printk(KERN_ALERT "register %x: %x\n", i, reg);
		len+=sprintf(buf+len, "register %x: %x\n", i, reg);
		
	}
	filp->private_data = NULL;
	return len;
}


static struct file_operations debugfs_fops = {
	.open = debugfs_open,
	.read = debugfs_read,
};


static int mt9p031_probe(struct i2c_client *client,
			 const struct i2c_device_id *did)
{
	struct mt9p031 *mt9p031;
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	int ret;



	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
		dev_warn(&adapter->dev,
			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
		return -EIO;
	}

	mt9p031 = kzalloc(sizeof(struct mt9p031), GFP_KERNEL);
	if (!mt9p031)
		return -ENOMEM;


	mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
	mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
//       struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
//       isp_set_xclk(isp, 16*1000*1000, ISP_XCLK_A);

	mt9p031->y_skip_top	= 0;
	mt9p031->rect.left	= MT9P031_COLUMN_SKIP;
	mt9p031->rect.top	= MT9P031_ROW_SKIP;
	mt9p031->rect.width	= MT9P031_MAX_WIDTH;
	mt9p031->rect.height	= MT9P031_MAX_HEIGHT;

        mt9p031->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
        mt9p031->format.width = MT9P031_MAX_WIDTH;
        mt9p031->format.height = MT9P031_MAX_HEIGHT;
        mt9p031->format.field = V4L2_FIELD_NONE;
        mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;


	/*
	 * Simulated autoexposure. If enabled, we calculate shutter width
	 * ourselves in the driver based on vertical blanking and frame width
	 */
	mt9p031->autoexposure = 1;

	mt9p031->xskip = 1;
	mt9p031->yskip = 1;

	mt9p031_idle(client);

	ret = mt9p031_video_probe(client);

	//mt9p031_disable(client);

	if (ret) {
		kfree(mt9p031);
		return ret;
	}

        mt9p031->pad.type = MEDIA_PAD_TYPE_OUTPUT;
        ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
        if (ret) {
                kfree(mt9p031);
                return ret;
        }
	mode_t mode =  S_IRUGO | S_IWUGO;
	struct dentry *dir = debugfs_create_dir("mt9p031", NULL);
	struct dentry *regs_filp = debugfs_create_file("regs", mode, dir, client, &debugfs_fops);
	debugfs_create_u8("reg_nr", mode, dir, &mt9p031->reg_debug_nr);
        debugfs_create_u16("reg_value", mode, dir, &mt9p031->reg_debug_value);

	printk(KERN_ALERT "clientaddr: %x\n", client);
	return ret;
}

static int mt9p031_remove(struct i2c_client *client)
{
	printk(KERN_ALERT "removing mt9p031\n");

        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
        struct mt9p031 *mt9p031 = to_mt9p031(client);

        v4l2_device_unregister_subdev(subdev);
        media_entity_cleanup(&subdev->entity);

	kfree(mt9p031);

	printk(KERN_ALERT "removing done\n");
	return 0;
}

static const struct i2c_device_id mt9p031_id[] = {
	{ "mt9p031", 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, mt9p031_id);

static struct i2c_driver mt9p031_i2c_driver = {
	.driver = {
		.name = "mt9p031",
	},
	.probe		= mt9p031_probe,
	.remove		= mt9p031_remove,
	.id_table	= mt9p031_id,
};

static int __init mt9p031_mod_init(void)
{
	return i2c_add_driver(&mt9p031_i2c_driver);
}

static void __exit mt9p031_mod_exit(void)
{
	i2c_del_driver(&mt9p031_i2c_driver);
}

module_init(mt9p031_mod_init);
module_exit(mt9p031_mod_exit);

MODULE_DESCRIPTION("Micron MT9T031 Camera driver");
MODULE_AUTHOR("Bastian Hecht <hechtb@xxxxxxxxx>");
MODULE_LICENSE("GPL v2");

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux