From 30c1e63389bb65008f8fec09ff5e12b19609c3e8 Mon Sep 17 00:00:00 2001 From: Marcin Juszkiewicz Date: Wed, 9 Sep 2009 10:55:18 +0200 Subject: linux-omap: added support for BeagleBUG extension board This is initial version of BeagleBUG extension board support. So far boards are not available for people outside of BugLabs and Texas Instruments companies. Patch adds support for few modules but not all of them will build for OMAP3 - some are still BUG only. --- conf/machine/include/omap3.inc | 2 +- .../linux/linux-omap-2.6.29/beagleboard/defconfig | 24 +- .../beaglebug/beaglebug-full.patch | 35774 +++++++++++++++++++ recipes/linux/linux-omap_2.6.29.bb | 1 + 4 files changed, 35798 insertions(+), 3 deletions(-) create mode 100644 recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch diff --git a/conf/machine/include/omap3.inc b/conf/machine/include/omap3.inc index 889e0f6478..c52cbddf18 100644 --- a/conf/machine/include/omap3.inc +++ b/conf/machine/include/omap3.inc @@ -1,7 +1,7 @@ require conf/machine/include/tune-cortexa8.inc PREFERRED_PROVIDER_virtual/kernel = "linux-omap" # Increase this everytime you change something in the kernel -MACHINE_KERNEL_PR = "r44" +MACHINE_KERNEL_PR = "r45" KERNEL_IMAGETYPE = "uImage" diff --git a/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig b/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig index c9f8e9962b..a1848d59a4 100644 --- a/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig +++ b/recipes/linux/linux-omap-2.6.29/beagleboard/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.29-omap1 -# Thu Aug 13 12:58:49 2009 +# Wed Sep 9 09:58:54 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -249,6 +249,7 @@ CONFIG_ARM_THUMBEE=y # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_HAS_TLS_REG=y # CONFIG_OUTER_CACHE is not set +CONFIG_ARM_L1_CACHE_SHIFT=6 # # Bus support @@ -272,7 +273,7 @@ CONFIG_PREEMPT=y CONFIG_HZ=128 CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set -CONFIG_ARCH_FLATMEM_HAS_HOLES=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_SELECT_MEMORY_MODEL=y @@ -2274,6 +2275,25 @@ CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y # CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set CONFIG_ANDROID_TIMED_GPIO=m CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_BMI=y + +# +# BMI Hardware Slot support +# +CONFIG_OMAP_SLOT=m +CONFIG_BMI_PIMS=m + +# +# BMI PIMS +# +# CONFIG_BUG_FACTORY_TEST is not set +CONFIG_BMI_GPS=m +CONFIG_BMI_MDACC=m +# CONFIG_BMI_AUDIO is not set +CONFIG_BMI_VH=m +# CONFIG_BMI_SENSOR is not set +# CONFIG_BMI_ZB is not set +CONFIG_BMI_GSM=m # # CBUS support diff --git a/recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch b/recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch new file mode 100644 index 0000000000..f556f420e4 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.29/beaglebug/beaglebug-full.patch @@ -0,0 +1,35774 @@ +--- + arch/arm/Kconfig | 2 + arch/arm/mach-omap2/board-omap3beagle.c | 52 + arch/arm/mach-omap2/mux.c | 25 + arch/arm/plat-omap/include/mach/mux.h | 7 + drivers/Kconfig | 3 + drivers/Makefile | 1 + drivers/bmi/Kconfig | 17 + drivers/bmi/Makefile | 8 + drivers/bmi/core/Makefile | 7 + drivers/bmi/core/core.c | 319 + + drivers/bmi/core/device.c | 35 + drivers/bmi/core/driver.c | 27 + drivers/bmi/core/eeprom.c | 32 + drivers/bmi/core/slot.c | 469 ++ + drivers/bmi/pims/Kconfig | 104 + drivers/bmi/pims/Makefile | 17 + drivers/bmi/pims/camera/Kconfig | 23 + drivers/bmi/pims/camera/Makefile | 12 + drivers/bmi/pims/camera/bmi_ov2640.c | 929 +++++ + drivers/bmi/pims/camera/bmi_vs6624.c | 915 +++++ + drivers/bmi/pims/camera/bug_camera.c | 611 +++ + drivers/bmi/pims/camera/bug_camera.h | 72 + drivers/bmi/pims/camera/ov2640.c | 301 + + drivers/bmi/pims/camera/ov2640.h | 14 + drivers/bmi/pims/camera/vs6624_access.c | 597 +++ + drivers/bmi/pims/camera/vs6624_access.h | 17 + drivers/bmi/pims/camera/vs6624_patch.c | 373 ++ + drivers/bmi/pims/camera/vs6624_regs.h | 467 ++ + drivers/bmi/pims/factory_test/Makefile | 6 + drivers/bmi/pims/factory_test/factory_test.c | 952 +++++ + drivers/bmi/pims/gps/Makefile | 6 + drivers/bmi/pims/gps/bmi_gps.c | 468 ++ + drivers/bmi/pims/gsm/Makefile | 6 + drivers/bmi/pims/gsm/bmi_gsm.c | 301 + + drivers/bmi/pims/lcd/Makefile | 9 + drivers/bmi/pims/lcd/acc.c | 114 + drivers/bmi/pims/lcd/acc.h | 35 + drivers/bmi/pims/lcd/bmi_lcd.c | 1790 ++++++++++ + drivers/bmi/pims/lcd/bmi_lcd_inf.c | 1775 ++++++++++ + drivers/bmi/pims/lcd/bmi_lcd_mi.c | 1855 +++++++++++ + drivers/bmi/pims/lcd/bmi_s320x240.c | 632 +++ + drivers/bmi/pims/lcd/lcd_ctl.c | 421 ++ + drivers/bmi/pims/lcd/lcd_ctl.h | 87 + drivers/bmi/pims/mdacc/Kconfig | 6 + drivers/bmi/pims/mdacc/Makefile | 9 + drivers/bmi/pims/mdacc/acc.c | 381 ++ + drivers/bmi/pims/mdacc/acc.h | 54 + drivers/bmi/pims/mdacc/avr.c | 511 +++ + drivers/bmi/pims/mdacc/avr.h | 54 + drivers/bmi/pims/mdacc/cque.c | 150 + drivers/bmi/pims/mdacc/cque.h | 42 + drivers/bmi/pims/mdacc/ctl.c | 176 + + drivers/bmi/pims/mdacc/ctl.h | 43 + drivers/bmi/pims/mdacc/md.c | 333 ++ + drivers/bmi/pims/mdacc/md.h | 60 + drivers/bmi/pims/mdacc/mdacc.c | 333 ++ + drivers/bmi/pims/mdacc/mdacc.h | 43 + drivers/bmi/pims/mdacc/mon.c | 474 ++ + drivers/bmi/pims/mdacc/mon.h | 61 + drivers/bmi/pims/projector/Makefile | 7 + drivers/bmi/pims/projector/bmi_projector.c | 674 ++++ + drivers/bmi/pims/projector/ch7024.c | 476 ++ + drivers/bmi/pims/projector/ch7024.h | 166 + + drivers/bmi/pims/sensor/Makefile | 6 + drivers/bmi/pims/sensor/bmi_sensor.c | 4321 ++++++++++++++++++++++++++ + drivers/bmi/pims/sound/Makefile | 6 + drivers/bmi/pims/sound/bmi_audio.c | 4434 +++++++++++++++++++++++++++ + drivers/bmi/pims/vonhippel/Makefile | 6 + drivers/bmi/pims/vonhippel/bmi_vh.c | 942 +++++ + drivers/bmi/pims/zb/Makefile | 5 + drivers/bmi/pims/zb/bmi_zaccel.c | 684 ++++ + drivers/bmi/pims/zb/bmi_zaccel.h | 288 + + drivers/bmi/pims/zb/bmi_zigbee.c | 1296 +++++++ + drivers/bmi/pims/zb/bmi_zigbee.h | 194 + + drivers/bmi/pims/zb/bmi_znetdev.c | 977 +++++ + drivers/bmi/pims/zb/bmi_zprotocol.c | 619 +++ + drivers/bmi/slots/Kconfig | 21 + drivers/bmi/slots/Makefile | 6 + drivers/bmi/slots/slots_beagle.c | 267 + + drivers/bmi/slots/slots_bug.c | 231 + + include/linux/bmi-ids.h | 30 + include/linux/bmi.h | 142 + include/linux/bmi/at24c02.h | 26 + include/linux/bmi/bmi-bus.h | 21 + include/linux/bmi/bmi-control.h | 303 + + include/linux/bmi/bmi-eeprom-data.h | 83 + include/linux/bmi/bmi-eeprom-driver.h | 113 + include/linux/bmi/bmi-eeprom.h | 75 + include/linux/bmi/bmi-slot.h | 29 + include/linux/bmi/bmi_audio.h | 449 ++ + include/linux/bmi/bmi_camera.h | 36 + include/linux/bmi/bmi_gps.h | 30 + include/linux/bmi/bmi_gsm.h | 33 + include/linux/bmi/bmi_ioctl.h | 27 + include/linux/bmi/bmi_lcd.h | 71 + include/linux/bmi/bmi_mdacc.h | 518 +++ + include/linux/bmi/bmi_projector.h | 33 + include/linux/bmi/bmi_sensor.h | 673 ++++ + include/linux/bmi/bmi_vh.h | 135 + include/linux/bmi/bmi_zb.h | 83 + include/linux/mod_devicetable.h | 13 + scripts/mod/file2alias.c | 20 + 102 files changed, 35212 insertions(+) + +--- git.orig/arch/arm/Kconfig ++++ git/arch/arm/Kconfig +@@ -1342,10 +1342,12 @@ source "drivers/regulator/Kconfig" + + source "drivers/uio/Kconfig" + + source "drivers/staging/Kconfig" + ++source "drivers/bmi/Kconfig" ++ + if ARCH_OMAP + source "drivers/cbus/Kconfig" + endif + + endmenu +--- git.orig/arch/arm/mach-omap2/board-omap3beagle.c ++++ git/arch/arm/mach-omap2/board-omap3beagle.c +@@ -23,10 +23,12 @@ + #include + #include + #include + #include + ++ ++#include + #include + #include + #include + + #include +@@ -404,10 +406,16 @@ static struct gpio_led gpio_leds[] = { + { + .name = "beagleboard::usr0", + .default_trigger = "heartbeat", + .gpio = 150, + }, ++ /*{ ++ .name = "beagleboard::exp21", ++ .default_trigger = "heartbeat", ++ .gpio = 130, ++ }, ++ */ + { + .name = "beagleboard::usr1", + .default_trigger = "mmc0", + .gpio = 149, + }, +@@ -537,20 +545,54 @@ static void __init beagle_display_init(v + } + + gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0); + } + ++ ++static struct resource bmi_slot1_resources[] = { ++ [0] = { ++ .start = 161, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [1] = { ++ .start = 134, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device bmi_slot_devices[] = { ++ { ++ .name = "omap_bmi_slot", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bmi_slot1_resources), ++ .resource = bmi_slot1_resources, ++ }, ++}; ++ ++ ++static void omap_init_bmi_slots(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(bmi_slot_devices); i++) { ++ if (platform_device_register(&bmi_slot_devices[i]) < 0) ++ dev_err(&bmi_slot_devices[i].dev, ++ "Unable to register BMI slot\n"); ++ } ++} ++ + static struct omap_board_config_kernel omap3_beagle_config[] __initdata = { + { OMAP_TAG_UART, &omap3_beagle_uart_config }, + }; + + static struct platform_device *omap3_beagle_devices[] __initdata = { + &beagle_dss_device, + &leds_gpio, + &keys_gpio, + }; + ++ + static void __init omap3beagle_flash_init(void) + { + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + +@@ -598,14 +640,24 @@ static void __init omap3_beagle_init(voi + + omap_cfg_reg(J25_34XX_GPIO170); + + omap3beagle_enc28j60_init(); + ++ omap_cfg_reg(AG4_3530_GPIO134); ++ omap_cfg_reg(K26_34XX_GPIO161); ++ omap_cfg_reg(Y21_3530_GPIO156_OUT); ++ omap_cfg_reg(AF14_34XX_I2C3_SCL); ++ omap_cfg_reg(AG14_34XX_I2C3_SDA); ++ omap_cfg_reg(U21_3530_GPIO159_OUT); ++ gpio_direction_output(156, false); ++ gpio_direction_output(159, false); ++ // BMI Presence and Status + usb_musb_init(); + usb_ehci_init(); + omap3beagle_flash_init(); + beagle_display_init(); ++ omap_init_bmi_slots(); + } + + static void __init omap3_beagle_map_io(void) + { + omap2_set_globals_343x(); +--- git.orig/arch/arm/mach-omap2/mux.c ++++ git/arch/arm/mach-omap2/mux.c +@@ -480,14 +480,39 @@ MUX_CFG_34XX("AE6_34XX_GPIO141", 0x16e, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) + MUX_CFG_34XX("AF5_34XX_GPIO142", 0x170, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) + MUX_CFG_34XX("AE5_34XX_GPIO143", 0x172, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++MUX_CFG_34XX("K26_34XX_GPIO161", 0x196, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) + MUX_CFG_34XX("H19_34XX_GPIO164_OUT", 0x19c, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) + MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++ ++/*BeagleBoard/BUG-Hybrid specific GPIO stuff*/ ++ ++MUX_CFG_34XX("AE2_3530_GPIO130", 0x158, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) ++/* ++MUX_CFG_34XX("AG5_3530_GPIO131", 0x15A, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++MUX_CFG_34XX("AH5_3530_GPIO132", 0x15C, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++MUX_CFG_34XX("AH4_3530_GPIO133", 0x15E, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++*/ ++MUX_CFG_34XX("AG4_3530_GPIO134", 0x160, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++MUX_CFG_34XX("AF4_3530_GPIO135", 0x162, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++MUX_CFG_34XX("Y21_3530_GPIO156_OUT", 0x18C, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) ++MUX_CFG_34XX("AA21_3530_GPIO157", 0x18E, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) ++MUX_CFG_34XX("U21_3530_GPIO159_OUT", 0x192, ++ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) + }; + + #define OMAP34XX_PINS_SZ ARRAY_SIZE(omap34xx_pins) + + #else +--- git.orig/arch/arm/plat-omap/include/mach/mux.h ++++ git/arch/arm/plat-omap/include/mach/mux.h +@@ -799,12 +799,19 @@ enum omap34xx_index { + AE4_34XX_GPIO136_OUT, + AF6_34XX_GPIO140_UP, + AE6_34XX_GPIO141, + AF5_34XX_GPIO142, + AE5_34XX_GPIO143, ++ K26_34XX_GPIO161, + H19_34XX_GPIO164_OUT, + J25_34XX_GPIO170, ++ AE2_3530_GPIO130, ++ AG4_3530_GPIO134, ++ AF4_3530_GPIO135, ++ Y21_3530_GPIO156_OUT, ++ AA21_3530_GPIO157, ++ U21_3530_GPIO159_OUT + }; + + struct omap_mux_cfg { + struct pin_config *pins; + unsigned long size; +--- git.orig/drivers/Kconfig ++++ git/drivers/Kconfig +@@ -4,10 +4,12 @@ menu "Device Drivers" + + source "drivers/base/Kconfig" + + source "drivers/connector/Kconfig" + ++source "drivers/bmi/Kconfig" ++ + source "drivers/mtd/Kconfig" + + source "drivers/of/Kconfig" + + source "drivers/parport/Kconfig" +@@ -107,6 +109,7 @@ source "drivers/uio/Kconfig" + source "drivers/xen/Kconfig" + + source "drivers/staging/Kconfig" + + source "drivers/platform/Kconfig" ++ + endmenu +--- git.orig/drivers/Makefile ++++ git/drivers/Makefile +@@ -91,10 +91,11 @@ obj-y += lguest/ + obj-$(CONFIG_CPU_FREQ) += cpufreq/ + obj-$(CONFIG_CPU_IDLE) += cpuidle/ + obj-y += idle/ + obj-$(CONFIG_MMC) += mmc/ + obj-$(CONFIG_MEMSTICK) += memstick/ ++obj-$(CONFIG_BMI) += bmi/ + obj-$(CONFIG_NEW_LEDS) += leds/ + obj-$(CONFIG_INFINIBAND) += infiniband/ + obj-$(CONFIG_SGI_SN) += sn/ + obj-y += firmware/ + obj-$(CONFIG_CRYPTO) += crypto/ +--- /dev/null ++++ git/drivers/bmi/Kconfig +@@ -0,0 +1,17 @@ ++# ++# BMI Infrastructure ++# ++ ++menuconfig BMI ++ tristate "BMI" ++ depends on I2C ++ default n ++ ---help--- ++ BMI bus infrastructure ++ ++if BMI ++ ++source drivers/bmi/slots/Kconfig ++source drivers/bmi/pims/Kconfig ++ ++endif # BMI +--- /dev/null ++++ git/drivers/bmi/Makefile +@@ -0,0 +1,8 @@ ++# ++# Makefile for the bmi bus drivers. ++# ++ ++obj-$(CONFIG_BMI) += core/ ++obj-$(CONFIG_BMI) += slots/ ++obj-$(CONFIG_BMI) += pims/ ++ +--- /dev/null ++++ git/drivers/bmi/core/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for BMI subsystem core ++# ++ ++#bmicore-objs := core.o slot.o ++ ++obj-$(CONFIG_BMI) += core.o driver.o slot.o eeprom.o +--- /dev/null ++++ git/drivers/bmi/core/core.c +@@ -0,0 +1,319 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static DEFINE_MUTEX(core_lock); ++ ++static struct class *bmi_class; ++ ++ ++struct class* bmi_get_class (void) ++{ ++ return bmi_class; ++}; ++EXPORT_SYMBOL(bmi_get_class); ++ ++ ++/** ++ * bmi_device_get - increments the reference count of the bmi device structure ++ * @dev: the device being referenced ++ * ++ * Each live reference to a device should be refcounted. ++ * ++ * Drivers for BMI devices should normally record such references in ++ * their probe() methods, when they bind to a device, and release ++ * them by calling bmi_dev_put(), in their disconnect() methods. ++ * ++ * A pointer to the device with the incremented reference counter is returned. ++ */ ++struct bmi_device *bmi_dev_get(struct bmi_device *dev) ++{ ++ if (dev) ++ get_device(&dev->dev); ++ return dev; ++} ++ ++ ++/** ++ * bmi_device_put - release a use of the bmi device structure ++ * @dev: device that's been disconnected ++ * ++ * Must be called when a user of a device is finished with it. When the last ++ * user of the device calls this function, the memory of the device is freed. ++ */ ++void bmi_dev_put(struct bmi_device *dev) ++{ ++ if (dev) ++ put_device(&dev->dev); ++} ++ ++ ++/** ++ * bmi_match_one_id - Tell if a BMI device structure has a matching ++ * BMI device id structure ++ * @id: single BMI device id structure to match ++ * @bdev: the BMI device structure to match against ++ * ++ * Returns the matching bmi_device_id structure or %NULL if there is no match. ++ */ ++ ++static const struct bmi_device_id *bmi_match_one_id(const struct bmi_device_id *id, ++ const struct bmi_device *bdev) ++{ ++ if ((id->vendor == bdev->vendor) && ++ (id->product == bdev->product) && ++ ((id->revision == bdev->revision) || (id->revision == BMI_ANY))) ++ return id; ++ return NULL; ++} ++ ++ ++/** ++ * bmi_match_id - See if a BMI device matches a given bmi_device_id table ++ * @ids: array of BMI device id structures to search in ++ * @bdev: the BMI device structure to match against. ++ * ++ * Used by a driver to check whether a BMI device present in the ++ * system is in its list of supported devices. Returns the matching ++ * bmi_device_id structure or %NULL if there is no match. ++ * ++ */ ++ ++ ++const struct bmi_device_id *bmi_match_id(const struct bmi_device_id *ids, ++ struct bmi_device *bdev) ++{ ++ if (ids) { ++ while (ids->vendor) { ++ if (bmi_match_one_id(ids, bdev)) ++ return ids; ++ ids++; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * bmi_device_match - Tell if a BMI device structure has a matching BMI device id structure ++ * @dev: the BMI device structure to match against ++ * @drv: the device driver to search for matching PCI device id structures ++ * ++ * Used by a driver to check whether a BMI device present in the ++ * system is in its list of supported devices. Returns the matching ++ * bmi_device_id structure or %NULL if there is no match. ++ */ ++ ++ ++static int bmi_device_match(struct device *dev, struct device_driver *driver) ++{ ++ struct bmi_device *bmi_dev = to_bmi_device(dev); ++ struct bmi_driver *bmi_drv = to_bmi_driver(driver); ++ const struct bmi_device_id *found_id; ++ ++ found_id = bmi_match_id(bmi_drv->id_table, bmi_dev); ++ ++ if (found_id) ++ return 1; ++ ++ printk(KERN_INFO "BMI: No matching Driver..."); ++ return 0; ++} ++ ++/* ++ * Uevent Generation for hotplug ++ */ ++ ++static int bmi_device_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct bmi_device *bdev = to_bmi_device(dev); ++ ++ if (!dev) ++ return -ENODEV; ++ ++ if (add_uevent_var(env, "BMIBUS_SLOT=%01X", bdev->slot->slotnum)) { ++ return -ENOMEM; ++ } ++ if (add_uevent_var(env, "BMIBUS_VENDOR=%04X", bdev->vendor)) { ++ return -ENOMEM; ++ } ++ if (add_uevent_var(env, "BMIBUS_PRODUCT=%04X", bdev->product)) { ++ return -ENOMEM; ++ } ++ if (add_uevent_var(env, "BMIBUS_REV=%04X", bdev->revision)) { ++ return -ENOMEM; ++ } ++ if (add_uevent_var(env, "MODALIAS=bmi:v%04Xp%04Xr%04X", ++ bdev->vendor, bdev->product, ++ bdev->revision)) { ++ return -ENOMEM; ++ } ++ return 0; ++} ++ ++ ++struct bmi_device *bmi_alloc_dev(struct bmi_slot *slot) ++{ ++ struct bmi_device *dev; ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (!dev) { ++ printk(KERN_ERR "BMI: Couldn't Allocate bmi_device structure...\n"); ++ return NULL; ++ } ++ ++ device_initialize(&dev->dev); ++ dev->dev.bus = &bmi_bus_type; ++ dev_set_name(&dev->dev, "bmi-dev-%d",slot->slotnum); ++ dev->dev.parent = &slot->slotdev; ++ dev->slot = slot; ++ ++ return dev; ++} ++ ++ ++ ++/** ++ * __bmi_probe() ++ * @drv: driver to call to check if it wants the BMI device ++ * @bmi_dev: BMI device being probed ++ * ++ * returns 0 on success, else error. ++ * side-effect: bmi_dev->driver is set to drv when drv claims bmi_dev. ++ */ ++static int ++__bmi_probe(struct bmi_driver *driver, struct bmi_device *bmi_dev) ++{ ++ int error = 0; ++ ++ if (!bmi_dev->driver && driver->probe) { ++ ++ error = driver->probe(bmi_dev); ++ if (error >= 0) { ++ // bmi_device -> bmi_driver (bmi-bus level ) ++ bmi_dev->driver = driver; ++ error = 0; ++ } ++ } ++ return error; ++} ++ ++static int bmi_device_probe (struct device *dev) ++{ ++ int error = 0; ++ struct bmi_driver *drv; ++ struct bmi_device *bmi_dev; ++ ++ //By this time, we have already been match()ed against a driver. ++ ++ // device -> device_driver. (driver-core level) ++ ++ drv = to_bmi_driver(dev->driver); ++ bmi_dev = to_bmi_device(dev); ++ ++ ++ bmi_dev_get(bmi_dev); ++ ++ error = __bmi_probe(drv, bmi_dev); ++ if (error) ++ bmi_dev_put(bmi_dev); ++ else ++ kobject_uevent(&dev->kobj, KOBJ_ADD); ++ ++ return error; ++} ++ ++ ++ ++static int bmi_device_remove (struct device *dev) ++{ ++ struct bmi_device * bmi_dev; ++ struct bmi_driver * driver; ++ ++ bmi_dev = to_bmi_device(dev); ++ driver = bmi_dev->driver; ++ ++ if (driver) { ++ if (driver->remove) ++ driver->remove(bmi_dev); ++ bmi_dev->driver = NULL; ++ } ++ ++ kobject_uevent(&dev->kobj, KOBJ_REMOVE); ++ bmi_dev_put(bmi_dev); ++ return 0; ++} ++ ++static void bmi_device_shutdown(struct device * dev) ++{ ++ return; ++} ++ ++static int bmi_device_suspend (struct device * dev, pm_message_t state) ++{ ++ return -1; ++} ++ ++static int bmi_device_suspend_late (struct device * dev, pm_message_t state) ++{ ++ return -1; ++} ++ ++static int bmi_device_resume_early (struct device * dev) ++{ ++ return -1; ++} ++ ++static int bmi_device_resume (struct device * dev) ++{ ++ return -1; ++} ++ ++ ++ ++struct bus_type bmi_bus_type = { ++ .name = "bmi", ++ .match = bmi_device_match, ++ .uevent = bmi_device_uevent, ++ .probe = bmi_device_probe, ++ .remove = bmi_device_remove, ++ .shutdown = bmi_device_shutdown, ++ .suspend = bmi_device_suspend, ++ .suspend_late = bmi_device_suspend_late, ++ .resume_early = bmi_device_resume_early, ++ .resume = bmi_device_resume, ++}; ++ ++static int __init bmi_init(void) ++{ ++ int ret = 0; ++ ++ ret = bus_register(&bmi_bus_type); ++ if (ret) { ++ printk(KERN_ERR "BMI: (bmi_init) - Bus registration failed...\n"); ++ return ret; ++ } ++ ++ // ret = class_register(&bmi_class); ++ bmi_class = class_create(THIS_MODULE, "bmi"); ++ if (ret) { ++ printk(KERN_ERR "BMI: (bmi_init) - Failed to register BMI Class...\n"); ++ bmi_class = NULL; ++ bus_unregister(&bmi_bus_type); ++ } ++ return ret; ++} ++ ++static void __exit bmi_cleanup(void) ++{ ++ bmi_class = NULL; ++ bus_unregister(&bmi_bus_type); ++} ++ ++//subsys_initcall(bmi_init); ++module_init(bmi_init); ++module_exit(bmi_cleanup); +--- /dev/null ++++ git/drivers/bmi/core/device.c +@@ -0,0 +1,35 @@ ++ ++ ++// bmi_device accessors ++static inline int bmi_device_get_status_irq (struct bmi_device *bdev) ++{ ++ return (bdev->slot->status_irq); ++} ++ ++static inline int bmi_device_get_present_irq (struct bmi_device *bdev) ++{ ++ return (bdev->slot->present_irq); ++} ++ ++static inline struct i2c_adapter* bmi_device_get_i2c_adapter (struct bmi_device *bdev) ++{ ++ return (&bdev->slot->adap); ++} ++ ++static inline int bmi_device_get_slot (struct bmi_device *bdev) ++{ ++ return (bdev->slot->slotnum); ++} ++ ++int bmi_device_present (struct bmi_device *bdev); ++struct bmi_device *bmi_device_get(struct bmi_device *dev); ++void bmi_device_put(struct bmi_device *dev); ++ ++int bmi_device_read_inventory_eeprom ( struct bmi_device *bdev ); ++int bmi_device_init ( struct bmi_device *bdev, struct bmi_info *info, struct bus_type *bmi_bus_type); ++void bmi_device_cleanup( struct bmi_device* bdev); ++int bmi_device_i2c_setup( struct bmi_device *bdev); ++void bmi_device_i2c_cleanup( struct bmi_device* bdev); ++int bmi_device_spi_setup( struct bmi_device *bdev, u32 speed, u8 mode, u8 bits_per_word); ++void bmi_device_spi_cleanup( struct bmi_device* bdev); ++struct spi_device *bmi_device_get_spi( struct bmi_device *bdev); +--- /dev/null ++++ git/drivers/bmi/core/driver.c +@@ -0,0 +1,27 @@ ++#include ++ ++int __bmi_register_driver(struct bmi_driver *drv, struct module *owner) ++{ ++ int error; ++ ++ /* initialize common driver fields */ ++ drv->driver.name = drv->name; ++ drv->driver.bus = &bmi_bus_type; ++ drv->driver.owner = owner; ++ ++ /* register with core */ ++ error = driver_register(&drv->driver); ++ ++ return error; ++} ++ ++ ++void ++bmi_unregister_driver(struct bmi_driver *drv) ++{ ++ driver_unregister(&drv->driver); ++} ++ ++EXPORT_SYMBOL(__bmi_register_driver); ++EXPORT_SYMBOL(bmi_unregister_driver); ++ +--- /dev/null ++++ git/drivers/bmi/core/eeprom.c +@@ -0,0 +1,32 @@ ++#include ++#include ++ ++ ++static inline __u8 bmi_eeprom_checksum (struct bmi_eeprom_data *raw) ++{ ++ int i; ++ __u8 sum = 0; ++ __u8 *buf = (__u8*)raw; ++ ++ for (i = 0; i < (sizeof (struct bmi_eeprom_data) - 1); i++) { ++ sum ^= *buf++; ++ } ++ return sum; ++} ++ ++ ++int bmi_eeprom_checksum_validate (struct bmi_eeprom_data *raw) ++{ ++ int ret = 0; ++ u8 calcsum; ++ ++ calcsum = bmi_eeprom_checksum (raw); ++ ++ if (calcsum != raw->checksum) { ++ //Rework: add conditional debug messages here ++ ret = -1; ++ } ++ return ret; ++} ++ ++ +--- /dev/null ++++ git/drivers/bmi/core/slot.c +@@ -0,0 +1,469 @@ ++/* Matt Isaacs - Kick ass platform independant BMI implementation */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_MUTEX(slot_lock); ++static DEFINE_IDR(bmi_slot_idr); ++ ++ ++//#include "slot.h" ++ ++/* ++struct slot_driver { ++ const char *description; ++ ++ irq_return_t (*irq) (struct bmi_slot); ++ int (*start) (struct bmi_slot); ++ int (*stop) (struct bmi_slot); ++} ++*/ ++ ++static struct task_struct *kslotd_task; ++ ++static DEFINE_SPINLOCK(slot_event_lock); ++static LIST_HEAD(slot_event_list); ++static DECLARE_WAIT_QUEUE_HEAD(kslotd_wait); ++ ++static struct i2c_board_info at24c02_info = { ++ I2C_BOARD_INFO("at24c02", 0XA0 >> 1), ++}; ++ ++static void bmi_slot_work_handler(struct work_struct * work); ++ ++struct bmi_slot* bmi_get_slot(int slotnum) ++{ ++ struct bmi_slot *slot; ++ ++ mutex_lock(&slot_lock); ++ slot = (struct bmi_slot*)idr_find(&bmi_slot_idr, slotnum); ++ if (slot && !try_module_get(slot->owner)) ++ slot = NULL; ++ ++ mutex_unlock(&slot_lock); ++ ++ return slot; ++} ++ ++void bmi_slot_power_on (int num) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ ++ if (!slot) { ++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num); ++ return; ++ } ++ ++ if (slot->actions->power_on) ++ slot->actions->power_on(slot); ++ else ++ printk(KERN_INFO "BMI: Slot %d power is always on...\n", num); ++ return; ++} ++ ++void bmi_slot_power_off (int num) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ ++ if (!slot) { ++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num); ++ return; ++ } ++ ++ if (slot->actions->power_off) ++ slot->actions->power_off(slot); ++ else ++ printk(KERN_INFO "BMI: Slot %d power is always on...\n", num); ++ return; ++} ++ ++void bmi_slot_gpio_configure (int num, int gpio) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ ++ if (!slot) { ++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num); ++ return; ++ } ++ ++ if (slot->actions->gpio_config) ++ slot->actions->gpio_config(slot, gpio); ++ else ++ printk(KERN_INFO "BMI: Slot GPIO not configurable...\n"); ++ return; ++ ++} ++EXPORT_SYMBOL(bmi_slot_gpio_configure); ++ ++int bmi_slot_gpio_get(int num) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ ++ if (!slot) { ++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num); ++ return -ENODEV; ++ } ++ ++ if (slot->actions->gpio_get) ++ return slot->actions->gpio_get(slot); ++ ++ printk(KERN_INFO "BMI: Slot GPIO not writable...\n"); ++ return -EIO; ++} ++EXPORT_SYMBOL(bmi_slot_gpio_get); ++ ++void bmi_slot_gpio_set(int num, int data) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ ++ if (!slot) { ++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num); ++ return; ++ } ++ ++ if (slot->actions->gpio_set) ++ slot->actions->gpio_set(slot, data); ++ else ++ printk(KERN_INFO "BMI: Slot GPIO not writable...\n"); ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_gpio_set); ++ ++void bmi_slot_gpio_write_bit(int num, int gpio, int data) ++{ ++ return; ++} ++ ++int bmi_slot_gpio_read_bit (int num, int gpio) ++{ ++ int gpdat; ++ int bit; ++ ++ gpdat = bmi_slot_gpio_get(num); ++ bit = (gpdat & (1 << gpio)) ? 1 : 0; ++ return bit; ++} ++ ++ ++// NOTE: When a plug-in module is removed, the gpios should be returned to inputs. ++// All requested slot resourece should be released. ++// The slot should be powered down. ++ ++void bmi_slot_gpio_configure_all_as_inputs (int slot) ++{ ++ return; ++} ++ ++ ++void bmi_slot_uart_enable (int num) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ ++ if (!slot) { ++ printk(KERN_ERR "BMI: Slot %d doesn't exist...\n", num); ++ return; ++ } ++ ++ if (slot->actions->uart_enable) ++ return slot->actions->uart_enable(slot); ++ ++ printk(KERN_INFO "BMI: UART always enabled...\n"); ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_uart_enable); ++ ++void bmi_slot_uart_disable (int num) ++{ ++ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_uart_disable); ++ ++void bmi_slot_spi_enable (int num) ++{ ++ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_spi_enable); ++ ++void bmi_slot_spi_disable (int num) ++{ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_spi_disable); ++ ++void bmi_slot_audio_enable (int num) ++{ ++ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_audio_enable); ++ ++void bmi_slot_audio_disable (int num) ++{ ++ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_audio_disable); ++ ++void bmi_slot_battery_enable (int num) ++{ ++ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_battery_enable); ++ ++void bmi_slot_battery_disable (int num) ++{ ++ ++ return; ++} ++EXPORT_SYMBOL(bmi_slot_battery_disable); ++ ++int bmi_slot_module_present (int num) ++{ ++ struct bmi_slot *slot = bmi_get_slot(num); ++ // slot->actions->gpio_set ++ if (slot->actions->present != NULL) ++ return slot->actions->present(slot); ++ else ++ printk(KERN_INFO "BMI: Slot Driver incomplete. No presence detection...\n"); ++ return 0; ++} ++ ++int bmi_slot_read_eeprom(struct bmi_slot *slot, u8* data) ++{ ++ unsigned char i = 0; ++ int ret; ++ ++ if (slot->eeprom == NULL) { ++ printk(KERN_INFO "Can't get eeprom client...\n"); ++ ret = -EIO; ++ } ++ else { ++ ret = i2c_master_send(slot->eeprom, &i, 1); ++ if (ret == 1) ++ ret = i2c_master_recv(slot->eeprom, data, sizeof(struct bmi_eeprom_data)); ++ } ++ return ret; ++} ++ ++int bmi_slot_status_irq_state (int slot) ++{ ++ int state = 0; ++ return state; ++} ++ ++ ++#define DEBOUNCE_DELAY msecs_to_jiffies(1000) ++ ++static irqreturn_t bmi_slot_irq_handler(int irq, void *dev_id) ++{ ++ struct bmi_slot *slot = dev_id; ++ ++ disable_irq_nosync(irq); ++ printk(KERN_INFO " BMI: IRQ Triggered on slot: %d\n", slot->slotnum); ++ schedule_delayed_work(&slot->work, DEBOUNCE_DELAY); ++ return IRQ_HANDLED; ++} ++ ++static void bmi_slot_work_handler(struct work_struct * work) ++{ ++ struct bmi_slot *slot; ++ struct bmi_device *bdev; ++ int ret; ++ struct bmi_eeprom_data data; ++ unsigned char* cdat; ++ ++ slot = work_to_slot(work); ++ ++ mutex_lock(&slot->pres_mutex); ++ if (bmi_slot_module_present(slot->slotnum)) { ++ if (!slot->present) { ++ slot->present = 1; ++ slot->eeprom = i2c_new_device(slot->adap, &at24c02_info); ++ ++ ret = bmi_slot_read_eeprom(slot, (u8*)&data); ++ ++ if (ret < 0) ++ { ++ printk(KERN_INFO "BMI: EEPROM Trouble on Slot %d...\n",slot->slotnum); ++ ++ goto irqenbl; ++ } ++ //Testing stuff here...get rid of this... ++ else ++ printk(KERN_INFO "BMI: EEPROM Found...\n"); ++ cdat = (char*)&data; ++ /*for (i = 0; i < 20; i++) ++ printk(KERN_INFO "0x%x\n", cdat[i]);*/ ++ printk(KERN_INFO "SLOTS: Vendor: 0x%x\n",(data.vendor_msb<<8) | (data.vendor_lsb)); ++ printk(KERN_INFO "SLOTS: Product 0x%x\n",(data.product_msb<<8) | (data.product_lsb)); ++ printk(KERN_INFO "SLOTS: Revision 0x%x\n",(data.revision_msb<<8) | (data.revision_lsb)); ++ ++ //Do new device allocation and hand it over to BMI... ++ bdev = bmi_alloc_dev(slot); ++ bdev->vendor = (data.vendor_msb<<8) | (data.vendor_lsb); ++ bdev->product = (data.product_msb<<8) | (data.product_lsb); ++ bdev->revision = (data.revision_msb<<8) | (data.revision_lsb); ++ ++ //Report module plugin so that udev can load appropriate drivers ++ //kobject_uevent (&bdev->dev.kobj, KOBJ_ADD); ++ ret = device_add(&bdev->dev); ++ if (ret) { ++ printk(KERN_ERR "SLOTS: Failed to add device...%d\n",ret); ++ goto irqenbl; //TODO: Memory allocated for by bmi_alloc_dev ++ } ++ slot->bdev = bdev; ++ /* ++ ret = device_attach(&bdev->dev); ++ if (ret != 1) { ++ printk(KERN_ERR "SLOTS: Failed to attach device...%d\n",ret); ++ goto irqenbl; //TODO: Memory allocated for by bmi_alloc_dev must be freed ++ } ++ */ ++ } ++ else ++ //spurious insertion event.. ++ printk(KERN_INFO "SLOTS: Spurious insertion on Slot %d...\n",slot->slotnum); ++ } ++ else { ++ if (slot->present) { ++ slot->present = 0; ++ printk(KERN_INFO "BMI: Module removed from slot %d...\n", slot->slotnum); ++ if (slot->bdev == NULL) { ++ printk(KERN_ERR "SLOTS: BMI Device NULL...\n"); ++ goto del_eeprom; ++ } ++ //Call BMI device removal stuff here... ++ device_del(&slot->bdev->dev); ++ goto del_eeprom; ++ } ++ } ++ irqenbl: ++ mutex_unlock(&slot->pres_mutex); ++ enable_irq(slot->present_irq); ++ return; ++ del_eeprom: ++ i2c_unregister_device(slot->eeprom); ++ slot->bdev = NULL; ++ slot->eeprom = NULL; ++ goto irqenbl; ++ ++} ++ ++static int bmi_register_slot(struct bmi_slot *slot) ++{ ++ int res = 0; ++ struct class *class; ++ ++ // mutex_init(&slot->state_lock); ++ if (unlikely(WARN_ON(!bmi_bus_type.p))) ++ return -EAGAIN; ++ if (slot->actions == NULL) { ++ printk(KERN_INFO "SLOTS: No Slot actions defined...\n"); ++ goto unlist; ++ } ++ mutex_init(&slot->pres_mutex); ++ mutex_lock(&slot_lock); ++ ++ if (slot->slotdev.parent == NULL) { ++ slot->slotdev.parent = &platform_bus; ++ //debug message here ++ } ++ ++ dev_set_name(&slot->slotdev, "bmi-%d", slot->slotnum); ++ ++ class = bmi_get_class(); ++ if (class == NULL) { ++ printk(KERN_ERR "BMI Class doesn't exist...\n"); ++ goto unlist; ++ } ++ res = device_register(&slot->slotdev); ++ if (res) { ++ printk(KERN_ERR "SLOT: Couldn't register slot... %d\n",res); ++ goto unlist; ++ //quit ++ } ++ ++ //Request IRQ ++ INIT_DELAYED_WORK(&slot->work, bmi_slot_work_handler); ++ ++ printk(KERN_ERR "SLOT: Requesting IRQ...\n"); ++ res = request_irq(slot->present_irq, bmi_slot_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING , slot->name, (void*)slot); ++ ++ if (res) { ++ printk(KERN_ERR "SLOT: IRQ Request failed...\n"); ++ goto unlist; ++ } ++ ++ unlock: ++ mutex_unlock(&slot_lock); ++ return res; ++ unlist: ++ idr_remove(&bmi_slot_idr, slot->slotnum); ++ goto unlock; ++ ++} ++ ++ ++int bmi_add_slot(struct bmi_slot *slot) ++{ ++ int slotnum = 0; ++ int res = 0; ++ ++ retry: ++ if (idr_pre_get(&bmi_slot_idr, GFP_KERNEL) == 0) ++ return -ENOMEM; ++ ++ mutex_lock(&slot_lock); ++ ++ res = idr_get_new_above(&bmi_slot_idr, slot, 0, &slotnum); ++ mutex_unlock(&slot_lock); ++ if (res < 0) { ++ if (res == -EAGAIN) ++ goto retry; ++ return res; ++ } ++ slot->slotnum = slotnum; ++ return bmi_register_slot(slot); ++} ++EXPORT_SYMBOL(bmi_add_slot); ++ ++ ++int bmi_del_slot(struct bmi_slot *slot) ++{ ++ int res = 0; ++ ++ mutex_lock(&slot_lock); ++ if (idr_find(&bmi_slot_idr, slot->slotnum)) { ++ printk(KERN_ERR "BMI: Attempting to delete unregistered slot...\n"); ++ res = -EINVAL; ++ goto unlock; ++ } ++ ++ disable_irq_nosync(slot->present_irq); ++ free_irq(slot->present_irq, slot); ++ device_unregister(&slot->slotdev); ++ idr_remove(&bmi_slot_idr, slot->slotnum); ++ memset(&slot->slotdev, 0, sizeof(slot->slotdev)); ++ ++ unlock: ++ mutex_unlock(&slot_lock); ++ return res; ++} ++EXPORT_SYMBOL(bmi_del_slot); ++ +--- /dev/null ++++ git/drivers/bmi/pims/Kconfig +@@ -0,0 +1,104 @@ ++# ++# BMI PIMS ++# ++ ++config BMI_PIMS ++ tristate "BMI_PIMS" ++ default n ++ ---help--- ++ BMI plug-in module support ++ ++ This driver must be built as a module. ++ ++menu "BMI PIMS" ++ ++config BUG_FACTORY_TEST ++ tristate "BUG_FACTORY_TEST" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ BMI FACTORY Test plug-in module ++ ++ This driver can also be built as a module. ++ ++config BMI_GPS ++ tristate "BMI_GPS" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ BMI GPS plug-in module ++ ++ This driver can also be built as a module. ++ ++source "drivers/bmi/pims/mdacc/Kconfig" ++ ++config VIDEO_BMI_LCD ++ tristate "BMI Bus LCD Module support" ++ depends on FB_MXC && MACH_BUG ++ default n ++ ---help--- ++ This is the BMI bus driver for the LCD Plug-In Module. ++ ++config VIDEO_BMI_LCD_S320X240 ++ tristate "BMI support for Sharp 320x240 module" ++ depends on FB_MXC && MACH_BUG && VIDEO_BMI_LCD ++ default n ++ ---help--- ++ This is the BMI LCD driver for the Sharp 320x240 LCD Plug-In Module. ++ ++config VIDEO_BMI_PROJECTOR ++ tristate "BMI Bus PROJECTOR Module support" ++ depends on FB_MXC_PROJECTOR && MACH_BUG ++ default n ++ ---help--- ++ This is the BMI bus driver for the PROJECTOR Plug-In Module. ++ ++config BMI_AUDIO ++ tristate "BMI Bus Audio Module support" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ This is the BMI bus driver for the Audio Plug-In Module. ++ ++ Select M to make a kernel-loadable module. ++ ++#source "drivers/bmi/pims/camera/Kconfig" ++ ++config BMI_VH ++ tristate "BMI von Hippel Module support" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ BMI von Hippel plug-in module ++ ++ This driver can also be built as a module. ++ ++config BMI_SENSOR ++ tristate "BMI Sensor Module support" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ BMI Sensor plug-in module ++ ++ This driver can also be built as a module. ++ ++config BMI_ZB ++ tristate "BMI ZigBee Module support" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ BMI ZigBee plug-in module ++ ++ This driver can also be built as a module. ++ ++config BMI_GSM ++ tristate "BMI GSM/UMTS Module support" ++ depends on BMI_PIMS ++ default n ++ ---help--- ++ BMI von Hippel plug-in module ++ ++ This driver can also be built as a module. ++ ++endmenu ++ +--- /dev/null ++++ git/drivers/bmi/pims/Makefile +@@ -0,0 +1,17 @@ ++# ++# BMI PIMS ++# ++ ++obj-$(CONFIG_BUG_FACTORY_TEST) += factory_test/ ++obj-$(CONFIG_BMI_GPS) += gps/ ++obj-$(CONFIG_BMI_MDACC) += mdacc/ ++obj-$(CONFIG_VIDEO_BMI_LCD) += lcd/ ++obj-$(CONFIG_BMI_CAMERA) += camera/ ++obj-$(CONFIG_BMI_AUDIO) += sound/ ++obj-$(CONFIG_BMI_VH) += vonhippel/ ++obj-$(CONFIG_BMI_GSM) += gsm/ ++obj-$(CONFIG_BMI_SENSOR) += sensor/ ++obj-$(CONFIG_VIDEO_BMI_PROJECTOR) += projector/ ++obj-$(CONFIG_BMI_ZB) += zb/ ++ ++ +--- /dev/null ++++ git/drivers/bmi/pims/camera/Kconfig +@@ -0,0 +1,23 @@ ++config BMI_CAMERA ++ tristate "BMI Camera" ++ depends on MACH_BUG ++ default n ++ ---help--- ++ This is the BMI Camera driver. ++ ++choice ++ prompt "Select Camera" ++ depends on (BMI_CAMERA) ++ ++config BMI_CAMERA_VS6624 ++ tristate "ST VS6624 camera support" ++ ---help--- ++ If you plan to use the ST VS6624 Camera with your BUG system, say Y here. ++ ++config BMI_CAMERA_OV2640 ++ tristate "Omnivision OV2640 camera support" ++ ---help--- ++ If you plan to use the Omnivision OV2640 Camera with your BUG system, say Y here. ++endchoice ++ ++ +--- /dev/null ++++ git/drivers/bmi/pims/camera/Makefile +@@ -0,0 +1,12 @@ ++#ifeq ($(CONFIG_MACH_BUG),y) ++# obj-$(CONFIG_BMI_CAMERA) += bug_v4l2_capture.o ++#endif ++ ++obj-$(CONFIG_BMI_CAMERA) += bug_camera.o ++ ++bmi_camera_vs6624-objs := bmi_vs6624.o vs6624_access.o ++obj-$(CONFIG_BMI_CAMERA_VS6624) += bmi_camera_vs6624.o ++ ++bmi_camera_ov2640-objs := bmi_ov2640.o ov2640.o ++obj-$(CONFIG_BMI_CAMERA_OV2640) += bmi_camera_ov2640.o ++ +--- /dev/null ++++ git/drivers/bmi/pims/camera/bmi_ov2640.c +@@ -0,0 +1,929 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "bug_camera.h" ++#include "ov2640.h" ++ ++#define BMI_OV2640_VERSION "1.0" ++ ++// BMI device ID table ++static struct bmi_device_id bmi_ov2640_tbl[] = ++{ ++ { .match_flags = BMI_DEVICE_ID_MATCH_VENDOR | BMI_DEVICE_ID_MATCH_PRODUCT, ++ .vendor = BMI_VENDOR_BUG_LABS, ++ .product = BMI_PRODUCT_CAMERA_OV2640, ++ .revision = BMI_ANY, ++ }, ++ { 0, }, /* terminate list */ ++}; ++MODULE_DEVICE_TABLE(bmi, bmi_ov2640_tbl); ++ ++int bmi_ov2640_probe(struct bmi_device *bdev); ++void bmi_ov2640_remove(struct bmi_device *bdev); ++int bmi_ov2640_suspend(struct bmi_device *bdev); ++int bmi_ov2640_resume(struct bmi_device *bdev); ++ ++// BMI driver structure ++static struct bmi_driver bmi_ov2640_driver = ++{ ++ .name = "bmi_ov2640", ++ .id_table = bmi_ov2640_tbl, ++ .probe = bmi_ov2640_probe, ++ .remove = bmi_ov2640_remove, ++ }; ++ ++ ++struct bmi_ov2640 { ++ struct bmi_device *bdev; ++ struct bmi_cam bcam; ++ unsigned int shutter; // shutter button save state ++ unsigned int zoomin; // zoomin button save state ++ unsigned int zoomout; // zoom out button save state ++ unsigned int flash; // state of camera FLASH ++ int irq; ++ struct input_dev *idev; ++ struct work_struct work; ++ ++}; ++ ++#define work_to_bmi_ov2640(w) container_of(w, struct bmi_ov2640, work) ++ ++/* IOX Bits Definitions ++ ++ IOX Bit 7 CAM_RST* Output: 0 = Reset, 1 = Normal Operation ++ IOX Bit 6 GRNLED Output: 0 = Green LED on, 1 = Green LED off ++ IOX Bit 5 SER_SYNC Output: 0 = Normal Operation, 1 = send SYNC ++ IOX Bit 4 FLASH_TORCH* Output: 0 = low beam, 1 = high beam ++ IOX Bit 3 STROBE_R I/O, not used. ++ IOX Bit 2 ZOOMB Input: Zoom OUT Button: 0 = depressed, 1 = released ++ IOX Bit 1 ZOOMA Input: Zoom IN Button 0 = depressed, 1 = released ++ IOX Bit 0 GPIO0_SHUTTER* Input: Shutter Button 0 = depressed, 1 = released ++ ++ GPIO Bits Definitions ++ ++ GPIO Bit 3 REDLED Output: 0 = Red LED on, 1 = Red LED off ++ GPIO Bit 2 FLASHON Output: 0 = Flash LED off, 1 = Flash LED on ++ GPIO Bit 1 SER_RST* Output: 0 = Serializer Reset, 1 = Normal Operation ++ GPIO Bit 0 GPIO0_SHUTTER* Input: Shutter Button: 0 = depressed, 1 = released ++ ++ ++*/ ++ ++ ++ ++ // I2C Slave Address ++#define BMI_IOX_I2C_ADDRESS 0x71 // 7-bit address ++ ++ // I2C IOX register addresses ++#define IOX_INPUT_REG 0x0 ++#define IOX_OUTPUT_REG 0x1 ++#define IOX_POLARITY_REG 0x2 ++#define IOX_CONTROL 0x3 ++ ++ ++// read byte from I2C IO expander ++ ++static int ReadByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char *data) ++{ ++ int ret = 0; ++ struct i2c_msg rmsg[2]; ++ int num_msgs; ++ ++ /* Read Byte with Pointer */ ++ ++ rmsg[0].addr = BMI_IOX_I2C_ADDRESS; ++ rmsg[0].flags = 0; /* write */ ++ rmsg[0].len = 1; ++ rmsg[0].buf = &offset; ++ ++ rmsg[1].addr = BMI_IOX_I2C_ADDRESS; ++ rmsg[1].flags = I2C_M_RD; /* read */ ++ rmsg[1].len = 1; ++ rmsg[1].buf = data; ++ ++ num_msgs = 2; ++ ret = i2c_transfer (adap, rmsg, num_msgs); ++ ++ if (ret == 2) { ++ ret = 0; ++ } ++ else { ++ printk (KERN_ERR "ReadByte_IOX() - i2c_transfer failed\n"); ++ ret = -1; ++ } ++ return ret; ++} ++ ++ ++// write byte to I2C IO expander ++static int WriteByte_IOX(struct i2c_adapter *adap, unsigned char offset, unsigned char data) ++{ ++ int ret = 0; ++ struct i2c_msg wmsg[2]; ++ int num_msgs; ++ ++ /* Write Byte with Pointer */ ++ ++ wmsg[0].addr = BMI_IOX_I2C_ADDRESS; ++ wmsg[0].flags = 0; /* write */ ++ wmsg[0].len = 1; ++ wmsg[0].buf = &offset; ++ ++ wmsg[1].addr = BMI_IOX_I2C_ADDRESS; ++ wmsg[1].flags = 0; /* write */ ++ wmsg[1].len = 1; ++ wmsg[1].buf = &data; ++ ++ num_msgs = 2; ++ ++ ++ ret = i2c_transfer (adap, wmsg, num_msgs); ++ ++ if (ret == 2) { ++ ret = 0; ++ } ++ else { ++ printk (KERN_ERR "WriteByte_IOX() - i2c_transfer() failed.\n"); ++ ret = -1; ++ } ++ return ret; ++} ++ ++ ++/* ++ * Input interrupt handler and support routines ++ */ ++ ++ ++// work handler ++void bmi_ov2640_buttons_work(struct work_struct * work) ++{ ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *pim = work_to_bmi_ov2640(work); ++ ++ unsigned char iox_data; ++ unsigned int test_value; ++ int sync_flag = 0; ++ int err; ++ ++ ++ // avoid i2c i/o if camera hardware not present. ++ ++ if (bmi_device_present (pim->bdev) == 0) { ++ goto exit; ++ } ++ ++ adap = bmi_device_get_i2c_adapter (pim->bdev); ++ ++ ++ // read IOX data input ++ err = ReadByte_IOX (adap, IOX_INPUT_REG, &iox_data); ++ if (err) { ++ goto exit; ++ } ++ ++ // zoom in button ++ test_value = !((iox_data & 0x2) >> 1); ++ if (test_value != pim->zoomin) { ++ pim->zoomin = test_value; ++ input_report_key (pim->idev, BN_ZOOMIN, test_value); ++ sync_flag = 1; ++ } ++ ++ ++ // zoom out button ++ test_value = !((iox_data & 0x4) >> 2); ++ if (test_value != pim->zoomout) { ++ pim->zoomout = test_value; ++ input_report_key (pim->idev, BN_ZOOMOUT, test_value); ++ sync_flag = 1; ++ } ++ ++ if ( sync_flag ) { ++ input_sync (pim->idev); ++ } ++exit: ++ enable_irq (pim->irq); ++ return; ++ ++} ++ ++ ++// interrupt handler ++static irqreturn_t module_irq_handler(int irq, void *dummy) ++{ ++ struct bmi_ov2640 *pim = dummy; ++ unsigned int test_value; ++ ++ int slot; ++ ++ disable_irq_nosync(irq); ++ ++ slot = bmi_device_get_slot(pim->bdev); ++ ++ ++ // shutter button on GPIO ++ ++ test_value = !(bmi_read_gpio_data_reg (slot) & 0x1); ++ ++ if (!test_value == pim->shutter) { ++ pim->shutter = test_value; ++ input_report_key (pim->idev, BN_SHUTTER, test_value); ++ input_sync (pim->idev); ++ } ++ ++ // other buttons on I2C IOX ++ schedule_work (&pim->work); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * control functions ++ */ ++ ++ ++// configure IOX IO and states ++void configure_IOX(struct bmi_ov2640 *cam) ++{ ++ struct i2c_adapter *adap; ++ ++ adap = bmi_device_get_i2c_adapter (cam->bdev); ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, 0xC0); // CAMRST* = 1, GRNLED = Off ++ WriteByte_IOX (adap, IOX_CONTROL, 0x0F); // IOX[7:4]=OUT, IOX[3:0]=IN ++ return; ++ ++} ++ ++// configure GPIO IO and states ++void configure_GPIO(struct bmi_ov2640 *cam) ++{ ++ // set states before turning on outputs ++ ++ int slot; ++ ++ ++ slot = bmi_device_get_slot (cam->bdev); ++ ++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF ++ bmi_set_module_gpio_data (slot, 2, 0); // Flash LED=OFF ++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0 ++ ++ // configure direction ++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_OUT); ++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_OUT); ++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_OUT); ++ bmi_set_module_gpio_dir (slot, 0, BMI_GPIO_IN); // SHUTTER ++ ++ // This is needed. ++ bmi_set_module_gpio_data (slot, 2, 0); // Flash LED off. ++ return; ++ ++} ++ ++// deconfigure IOX and GPIO ++void deconfigure_module(struct bmi_ov2640 *cam) ++{ ++ int slot; ++ struct i2c_adapter *adap; ++ ++ slot = bmi_device_get_slot (cam->bdev); ++ adap = bmi_device_get_i2c_adapter (cam->bdev); ++ ++ ++ if ( bmi_device_present (cam->bdev) ) { ++ WriteByte_IOX (adap, IOX_CONTROL, 0xFF); ++ } ++ bmi_set_module_gpio_dir (slot, 3, BMI_GPIO_IN); ++ bmi_set_module_gpio_dir (slot, 2, BMI_GPIO_IN); ++ bmi_set_module_gpio_dir (slot, 1, BMI_GPIO_IN); ++} ++ ++ ++// configure serializer on plug-in module ++void configure_serializer(struct bmi_ov2640 *cam) ++{ ++ int slot = bmi_device_get_slot (cam->bdev); ++ bmi_set_module_gpio_data (slot, 1, 1); // SER_RST=1 ++} ++ ++void deconfigure_serializer(struct bmi_ov2640 *cam) ++{ ++ int slot = bmi_device_get_slot (cam->bdev); ++ bmi_set_module_gpio_data (slot, 1, 0); // SER_RST=0 ++} ++ ++void enable_camera(struct bmi_ov2640 *cam) ++{ ++ struct i2c_adapter *adap; ++ unsigned char iox_data; ++ ++ adap = bmi_device_get_i2c_adapter (cam->bdev); ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data); ++ ++ iox_data |= (0x80); //Set CAM_RST* to 1. ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data); ++ return; ++} ++ ++// disable camera on plug-in module ++void disable_camera(struct bmi_ov2640 *cam) ++{ ++ struct i2c_adapter *adap; ++ unsigned char iox_data; ++ ++ if (cam == NULL) ++ { ++ printk(KERN_INFO "bmi_camera_ov2640: disable_camera: NULL Pointer on cam\n"); ++ return; ++ } ++ if (cam->bdev == NULL) ++ { ++ printk(KERN_INFO "bmi_camera_ov2640: disable_camera: NULL Pointer on cam->bdev\n"); ++ return; ++ } ++ adap = bmi_device_get_i2c_adapter (cam->bdev); ++ ++ if ( bmi_device_present(cam->bdev) ) { ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data); ++ ++ iox_data &= ~(0x80); //Set CAM_RST* to 0; ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data); ++ } ++ return; ++} ++ ++// generate sync ++void generate_camera_sync(struct i2c_adapter *adap) ++{ ++ unsigned char iox_data[0]; ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data); ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1 ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0 ++ udelay(20); // 60 MHz * 1024 = ~17 us sync time ++ return; ++} ++ ++void set_sync(struct i2c_adapter *adap) ++{ ++ unsigned char iox_data[0]; ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data); ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data | 0x20);// SYNC = 1 ++ return; ++} ++ ++void clear_sync(struct i2c_adapter *adap) ++{ ++ unsigned char iox_data[0]; ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, iox_data); ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, *iox_data & 0xD0);// SYNC = 0 ++ return; ++} ++ ++ ++// check serializer lock ++int check_camera_lock(void) ++{ ++ return bmi_sensor_lock_status(); ++} ++ ++void bmi_ov2640_set_color(struct bmi_cam *cam, int bright, int saturation, int red, int green, int blue) ++{ ++ ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *bmi_ov2640; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ adap = &bmi_ov2640->bdev->adap; ++ ++// ov2640_set_color (adap, bright, saturation, red, green, blue); ++ printk (KERN_ERR "bmi_ov2640_set_color() - NOT IMPLEMENTED.\n"); ++ return; ++ ++} ++ ++void bmi_ov2640_get_color(struct bmi_cam *cam, int *bright, int *saturation, int *red, int *green, int *blue) ++{ ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *bmi_ov2640; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ adap = &bmi_ov2640->bdev->adap; ++ ++// ov2640_get_color (adap, bright, saturation, red, green, blue); ++ printk (KERN_ERR "bmi_ov2640_get_color() - NOT IMPLEMENTED.\n"); ++ return; ++} ++ ++ ++ ++ ++void bmi_ov2640_set_ae_mode (struct bmi_cam *cam, int ae_mode) ++{ ++ printk (KERN_ERR "bmi_ov2640_set_ae_mode() - NOT IMPLEMENTED.\n"); ++} ++ ++ ++void bmi_ov2640_get_ae_mode (struct bmi_cam *cam, int *ae_mode) ++{ ++ printk (KERN_ERR "bmi_ov2640_set_ae_mode() - NOT IMPLEMENTED.\n"); ++} ++ ++ ++sensor_interface * bmi_ov2640_config (struct bmi_cam *cam, int *frame_rate, int high_quality) ++{ ++ ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *bmi_ov2640; ++ int i; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ adap = &bmi_ov2640->bdev->adap; ++ ++ //Bring up the serial link ++ ++ bmi_sensor_active(1); ++ configure_serializer (bmi_ov2640); ++ ++ adap = &bmi_ov2640->bdev->adap; ++ set_sync (adap); ++ ++ for (i = 0; i < 10; i++) { ++ ++ msleep(10); ++ ++ if(check_camera_lock()) { ++ break; ++ } ++ else { ++ printk(KERN_ERR "bmi_ov2640_config() - camera serializer did not lock,i = %d\n", i); ++ } ++ ++ } ++ clear_sync(adap); ++ ++ ++ if(!check_camera_lock()) { ++ printk(KERN_ERR "bmi_ov2640_config(): camera serializer NOT LOCKED\n"); ++ } ++ ++ return &cam->interface; ++ ++} ++ ++ ++sensor_interface * bmi_ov2640_reset (struct bmi_cam *cam) ++{ ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *bmi_ov2640; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ ++ ++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev); ++ ++ //disable the serial link ++ ++ deconfigure_serializer (bmi_ov2640); ++ bmi_sensor_inactive(); ++ ++ return &cam->interface; ++} ++ ++int bmi_ov2640_activate (struct bmi_cam *cam, struct input_dev *idev) ++{ ++ int rc = 0; ++ int i; ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *bmi_ov2640; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ ++ ++ //bmi_ov2640 struct fields ++ bmi_ov2640->idev = idev; ++ ++ bmi_ov2640->shutter = 0; ++ bmi_ov2640->zoomin = 0; ++ bmi_ov2640->zoomout = 0; ++ bmi_ov2640->flash = 0; ++ ++ ++ // install button irq_handler ++ if (request_irq(bmi_ov2640->irq, &module_irq_handler, 0, "bmi_cam_button", bmi_ov2640)) { ++ printk (KERN_ERR ++ "bmi_ov2640_activate() - request_irq (irq = %d) failed.\n", ++ bmi_ov2640->irq); ++ ++ rc = -EBUSY; ++ goto exit; ++ } ++ ++ //Activate serial link ++ bmi_sensor_active(1); // rising edge clock ++ configure_serializer (bmi_ov2640); ++ ++ adap = &bmi_ov2640->bdev->adap; ++ set_sync (adap); ++ ++ ++ for (i = 0; i < 10; i++) { ++ ++ msleep(10); ++ ++ if(check_camera_lock()) { ++ break; ++ } ++ else { ++ printk(KERN_ERR "bmi_ov2640_activate() - camera serializer did not lock,i = %d\n", i); ++ } ++ ++ } ++ clear_sync (adap); ++ ++exit: ++ return rc; ++} ++ ++int bmi_ov2640_deactivate (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ ++ //De-activate serial link ++ deconfigure_serializer (bmi_ov2640); ++ bmi_sensor_inactive(); ++ ++ //uninstall button irq_handler ++ free_irq(bmi_ov2640->irq, bmi_ov2640); ++ return 0; ++} ++ ++ ++void bmi_ov2640_link_enable (struct bmi_cam *cam) ++{ ++ int i; ++ struct i2c_adapter *adap; ++ struct bmi_ov2640 *bmi_ov2640; ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ ++ //Activate serial link ++ bmi_sensor_active(1); // rising edge clock ++ configure_serializer (bmi_ov2640); ++ ++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev); ++ ++ set_sync (adap); ++ ++ ++ //REWORK: Speed this up. (shorten delay) ++ ++ for (i = 0; i < 10; i++) { ++ ++ msleep(10); ++ ++ if(check_camera_lock()) { ++ break; ++ } ++ else { ++ printk(KERN_ERR "bmi_ov2640_activate() - camera serializer did not lock,i = %d\n", i); ++ } ++ ++ } ++ clear_sync (adap); ++ return; ++} ++ ++ ++void bmi_ov2640_link_disable (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ ++ ++ //De-activate serial link ++ deconfigure_serializer (bmi_ov2640); ++ bmi_sensor_inactive(); ++ ++ return; ++} ++ ++ ++int bmi_ov2640_flash_led_off (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ struct bmi_device *bdev; ++ int slot; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ bdev = bmi_ov2640->bdev; ++ ++ slot = bmi_device_get_slot (bdev); ++ ++ bmi_set_module_gpio_data (slot, 2, 0); // Flash LED off. ++ return 0; ++} ++ ++int bmi_ov2640_flash_led_on (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ struct bmi_device *bdev; ++ int slot; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ bdev = bmi_ov2640->bdev; ++ ++ slot = bmi_device_get_slot (bdev); ++ ++ bmi_set_module_gpio_data (slot, 2, 1); // Flash LED on. ++ return 0; ++} ++ ++int bmi_ov2640_flash_high_beam (struct bmi_cam *cam) ++{ ++ unsigned char data; ++ struct bmi_ov2640 *bmi_ov2640; ++ struct i2c_adapter *adap; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev); ++ ++ ReadByte_IOX (adap, IOX_INPUT_REG, &data); ++ data |= 0x10; //High Beam ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, data); ++ ++ return 0; ++} ++ ++int bmi_ov2640_flash_low_beam (struct bmi_cam *cam) ++{ ++ unsigned char data; ++ struct bmi_ov2640 *bmi_ov2640; ++ struct i2c_adapter *adap; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ adap = bmi_device_get_i2c_adapter (bmi_ov2640->bdev); ++ ++ ReadByte_IOX (adap, IOX_INPUT_REG, &data); ++ data &= ~(0x10); // Low Beam ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, data); ++ ++ return 0; ++} ++ ++int bmi_ov2640_red_led_off (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ struct bmi_device *bdev; ++ int slot; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ bdev = bmi_ov2640->bdev; ++ ++ slot = bmi_device_get_slot (bdev); ++ ++ bmi_set_module_gpio_data (slot, 3, 1); // Red LED=OFF ++ return 0; ++} ++ ++ ++int bmi_ov2640_red_led_on (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ struct bmi_device *bdev; ++ int slot; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ bdev = bmi_ov2640->bdev; ++ ++ slot = bmi_device_get_slot (bdev); ++ ++ bmi_set_module_gpio_data (slot, 3, 0); // Red LED=ON ++ return 0; ++} ++ ++ ++int bmi_ov2640_green_led_off (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ struct bmi_device *bdev; ++ struct i2c_adapter *adap; ++ unsigned char iox_data; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ bdev = bmi_ov2640->bdev; ++ ++ adap = bmi_device_get_i2c_adapter (bdev); ++ ++ if ( bmi_device_present(bdev) ) { ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data); ++ ++ iox_data |= (0x40); //Set GRNLED to 1.(Off) ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data); ++ } ++ return 0; ++} ++ ++int bmi_ov2640_green_led_on (struct bmi_cam *cam) ++{ ++ struct bmi_ov2640 *bmi_ov2640; ++ struct bmi_device *bdev; ++ struct i2c_adapter *adap; ++ unsigned char iox_data; ++ ++ bmi_ov2640 = container_of(cam, struct bmi_ov2640, bcam); ++ bdev = bmi_ov2640->bdev; ++ ++ adap = bmi_device_get_i2c_adapter (bdev); ++ ++ if ( bmi_device_present(bdev) ) { ++ ++ ReadByte_IOX (adap, IOX_OUTPUT_REG, &iox_data); ++ ++ iox_data &= ~(0x40); //Set GRNLED to 0.(On) ++ ++ WriteByte_IOX (adap, IOX_OUTPUT_REG, iox_data & 0xF0); ++ } ++ return 0; ++} ++ ++ ++int bmi_ov2640_probe(struct bmi_device *bdev) ++{ ++ ++ int slot = bmi_device_get_slot(bdev); ++ ++ // allocate a driver-specific structure ++ ++ struct bmi_ov2640 *bmi_ov2640 = kzalloc(sizeof(struct bmi_ov2640), GFP_KERNEL); ++ if (!bmi_ov2640) { ++ return -1; ++ } ++ ++ // attach bmi_device structure (so we can find it later). ++ ++ bmi_device_set_drvdata(bdev, bmi_ov2640); ++ printk(KERN_INFO "bmi_ov2640: probe: bmi_ov2640 pointer 0x%p \n",bdev->dev.driver_data); ++ ++ // initialize bmi_ov2640 struct ++ bmi_ov2640->bdev = bdev; ++ ++ // sensor interface struct fields ++ ++ bmi_ov2640->bcam.interface.clk_mode = 0; // gated ++ bmi_ov2640->bcam.interface.ext_vsync = 1; // external vsync ++ bmi_ov2640->bcam.interface.Vsync_pol = 0; // non-inverted ++ bmi_ov2640->bcam.interface.Hsync_pol = 0; // non-inverted ++ bmi_ov2640->bcam.interface.pixclk_pol = 0; // non-inverted ++ bmi_ov2640->bcam.interface.data_pol = 0; // non-inverted ++ bmi_ov2640->bcam.interface.data_width = 1; // 8-bits ++ bmi_ov2640->bcam.interface.width = 1600-1; // 1280 - SXGA 1600 - UXGA ++ bmi_ov2640->bcam.interface.height = 1200-1; // 1024 - SXGA 1200 - UXGA ++ ++ bmi_ov2640->bcam.interface.pixel_fmt = IPU_PIX_FMT_UYVY; // YUV422 ++ bmi_ov2640->bcam.interface.mclk = 12000000; // frequency/src ++ ++ //bmi_camera_sensor struct fields ++ ++ bmi_ov2640->bcam.sensor.set_color = bmi_ov2640_set_color; ++ bmi_ov2640->bcam.sensor.get_color = bmi_ov2640_get_color; ++ bmi_ov2640->bcam.sensor.set_ae_mode = bmi_ov2640_set_ae_mode; ++ bmi_ov2640->bcam.sensor.get_ae_mode = bmi_ov2640_get_ae_mode; ++ bmi_ov2640->bcam.sensor.config = bmi_ov2640_config; ++ bmi_ov2640->bcam.sensor.reset = bmi_ov2640_reset; ++ ++ //bmi_camera_link struct fields ++ ++ bmi_ov2640->bcam.link.enable = bmi_ov2640_link_enable; ++ bmi_ov2640->bcam.link.disable = bmi_ov2640_link_disable; ++ ++ //bmi_camera_cntl struct fields ++ ++ bmi_ov2640->bcam.cntl.flash_led_off = bmi_ov2640_flash_led_off; ++ bmi_ov2640->bcam.cntl.flash_led_on = bmi_ov2640_flash_led_on; ++ bmi_ov2640->bcam.cntl.flash_high_beam = bmi_ov2640_flash_high_beam; ++ bmi_ov2640->bcam.cntl.flash_low_beam = bmi_ov2640_flash_low_beam; ++ bmi_ov2640->bcam.cntl.red_led_off = bmi_ov2640_red_led_off; ++ bmi_ov2640->bcam.cntl.red_led_on = bmi_ov2640_red_led_on; ++ bmi_ov2640->bcam.cntl.green_led_off = bmi_ov2640_green_led_off; ++ bmi_ov2640->bcam.cntl.green_led_on = bmi_ov2640_green_led_on; ++ ++ ++ //bmi_cam struct fields ++ ++ bmi_ov2640->bcam.activate = bmi_ov2640_activate ; ++ bmi_ov2640->bcam.deactivate = bmi_ov2640_deactivate; ++ ++ //bmi_ov2640 struct fields ++ bmi_ov2640->shutter = 0; ++ bmi_ov2640->zoomin = 0; ++ bmi_ov2640->zoomout = 0; ++ bmi_ov2640->flash = 0; ++ ++ bmi_ov2640->irq = bmi_device_get_status_irq (bdev); ++ ++ //initialize struct work_struct ++ INIT_WORK (&bmi_ov2640->work, bmi_ov2640_buttons_work); ++ ++ //Power stablization delay ++ mdelay(500); ++ ++ //Do one-time hw initialization (e.g. patch) ++ ++ // configure IOX ++ configure_IOX (bmi_ov2640); ++ ++ // configure GPIO ++ configure_GPIO (bmi_ov2640); ++ ++ // chip enable camera ++ enable_camera (bmi_ov2640); ++ ++ ov2640_patch (&bmi_ov2640->bdev->adap); ++ ++ //register with bug_camera ++ ++ //REWORK: check return code ++ register_bug_camera (&bmi_ov2640->bcam, slot); ++ ++ return 0; ++} ++ ++void bmi_ov2640_remove(struct bmi_device *bdev) ++{ ++ ++ //get our pointer ++ struct bmi_ov2640 *bmi_ov2640 = (struct bmi_ov2640*)(bmi_device_get_drvdata (bdev)); ++ int slot = bmi_device_get_slot (bdev); ++ ++ if (bdev == NULL) ++ { ++ printk(KERN_INFO "bmi_ov2640: bmi-ov2640_remove: NULL Pointer on bdev\n"); ++ return; ++ } ++ if (bmi_ov2640 == NULL) ++ { ++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: NULL Pointer on bmi_ov2640\n"); ++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: bdev->epid.vendor: 0x%x\n",bdev->epid.vendor); ++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: bdev->epid.product: 0x%x\n",bdev->epid.product); ++ printk(KERN_INFO "bmi_ov2640: bmi_ov2640_remove: bdev->epid.revision: 0x%x\n",bdev->epid.revision); ++ printk(KERN_INFO "bmi_ov3640: bmi_ov2640_remove: bmi_ov2640 pointer 0x%p \n",bdev->dev.driver_data); ++ return; ++ } ++ //unregister with bug_camera ++ unregister_bug_