diff -Naur linux-2.6.16.16/arch/arm/Kconfig h6300_dev/arch/arm/Kconfig --- linux-2.6.16.16/arch/arm/Kconfig 2006-05-17 21:41:27.000000000 +0300 +++ h6300_dev/arch/arm/Kconfig 2006-04-02 00:23:01.000000000 +0300 @@ -811,6 +811,8 @@ source "drivers/video/Kconfig" +source "drivers/telephony/Kconfig" + source "sound/Kconfig" source "drivers/usb/Kconfig" diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/board-h6300.c h6300_dev/arch/arm/mach-omap1/board-h6300.c --- linux-2.6.16.16/arch/arm/mach-omap1/board-h6300.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/arch/arm/mach-omap1/board-h6300.c 2006-04-24 20:53:29.000000000 +0300 @@ -0,0 +1,424 @@ +/* + * Modified from board-h6300.c + * + * Code for generic OMAP board. Should work on many OMAP systems where + * the device drivers take care of all the necessary hardware initialization. + * Do not put any board specific code to this file; create a new machine + * type if you need custom low-level initializations. + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define _h6300_KEY_CALENDAR 67 // xmodmap 75 aka F9 +#define _H6300_KEY_TELEPHONE 68 // xmodmap 76 aka F10 +#define _H6300_KEY_HOMEPAGE 87 // xmodmap 87 aka Num_Lock +#define _H6300_KEY_MAIL 88 // xmodmap 88 aka Scroll_Lock + +/* + * Following 5 keypad events are not really sent to userspace. + * Instead if the good combination of them is sent, then that is send. + * (up, right, down, left, enter) + */ +#define _H6300_JOYPAD_UP_RIGHT 1 // 00001 +#define _H6300_JOYPAD_DOWN_RIGHT 2 // 00010 +#define _h6300_JOYPAD_DOWN_LEFT 4 // 00100 +#define _h6300_JOYPAD_UP_LEFT 8 // 01000 +#define _H6300_JOYPAD_KEY_OK 16 // 10000 + +static int h6300_keymap[] = { + KEY(2, 0, _h6300_KEY_CALENDAR), // address button in the bottom left + KEY(2, 3, _H6300_KEY_TELEPHONE), // start call button in the bottom + KEY(3, 1, _H6300_KEY_HOMEPAGE), // stop call button in the bottom + KEY(3, 4, _H6300_KEY_MAIL), // messaging button in the bottom right + + KEY(0, 0, KEY_VOLUMEUP), // volume up button in the right side + KEY(0, 1, KEY_VOLUMEDOWN), // volume down button in the right side + KEY(3, 2, KEY_RECORD), // record button in the left side + + KEY(1, 0, _h6300_JOYPAD_UP_LEFT), + KEY(1, 1, _h6300_JOYPAD_DOWN_LEFT), + KEY(1, 2, _H6300_JOYPAD_KEY_OK), + KEY(1, 3, _H6300_JOYPAD_DOWN_RIGHT), + KEY(1, 4, _H6300_JOYPAD_UP_RIGHT), + + KEY(4, 0, KEY_RIGHT), + KEY(4, 1, KEY_DOWN), + KEY(4, 2, KEY_LEFT), + KEY(4, 3, KEY_UP), + KEY(4, 4, KEY_ENTER), + + 0 +}; + +/* + * Bluetooth - Relies on h6300_bt module, + * so make the calls indirectly through pointers. Requires that the + * h6300_bt bluetooth module be loaded before any attempt to use + * bluetooth (obviously). + */ + +static struct h6300_uart_funcs bt_funcs; +static struct h6300_uart_funcs gsm_funcs; + +static void h6300_bt_configure(struct uart_omap_port *up, int enable) +{ + printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() started\n"); + if (bt_funcs.configure != NULL) + bt_funcs.configure(up, enable); + printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() done\n"); +} + +static void h6300_bt_set_txrx(struct uart_omap_port *up, int txrx) +{ + printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() started\n"); + if (bt_funcs.set_txrx != NULL) + { + printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx(), bt_funcs.set_txrx != NULL\n"); + bt_funcs.set_txrx(up, txrx); + } + printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() done\n"); +} + +static int h6300_bt_get_txrx(struct uart_omap_port *up) +{ + int retVal; + + printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() started\n"); + if (bt_funcs.get_txrx != NULL) + { + retVal = bt_funcs.get_txrx(up); + printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal); + return retVal; + } + else + { + printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() done, returning 0\n"); + return 0; + } +} + +static struct platform_omap_serial_funcs h6300_omap_bt_funcs = { + .configure = h6300_bt_configure, + .set_txrx = h6300_bt_set_txrx, + .get_txrx = h6300_bt_get_txrx, +}; + +struct platform_device btuart_device = { + .name = "h6300_bt", + .id = 1, +}; +EXPORT_SYMBOL(btuart_device); + +static void h6300_gsm_configure(struct uart_omap_port *up, int enable) +{ + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() started\n"); + if (gsm_funcs.configure != NULL) + gsm_funcs.configure(up, enable); + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() done\n"); +} + +static void h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx) +{ + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() started\n"); + if (bt_funcs.set_txrx != NULL) + { + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx(), bt_funcs.set_txrx != NULL\n"); + gsm_funcs.set_txrx(up, txrx); + } + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() done\n"); +} + +static int h6300_gsm_get_txrx(struct uart_omap_port *up) +{ + int retVal; + + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() started\n"); + if (bt_funcs.get_txrx != NULL) + { + retVal = gsm_funcs.get_txrx(up); + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal); + return retVal; + } + else + { + printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() done, returning 0\n"); + return 0; + } +} + +static struct platform_omap_serial_funcs h6300_omap_gsm_funcs = { + .configure = h6300_gsm_configure, + .set_txrx = h6300_gsm_set_txrx, + .get_txrx = h6300_gsm_get_txrx, +}; + +struct platform_device gsmuart_device = { + .name = "h6300_gsm", + .id = 1, +}; +EXPORT_SYMBOL(gsmuart_device); + +#if 0 +static struct mtd_partition h6300_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = 0, + }, + /* kernel */ + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0 + }, + /* rest of flash1 is a file system */ + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M - SZ_2M - 2 * SZ_128K, + .mask_flags = 0 + }, + /* file system */ + { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0 + } +}; + +static struct flash_platform_data h6300_flash_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = h6300_partitions, + .nr_parts = ARRAY_SIZE(h6300_partitions), +}; + +static struct resource h6300_flash_resource = { + .start = OMAP_CS0_PHYS, + .end = OMAP_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device h6300_flash_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &h6300_flash_data, + }, +static struct platform_device h6300_flash_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &h6300_flash_data, + }, + .num_resources = 1, + .resource = &h6300_flash_resource, +}; +#endif + +static struct resource h6300_kp_resources[] = { + [0] = { + .start = INT_KEYBOARD, + .end = INT_KEYBOARD, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct omap_kp_platform_data h6300_kp_data = { + .rows = 8, + .cols = 8, + .keymap = h6300_keymap, + .rep = 1, // turns repeat bit on +}; + +static struct platform_device h6300_kp_device = { + .name = "omap-keypad", + .id = -1, + .dev = { + .platform_data = &h6300_kp_data, + }, + .num_resources = ARRAY_SIZE(h6300_kp_resources), + .resource = h6300_kp_resources, +}; + +static struct resource h6300_wlan_resource[] = { + [0] = { + .start = OMAP_CS1_PHYS, + .end = OMAP_CS1_PHYS + SZ_32M -1, + .flags = IORESOURCE_MEM, + }, + + [1] = { + .start = OMAP_GPIO_IRQ(11), + .end = OMAP_GPIO_IRQ(11), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device h6300_wlan_device = { + .name = "tnetw1100b", + .id = 0, + .num_resources = 2, + .resource = h6300_wlan_resource, +}; + +static struct omap_mcbsp_reg_cfg mcbsp_regs = { + .spcr2 = 0x0000, + .spcr1 = 0x0000, + .rcr2 = 0x8041, + .rcr1 = 0x0040, + .xcr2 = 0x00a1, + .xcr1 = 0x00a0, + .srgr2 = 0xb000, + .srgr1 = 0x0000, + .pcr0 = 0x0081, +}; + +static struct omap_alsa_codec_config alsa_config = { + .name = "iPAQ h6300 TSC2101", + .mcbsp_regs_alsa = &mcbsp_regs, + .codec_configure_dev = NULL, //tsc2101_configure, + .codec_set_samplerate = NULL, //tsc2101_set_samplerate, + .codec_clock_setup = NULL, //tsc2101_clock_setup, + .codec_clock_on = NULL, //tsc2101_clock_on, + .codec_clock_off = NULL, //tsc2101_clock_off, + .get_default_samplerate = NULL, //tsc2101_get_default_samplerate, +}; + +static struct platform_device h6300_mcbsp1_device = { + .name = "omap_alsa_mcbsp", + .id = 1, + .dev = { + .platform_data = &alsa_config, + }, +}; + +static struct platform_device h6300_lcd_device = { + .name = "lcd_h6300", + .id = -1, +}; + +static struct platform_device *h6300_devices[] __initdata = { + &h6300_lcd_device, + &btuart_device, + &gsmuart_device, + &h6300_kp_device, + &h6300_mcbsp1_device, + &h6300_wlan_device, + //&h6300_flash_device, +}; + +static void __init h6300_init_irq(void) +{ + omap1_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); + + /* this is now done in the drivers/input/touschreen/omap/ts_hx.c*/ + //omap_request_gpio(2); + //omap_set_gpio_direction(2, 0); + //omap_set_gpio_dataout(2, 1); +} + +/* assume no Mini-AB port */ + +static struct omap_usb_config h6300_usb_config __initdata = { + .hmc_mode = 0, + .register_dev = 1, + .pins[0] = 0, +}; + +static struct omap_lcd_config h6300_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_mmc_config h6300_mmc_config __initdata = { + .mmc [0] = { + .enabled = 1, + .wire4 = 1, + .wp_pin = OMAP_GPIO_IRQ(13), + .power_pin = -1, // tps65010 ? + .switch_pin = -1, // OMAP_MPUIO(1), // = -1, // ARMIO2? + }, +}; + +static struct omap_uart_config h6300_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static struct omap_board_config_kernel h6300_config[] = { + { OMAP_TAG_USB, &h6300_usb_config }, + { OMAP_TAG_MMC, &h6300_mmc_config }, + { OMAP_TAG_UART, &h6300_uart_config }, + { OMAP_TAG_LCD, &h6300_lcd_config }, +}; + +static void __init h6300_init(void) +{ + int ret; + + ret = platform_add_devices(h6300_devices, ARRAY_SIZE(h6300_devices)); + if (ret) + { + printk(KERN_WARNING "Unable to add h6300 platform devices like bluetooth"); + } + omap_board_config = h6300_config; + omap_board_config_size = ARRAY_SIZE(h6300_config); + omap_serial_init(); +} + +static void __init h6300_map_io(void) +{ + omap1_map_common_io(); + + btuart_device.dev.platform_data = &h6300_omap_bt_funcs; + gsmuart_device.dev.platform_data = &h6300_omap_gsm_funcs; +} + +MACHINE_START(OMAP_H6300, "HP iPAQ h6300") + /* MAINTAINER("Everett Coleman II ") */ + .phys_io = 0xfff00000, + .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, + .boot_params = 0x10000100, + .map_io = h6300_map_io, + .init_irq = h6300_init_irq, + .init_machine = h6300_init, + .timer = &omap_timer, +MACHINE_END diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/Kconfig h6300_dev/arch/arm/mach-omap1/Kconfig --- linux-2.6.16.16/arch/arm/mach-omap1/Kconfig 2006-05-17 21:41:27.000000000 +0300 +++ h6300_dev/arch/arm/mach-omap1/Kconfig 2006-04-02 20:47:24.000000000 +0300 @@ -26,6 +26,15 @@ TI OMAP 1510 or 1610 Innovator board support. Say Y here if you have such a board. +config MACH_OMAP_H6300 + bool "HP iPAQ h6300 series" + depends on ARCH_OMAP1 && ARCH_OMAP15XX + select I2C + select PCA9535 + help + HP iPAQ h6315, h6340 and h6365 devices that are based + on the OMAP 1510. Say Y here if you have such a device. + config MACH_OMAP_H2 bool "TI H2 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/Makefile h6300_dev/arch/arm/mach-omap1/Makefile --- linux-2.6.16.16/arch/arm/mach-omap1/Makefile 2006-05-17 21:41:28.000000000 +0300 +++ h6300_dev/arch/arm/mach-omap1/Makefile 2006-04-02 00:23:01.000000000 +0300 @@ -23,6 +23,7 @@ obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o +obj-$(CONFIG_MACH_OMAP_H6300) += board-h6300.o ifeq ($(CONFIG_ARCH_OMAP15XX),y) # Innovator-1510 FPGA @@ -36,4 +37,3 @@ led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o obj-$(CONFIG_LEDS) += $(led-y) - diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/mux.c h6300_dev/arch/arm/mach-omap1/mux.c --- linux-2.6.16.16/arch/arm/mach-omap1/mux.c 2006-05-17 21:41:28.000000000 +0300 +++ h6300_dev/arch/arm/mach-omap1/mux.c 2006-02-21 23:54:33.000000000 +0200 @@ -200,6 +200,13 @@ MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1) MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1) +/* OMAP-1510 uWire */ +MUX_CFG("P15_1510_UWIRE_CS3", 8, 12, 1, NA, 0, 0, NA, 0, 1) +MUX_CFG("N14_1510_UWIRE_CS0", 8, 9, 1, NA, 0, 0, NA, 0, 1) +MUX_CFG("V19_1510_UWIRE_SCLK", 8, 6, 0, NA, 0, 0, NA, 0, 1) +MUX_CFG("W21_1510_UWIRE_SDO", 8, 3, 0, NA, 0, 0, NA, 0, 1) +MUX_CFG("U18_1510_UWIRE_SDI", 8, 0, 0, 1, 18, 0, NA, 0, 1) + /* OMAP-1610 Flash */ MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1) MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1) @@ -262,6 +269,7 @@ MUX_CFG("T20_1610_LOW_PWR", 7, 12, 1, NA, 0, 0, NA, 0, 0) /* MCLK Settings */ +MUX_CFG("R10_1510_MCLK_ON", B, 18, 0, 2, 22, 1, NA, 1, 1) MUX_CFG("V5_1710_MCLK_ON", B, 15, 0, NA, 0, 0, NA, 0, 0) MUX_CFG("V5_1710_MCLK_OFF", B, 15, 6, NA, 0, 0, NA, 0, 0) MUX_CFG("R10_1610_MCLK_ON", B, 18, 0, NA, 22, 0, NA, 1, 0) diff -Naur linux-2.6.16.16/arch/arm/plat-omap/devices.c h6300_dev/arch/arm/plat-omap/devices.c --- linux-2.6.16.16/arch/arm/plat-omap/devices.c 2006-05-17 21:41:28.000000000 +0300 +++ h6300_dev/arch/arm/plat-omap/devices.c 2006-05-18 00:59:02.000000000 +0300 @@ -92,7 +92,7 @@ static void omap_init_kp(void) { - if (machine_is_omap_h2() || machine_is_omap_h3()) { + if (machine_is_omap_h2() || machine_is_omap_h3() || machine_is_omap_h6300()) { omap_cfg_reg(F18_1610_KBC0); omap_cfg_reg(D20_1610_KBC1); omap_cfg_reg(D19_1610_KBC2); diff -Naur linux-2.6.16.16/arch/arm/plat-omap/dma.c h6300_dev/arch/arm/plat-omap/dma.c --- linux-2.6.16.16/arch/arm/plat-omap/dma.c 2006-05-17 21:41:28.000000000 +0300 +++ h6300_dev/arch/arm/plat-omap/dma.c 2006-02-06 15:36:21.000000000 +0200 @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -1086,6 +1087,10 @@ } if (omap_dma_in_1510_mode()) { + u16 l = omap_readw(OMAP1510_DMA_LCD_CTRL); + l &= ~(1 << 6); + omap_writew (l, OMAP1510_DMA_LCD_CTRL); + omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); diff -Naur linux-2.6.16.16/arch/arm/tools/mach-types h6300_dev/arch/arm/tools/mach-types --- linux-2.6.16.16/arch/arm/tools/mach-types 2006-05-11 04:56:24.000000000 +0300 +++ h6300_dev/arch/arm/tools/mach-types 2006-04-24 20:53:29.000000000 +0300 @@ -576,7 +576,7 @@ s3c2460 MACH_S3C2460 S3C2460 560 pdm MACH_PDM PDM 561 h4700 MACH_H4700 H4700 562 -h6300 MACH_H6300 H6300 563 +omap_h6300 MACH_OMAP_H6300 OMAP_H6300 563 rz1700 MACH_RZ1700 RZ1700 564 a716 MACH_A716 A716 565 estk2440a MACH_ESTK2440A ESTK2440A 566 diff -Naur linux-2.6.16.16/drivers/bluetooth/Kconfig h6300_dev/drivers/bluetooth/Kconfig --- linux-2.6.16.16/drivers/bluetooth/Kconfig 2006-05-17 21:41:29.000000000 +0300 +++ h6300_dev/drivers/bluetooth/Kconfig 2006-02-21 23:54:33.000000000 +0200 @@ -166,6 +166,16 @@ Say Y here to compile support for virtual HCI devices into the kernel or say M to compile it as module (hci_vhci). + +config BT_H6300 + tristate "H6300 BRF6100 BT DRIVER" + help + Bluetooth H6300 BRF6100 driver. + This driver provides the firmware loading mechanism for the BRF6100 + bt hardware in iPAQ h6300. + + Say Y here to compile support for BRF6100 BT devices into the + kernel or say M to compile it as module (h6300_BT). endmenu diff -Naur linux-2.6.16.16/drivers/bluetooth/Makefile h6300_dev/drivers/bluetooth/Makefile --- linux-2.6.16.16/drivers/bluetooth/Makefile 2006-05-17 21:41:29.000000000 +0300 +++ h6300_dev/drivers/bluetooth/Makefile 2006-02-21 23:54:33.000000000 +0200 @@ -13,6 +13,7 @@ obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o obj-$(CONFIG_BT_HCIBRF6150) += brf6150.o +obj-$(CONFIG_BT_H6300) += omap/ hci_uart-y := hci_ldisc.o hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_brf6100.c h6300_dev/drivers/bluetooth/omap/h6300_bt_brf6100.c --- linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_brf6100.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/bluetooth/omap/h6300_bt_brf6100.c 2006-01-23 00:09:23.000000000 +0200 @@ -0,0 +1,154 @@ +/* + * Bluetooth interface driver for TI BRF6100 on h6300 + * + * Copyright (C) 2005 Mika Laitio + * Ideas taken from the brf6150 bt driver made by Todd Blumer for the pxa hx4700. + * + * 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 +#include +#include +#include + +#include +#include + +#include +#include "h6300_bt_led.h" + +static void +h6300_bt_configure(struct uart_omap_port *up, int enable) +{ + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable); + + // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable ); + if (enable == 0) { + omap_set_gpio_dataout(GPIO_N_BT_RST, 1); // turn off gpio, note 1 == off for negative gpios + mdelay(5); + h6300_clear_led(INDEX_BT_LED); + } + else if (enable == 1) { + omap_set_gpio_dataout(GPIO_N_BT_RST, 1); // turn on gpio, note 0 == on for negative gpios + mdelay(5); + } + else if (enable == 2) { + /* + * BRF6150's RTS goes low when firmware is ready + * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms + */ +/* + int tries = 0; + do + { + mdelay(10); + } + while ((BTMSR & MSR_CTS) == 0 && tries++ < 50); +*/ + h6300_set_led(INDEX_BT_LED, 16, 16); + } + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n"); +} + +static void +h6300_bt_set_txrx(struct uart_omap_port *up, int txrx) +{ + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx); + /* do nothing */ +} + +static int +h6300_bt_get_txrx(struct uart_omap_port *up) +{ + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n"); + /* do nothing */ + return 0; +} + +static int +h6300_bt_probe(struct platform_device *pdev) +{ + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data; + + omap_request_gpio(GPIO_BT_PWR_EN); // ask bt_power_en gpio, remember to release in remove_function + omap_set_gpio_direction(GPIO_BT_PWR_EN, 1); // set gpio direction to be output + omap_set_gpio_dataout(GPIO_BT_PWR_EN, 1); // turn on gpio + + mdelay(200); + + omap_request_gpio(GPIO_N_BT_RST); // ask bt_reset gpio, remember to release in remove_function + omap_set_gpio_direction(GPIO_N_BT_RST, 1); // set gpio direction to be output + omap_set_gpio_dataout(GPIO_N_BT_RST, 0); // turn on gpio, note 0 == on for negative gpios + + /* configure bluetooth UART */ + //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD); + + funcs->configure = h6300_bt_configure; + funcs->set_txrx = h6300_bt_set_txrx; + funcs->get_txrx = h6300_bt_get_txrx; + + /* Make sure the LED is off */ + h6300_clear_led(INDEX_BT_LED); + + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n"); + + return 0; +} + +static int +h6300_bt_remove(struct platform_device *pdev) +{ + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data; + + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n"); + + omap_free_gpio(GPIO_BT_PWR_EN); + omap_free_gpio(GPIO_N_BT_RST); + + funcs->configure = NULL; + funcs->set_txrx = NULL; + funcs->get_txrx = NULL; + + /* Make sure the LED is off */ + h6300_clear_led(INDEX_BT_LED); + + printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n"); + + return 0; +} + +static struct platform_driver bt_driver = { + .probe = h6300_bt_probe, + .remove = h6300_bt_remove, + .driver = { + .name = "h6300_bt", + }, +}; + +static int __init +h6300_bt_init(void) +{ + printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n"); + return platform_driver_register(&bt_driver); +} + +static void __exit +h6300_bt_exit(void) +{ + printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n"); + platform_driver_unregister(&bt_driver); +} + +module_init(h6300_bt_init); +module_exit(h6300_bt_exit); + +MODULE_AUTHOR("Mika Laitio, "); +MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver."); +MODULE_LICENSE("GPL"); + diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.c h6300_dev/drivers/bluetooth/omap/h6300_bt_led.c --- linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/bluetooth/omap/h6300_bt_led.c 2005-10-06 02:34:39.000000000 +0300 @@ -0,0 +1,41 @@ +/* + * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300. + * + * Copyright (C) 2005 Mika Laitio + * Ideas from the brf6150 bt driver made by Todd Blumer for the pxa hx4700. + * + * 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 +#include +#include +#include + +#include +#include + +/* + * Low level access for disabling h6300 bt led. + * + * TODO: implement for h6300 + */ +void h6300_clear_led(int led_num) +{ + printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n"); + //hx4700_set_led(led_num, 0, 16); +} +EXPORT_SYMBOL(h6300_clear_led); + +/* + * Low level access for setting up the bt led. + * + * TODO: implement for h6300 + */ +void h6300_set_led(int led_num, int duty_time, int cycle_time) +{ + printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n"); +} +EXPORT_SYMBOL(h6300_set_led); diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.h h6300_dev/drivers/bluetooth/omap/h6300_bt_led.h --- linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.h 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/bluetooth/omap/h6300_bt_led.h 2005-10-06 02:34:39.000000000 +0300 @@ -0,0 +1,9 @@ +#ifndef H6300_BT_LED_H_ +#define H6300_BT_LED_H_ + +#define INDEX_BT_LED 2 + +void h6300_clear_led(int led_num); +void h6300_set_led(int led_num, int duty_time, int cycle_time); + +#endif /*H6300_BT_LED_H_*/ diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/Makefile h6300_dev/drivers/bluetooth/omap/Makefile --- linux-2.6.16.16/drivers/bluetooth/omap/Makefile 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/bluetooth/omap/Makefile 2005-10-06 02:34:39.000000000 +0300 @@ -0,0 +1,6 @@ +# +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers. +# + +h6300_bt-objs := h6300_bt_led.o h6300_bt_brf6100.o +obj-$(CONFIG_BT_H6300) += h6300_bt.o diff -Naur linux-2.6.16.16/drivers/i2c/busses/i2c-omap.c h6300_dev/drivers/i2c/busses/i2c-omap.c --- linux-2.6.16.16/drivers/i2c/busses/i2c-omap.c 2006-05-17 21:41:29.000000000 +0300 +++ h6300_dev/drivers/i2c/busses/i2c-omap.c 2006-04-02 00:23:01.000000000 +0300 @@ -163,17 +163,22 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev) { - if (cpu_is_omap16xx() || cpu_is_omap24xx()) { + if (cpu_is_omap24xx()) { dev->iclk = clk_get(dev->dev, "i2c_ick"); - if (IS_ERR(dev->iclk)) + if (IS_ERR(dev->iclk)) { return -ENODEV; + } + dev->fclk = clk_get(dev->dev, "i2c_fck"); + if (IS_ERR(dev->fclk)) { + clk_put(dev->fclk); + return -ENODEV; + } } - dev->fclk = clk_get(dev->dev, "i2c_fck"); - if (IS_ERR(dev->fclk)) { - if (dev->iclk != NULL) - clk_put(dev->iclk); - return -ENODEV; + if (cpu_class_is_omap1()) { + dev->fclk = clk_get(dev->dev, "i2c_fck"); + if (IS_ERR(dev->fclk)) + return -ENODEV; } return 0; diff -Naur linux-2.6.16.16/drivers/i2c/chips/Kconfig h6300_dev/drivers/i2c/chips/Kconfig --- linux-2.6.16.16/drivers/i2c/chips/Kconfig 2006-05-17 21:41:29.000000000 +0300 +++ h6300_dev/drivers/i2c/chips/Kconfig 2006-04-24 20:53:29.000000000 +0300 @@ -46,6 +46,16 @@ This driver can also be built as a module. If so, the module will be called pcf8574. +config PCA9535 + tristate "Philips PCA9535 16-bit I/O port" + depends on I2C + help + If you say yes here you get support for the Philips PCA9535 + 16-bit I/O port. + + This driver can also be built as a module. If so, the module + will be called pca9535. + config SENSORS_PCA9539 tristate "Philips PCA9539 16-bit I/O port" depends on I2C && EXPERIMENTAL diff -Naur linux-2.6.16.16/drivers/i2c/chips/Makefile h6300_dev/drivers/i2c/chips/Makefile --- linux-2.6.16.16/drivers/i2c/chips/Makefile 2006-05-17 21:41:29.000000000 +0300 +++ h6300_dev/drivers/i2c/chips/Makefile 2006-04-24 20:53:29.000000000 +0300 @@ -7,6 +7,7 @@ obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_M41T00) += m41t00.o +obj-$(CONFIG_PCA9535) += pca9535.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o diff -Naur linux-2.6.16.16/drivers/i2c/chips/pca9535.c h6300_dev/drivers/i2c/chips/pca9535.c --- linux-2.6.16.16/drivers/i2c/chips/pca9535.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/i2c/chips/pca9535.c 2006-04-24 20:53:29.000000000 +0300 @@ -0,0 +1,412 @@ +/* + Driver for Philips PCA9535 16-bit low power I/O port with interrupt + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + Copyright (C) 2005 Husam Senussi + Framework based on Pawel Kolodziejski's pca9535 driver in + handheld.org's 2.6.13 kernel. Driver updated by Mika Laitio. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +EXPORT_SYMBOL(pca9535_gpio_read); +EXPORT_SYMBOL(pca9535_gpio_write); +EXPORT_SYMBOL(pca9535_gpio_direction); + +static int pca9535_attach_adapter(struct i2c_adapter *adapter); +static int pca9535_detach_client(struct i2c_client *client); +static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one); +static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr); +static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 param); + +enum pca9535_cmd +{ + PCA9535_INPUT_0 = 0, + PCA9535_INPUT_1 = 1, + PCA9535_OUTPUT_0 = 2, + PCA9535_OUTPUT_1 = 3, + PCA9535_INVERT_0 = 4, + PCA9535_INVERT_1 = 5, + PCA9535_DIRECTION_0 = 6, + PCA9535_DIRECTION_1 = 7, +}; + +struct pca9535_data { + struct semaphore lock; + struct i2c_client client; +}; + +static struct i2c_driver pca9535_driver = { + .driver = { + .name = "pca9535", + }, + .attach_adapter = pca9535_attach_adapter, + .detach_client = pca9535_detach_client, +}; + +static struct i2c_client *pca9535_i2c_client = NULL; +static struct pca9535_data pca9535_inited; + +static unsigned short normal_i2c[] = { 0x20, I2C_CLIENT_END }; + +#define DRIVER_VERSION "20 OCT 2005" +#define DRIVER_NAME "PCA9535" + +/* + * sysfs callback function. + */ +static ssize_t pca9535_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + return sprintf(buf, "%02X\n", (pca9535_read_reg(client, psa->index) >> 8)); +} + +/* + * sysfs callback function. + */ +static ssize_t pca9535_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + unsigned long val = simple_strtoul(buf, NULL, 0); + unsigned long old = pca9535_read_reg(client, psa->index); + + if (val > 0xff) + return -EINVAL; + + val = (old & 0xff) | (val << 8); + pca9535_write_reg(client, psa->index, val); + return count; +} + +#define PCA9535_ENTRY_RO(name, cmd_idx) \ + static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9535_show, NULL, cmd_idx) + +#define PCA9535_ENTRY_RW(name, cmd_idx) \ + static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9535_show, \ + pca9535_store, cmd_idx) + +PCA9535_ENTRY_RO(input0, PCA9535_INPUT_0); +PCA9535_ENTRY_RO(input1, PCA9535_INPUT_1); +PCA9535_ENTRY_RW(output0, PCA9535_OUTPUT_0); +PCA9535_ENTRY_RW(output1, PCA9535_OUTPUT_1); +PCA9535_ENTRY_RW(invert0, PCA9535_INVERT_0); +PCA9535_ENTRY_RW(invert1, PCA9535_INVERT_1); +PCA9535_ENTRY_RW(direction0, PCA9535_DIRECTION_0); +PCA9535_ENTRY_RW(direction1, PCA9535_DIRECTION_1); + +static struct attribute *pca9535_attributes[] = { + &sensor_dev_attr_input0.dev_attr.attr, + &sensor_dev_attr_input1.dev_attr.attr, + &sensor_dev_attr_output0.dev_attr.attr, + &sensor_dev_attr_output1.dev_attr.attr, + &sensor_dev_attr_invert0.dev_attr.attr, + &sensor_dev_attr_invert1.dev_attr.attr, + &sensor_dev_attr_direction0.dev_attr.attr, + &sensor_dev_attr_direction1.dev_attr.attr, + NULL +}; + +static struct attribute_group pca9535_defattr_group = { + .attrs = pca9535_attributes, +}; +//End of sysfs management code. + +I2C_CLIENT_INSMOD; + +u32 pca9535_read_input(void) +{ + return pca9535_read_reg(pca9535_i2c_client, 0); +} +EXPORT_SYMBOL(pca9535_read_input); + +void pca9535_write_output(u16 param) +{ + pca9535_write_reg(pca9535_i2c_client, 2, param); +} +EXPORT_SYMBOL(pca9535_write_output); + +void pca9535_set_dir(u16 param) +{ + pca9535_write_reg(pca9535_i2c_client, 6, param); +} +EXPORT_SYMBOL(pca9535_set_dir); + +static int pca9535_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, pca9535_attach); +} + +static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one) +{ + struct i2c_client *new_client; + int err = 0; + + new_client = &(pca9535_inited.client); + i2c_set_clientdata(new_client, 0); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &pca9535_driver; + strcpy(new_client->name, DRIVER_NAME); + + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + pca9535_i2c_client = new_client; + + init_MUTEX(&pca9535_inited.lock); + i2c_set_clientdata(pca9535_i2c_client, &pca9535_inited); + + sysfs_create_group(&pca9535_i2c_client->dev.kobj, &pca9535_defattr_group); + + printk("pca9535_attach() ok, address = %d, zero_or_minus_one = %d\n", address, zero_or_minus_one); + return 0; + +exit_free: + printk("pca9535_attach() failed, error code = %d\n", err); + return err; +} + +static int pca9535_detach_client(struct i2c_client *client) +{ + int err; + + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, "Client deregistration failed, client not detached.\n"); + return err; + } + pca9535_i2c_client = NULL; + + return 0; +} + +static int __init pca9535_init(void) +{ + return i2c_add_driver(&pca9535_driver); +} + +static void __exit pca9535_exit(void) +{ + i2c_del_driver(&pca9535_driver); +} + +/* + * Reads the value of GPIO available via I2C. + */ +int pca9535_gpio_read(int gpio){ + unsigned char reg = 0; + unsigned long val = 0; + + printk("9535_gpio_read() called\n"); + if(!pca9535_i2c_client) + return -ENODEV; + + if(gpio < GPIO0 || gpio > GPIO17) + return -EINVAL; + + if(gpio >= GPIO0 && gpio <= GPIO7){ + reg = PCA9535_INPUT_0; + gpio -= GPIO0; + }else if(gpio >= GPIO8 && gpio <= GPIO17){ + reg = PCA9535_INPUT_1; + gpio -= GPIO8; + } + + down(&pca9535_inited.lock); + + // Read the existing values first + val = pca9535_read_reg(pca9535_i2c_client, reg) >> 8; + val = (val >> gpio) & 0x01; + + up(&pca9535_inited.lock); + + return val; +} + +/* + * Set the value of I2C GPIO. + */ +int pca9535_gpio_write(int gpio, unsigned char value){ + unsigned char in_reg = 0; + unsigned char out_reg = 0; + unsigned long val = 0; + unsigned long old = 0; + int ret = 0; + + if(!pca9535_i2c_client) + return -ENODEV; + + if(gpio < GPIO0 || gpio > GPIO17) + return -EINVAL; + + if(gpio >= GPIO0 && gpio <= GPIO7){ + in_reg = PCA9535_INPUT_0; + out_reg = PCA9535_OUTPUT_0; + gpio -= GPIO0; + }else if(gpio >= GPIO8 && gpio <= GPIO17){ + in_reg = PCA9535_INPUT_1; + out_reg = PCA9535_OUTPUT_1; + gpio -= GPIO8; + } + + down(&pca9535_inited.lock); + + // Read the existing values first + val = pca9535_read_reg(pca9535_i2c_client, in_reg); + old = val >> 8; + + switch(value){ + case LOW: + old |= (1 << gpio); + break; + case HI: + old &= ~(1 << gpio); + break; + default: + ret = -EINVAL; + goto error; + } + + val = (val & 0xff) | (old << 8); + + // write the values back to the register + pca9535_write_reg(pca9535_i2c_client, out_reg, val); +error: + + up(&pca9535_inited.lock); + return ret; +} + +/* + * Set the direction of I2C GPIO. + */ +int pca9535_gpio_direction(int gpio, unsigned char direction){ + unsigned char reg = 0; + unsigned long val = 0; + unsigned long old = 0; + int ret = 0; + + if(!pca9535_i2c_client) + return -ENODEV; + + if(gpio < GPIO0 || gpio > GPIO17) + return -EINVAL; + + if(gpio >= GPIO0 && gpio <= GPIO7){ + reg = PCA9535_DIRECTION_0; + gpio -= GPIO0; + }else if(gpio >= GPIO8 && gpio <= GPIO17){ + reg = PCA9535_DIRECTION_1; + gpio -= GPIO8; + } + + down(&pca9535_inited.lock); + + // Read the existing values first + old = pca9535_read_reg(pca9535_i2c_client, reg); + val = old >> 8; + + switch(direction){ + case GPIO_INPUT: + val |= (1 << gpio); + break; + case GPIO_OUTPUT: + val &= ~(1 << gpio); + break; + default: + ret = -EINVAL; + goto error; + } + + val = (old & 0xff) | (val << 8); + + // write the values back to the register + pca9535_write_reg(pca9535_i2c_client, reg, val); +error: + + up(&pca9535_inited.lock); + return ret; +} + +static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr) +{ + char buffer[3]; + int r; + u32 data; + + buffer[0] = regaddr; + buffer[1] = 0; + buffer[2] = 0; + + r = i2c_master_send(client, buffer, 1); + if (r != 1) { + printk(KERN_ERR "pca9535: read failed, status %d\n", r); + return 0xffffffff; + } + + r = i2c_master_recv(client, buffer, 3); + if (r != 3) { + printk(KERN_ERR "pca9535: read failed, status %d\n", r); + return 0xffffffff; + } + + data = buffer[1]; + data |= buffer[2] << 8; + //printk(KERN_ERR "%s: reading %x in %x\n", __FUNCTION__, data, regaddr); + + return data; +} + +static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 data) +{ + char buffer[3]; + int r; + + //printk(KERN_ERR "%s: writing %x in %x\n", __FUNCTION__, data, regaddr); + buffer[0] = regaddr; + buffer[1] = data >> 8; + buffer[2] = data & 0xff; + + r = i2c_master_send(client, buffer, 3); + if (r != 3) { + printk(KERN_ERR "pca9535: write failed, status %d\n", r); + } +} + +MODULE_AUTHOR("Husam Senussi "); +MODULE_DESCRIPTION("PCA9535 driver"); +MODULE_LICENSE("GPL"); + +module_init(pca9535_init); +module_exit(pca9535_exit); diff -Naur linux-2.6.16.16/drivers/input/keyboard/omap-keypad.c h6300_dev/drivers/input/keyboard/omap-keypad.c --- linux-2.6.16.16/drivers/input/keyboard/omap-keypad.c 2006-05-17 21:41:29.000000000 +0300 +++ h6300_dev/drivers/input/keyboard/omap-keypad.c 2006-04-24 20:53:29.000000000 +0300 @@ -4,11 +4,12 @@ * OMAP Keypad Driver * * Copyright (C) 2003 Nokia Corporation - * Written by Timo Teräs + * Written by Timo Ter�s + * iPAQ h6300 key and joypad support added by Mika Laitio. (2005) * * Added support for H2 & H3 Keypad * Copyright (C) 2004 Texas Instruments - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -44,6 +45,19 @@ #include #undef NEW_BOARD_LEARNING_MODE +//#define NEW_BOARD_LEARNING_MODE 1 + +/* + * Following 5 keypad events are not really sent to userspace. + * Instead if the good combination of them is sent, then that is send. + * (up, right, down, left, enter) + */ +#define _H6300_JOYPAD_UP_RIGHT 1 // 00001 +#define _H6300_JOYPAD_DOWN_RIGHT 2 // 00010 +#define _h6300_JOYPAD_DOWN_LEFT 4 // 00100 +#define _h6300_JOYPAD_UP_LEFT 8 // 01000 +#define _H6300_JOYPAD_KEY_OK 16 // 10000 +#define _H6300_JOYPAD_REPORT_COLUMN 4 static void omap_kp_tasklet(unsigned long); static void omap_kp_timer(unsigned long); @@ -53,6 +67,8 @@ static int kp_enable = 1; static int kp_cur_group = -1; +static int prevJoypadKeycodePressEmulated; + struct omap_kp { struct input_dev *input; struct timer_list timer; @@ -139,7 +155,7 @@ for (col = 0; col < omap_kp->cols; col++) { omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC); - if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()) { + if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3() || machine_is_omap_h6300()) { udelay(9); } else { udelay(4); @@ -169,17 +185,26 @@ return -1; } +int is_key_down(unsigned char new_state[], + int col, + int row) +{ + return (new_state[col] & (1 << row)) ? 1 : 0; +} + static void omap_kp_tasklet(unsigned long data) { struct omap_kp *omap_kp_data = (struct omap_kp *) data; unsigned char new_state[8], changed, key_down = 0; int col, row; int spurious = 0; + int report_key, report_col, report_row, joypad_checked; // h6300-joypad specific variables /* check for any changes */ omap_kp_scan_keypad(omap_kp_data, new_state); /* check for changes and print those */ + joypad_checked = 0; for (col = 0; col < omap_kp_data->cols; col++) { changed = new_state[col] ^ keypad_state[col]; key_down |= new_state[col]; @@ -201,14 +226,177 @@ spurious = 1; continue; } - - if (!(kp_cur_group == (key & GROUP_MASK) || - kp_cur_group == -1)) - continue; - - kp_cur_group = key & GROUP_MASK; - input_report_key(omap_kp_data->input, key & ~GROUP_MASK, - !!(new_state[col] & (1 << row))); + if (machine_is_omap_h6300() && + ((col == 1) || (col == _H6300_JOYPAD_REPORT_COLUMN))) + { + if (col == _H6300_JOYPAD_REPORT_COLUMN) + { + continue; + } + if ((joypad_checked == 0) && + ((key == _H6300_JOYPAD_KEY_OK) || + (key == _h6300_JOYPAD_UP_LEFT) || + (key == _H6300_JOYPAD_UP_RIGHT) || + (key == _H6300_JOYPAD_DOWN_RIGHT) || + (key == _h6300_JOYPAD_DOWN_LEFT))) + { + if (is_key_down(new_state, col, row)) + { + /* + * only enter pressed + * 1 0 0 _H6300_JOYPAD_KEY_OK 0 0 + * --> 100100 == 36 + */ + if (new_state[1] == 36) + { + joypad_checked = 1; + prevJoypadKeycodePressEmulated = KEY_ENTER; + new_state[_H6300_JOYPAD_REPORT_COLUMN] = 48; //110000 + report_key = prevJoypadKeycodePressEmulated; + report_col = _H6300_JOYPAD_REPORT_COLUMN; + report_row = 4; + input_report_key(omap_kp_data->input, + report_key, + new_state[report_col] & (1 << report_row)); + } + /* + * enter, up_left and up_right sensors pressed. + * 1 _H6300_JOYPAD_UP_RIGHT 0 _H6300_JOYPAD_KEY_OK 0 _h6300_JOYPAD_UP_LEFT + * --> 110101 == 53 + * OR + * 1 KEY_UP_RIGHT 0 0 0 _h6300_JOYPAD_UP_LEFT + * --> 110001 == 42 + * --> move to up + */ + else if ((new_state[1] == 53) || + (new_state[1] == 49)) + { + joypad_checked = 1; + prevJoypadKeycodePressEmulated = KEY_UP; + new_state[_H6300_JOYPAD_REPORT_COLUMN] = 40; //101000 + report_key = prevJoypadKeycodePressEmulated; + report_col = _H6300_JOYPAD_REPORT_COLUMN; + report_row = 3; + input_report_key(omap_kp_data->input, + report_key, + new_state[report_col] & (1 << report_row)); + } + /* + * enter, down_left and down_right sensors pressed + * --> 101110 == 46 + * OR + * down_left and down_right + * -->101010 == 42 + * --> move to down + */ + else if ((new_state[1] == 46) || + (new_state[1] == 42)) + { + joypad_checked = 1; + prevJoypadKeycodePressEmulated = KEY_DOWN; + new_state[_H6300_JOYPAD_REPORT_COLUMN] = 34; //100010 + report_key = prevJoypadKeycodePressEmulated; + report_col = _H6300_JOYPAD_REPORT_COLUMN; + report_row = 1; + input_report_key(omap_kp_data->input, + report_key, + new_state[report_col] & (1 << report_row)); + } + /* + * enter, up_right and down_right sensors pressed + * --> 111100 == 60 + * or + * down_right and up_right + * --> 111000 == 56 + * --> move to right + */ + else if ((new_state[1] == 60) || + (new_state[1] == 56)) + { + joypad_checked = 1; + prevJoypadKeycodePressEmulated = KEY_RIGHT; + new_state[_H6300_JOYPAD_REPORT_COLUMN] = 33; //100001 + report_key = prevJoypadKeycodePressEmulated; + report_col = _H6300_JOYPAD_REPORT_COLUMN; + report_row = 0; + input_report_key(omap_kp_data->input, + report_key, + new_state[report_col] & (1 << report_row)); + } + /* + * enter, up_left and down_left sensors pressed + * --> 100111 == 39 + * or up_left and down_left + * --> 100011 == 35 + * --> move to left + */ + else if ((new_state[1] == 39) || + (new_state[1] == 35)) + { + joypad_checked = 1; + prevJoypadKeycodePressEmulated = KEY_LEFT; + new_state[_H6300_JOYPAD_REPORT_COLUMN] = 36; //100100 + report_key = prevJoypadKeycodePressEmulated; + report_col = _H6300_JOYPAD_REPORT_COLUMN; + report_row = 2; + input_report_key(omap_kp_data->input, + report_key, + new_state[report_col] & (1 << report_row)); + } + else + { + //printk("missed new_state = %d\n", new_state[1]); + } + } + else + { + if (prevJoypadKeycodePressEmulated != 0) + { + // report key up event + joypad_checked = 1; + new_state[_H6300_JOYPAD_REPORT_COLUMN] = 32; //100000 + report_key = prevJoypadKeycodePressEmulated; + report_col = _H6300_JOYPAD_REPORT_COLUMN; + switch(prevJoypadKeycodePressEmulated) + { + case KEY_RIGHT: + report_row = 0; + break; + case KEY_DOWN: + report_row = 1; + break; + case KEY_LEFT: + report_row = 2; + break; + case KEY_UP: + report_row = 3; + break; + case KEY_ENTER: + report_row = 4; + break; + default: + printk(KERN_WARNING "Unknown iPAQ h6300 column 1 key = %d released. This should newer happen!\n", + key); + report_row = 0; + } + input_report_key(omap_kp_data->input, + report_key, + new_state[report_col] & (1 << report_row)); + prevJoypadKeycodePressEmulated = 0; + } + } + } + } + else + { + if (!(kp_cur_group == (key & GROUP_MASK) || + kp_cur_group == -1)) + continue; + + kp_cur_group = key & GROUP_MASK; + input_report_key(omap_kp_data->input, key & ~GROUP_MASK, + !!(new_state[col] & (1 << row))); + } #endif } } @@ -348,10 +536,11 @@ omap_set_gpio_direction(row_gpios[i], 1); } } + prevJoypadKeycodePressEmulated = 0; init_timer(&omap_kp->timer); omap_kp->timer.function = omap_kp_timer; - omap_kp->timer.data = (unsigned long) omap_kp; + omap_kp->timer.data = (unsigned long)omap_kp; /* get the irq and init timer*/ tasklet_enable(&kp_tasklet); @@ -376,7 +565,7 @@ input_register_device(omap_kp->input); if (machine_is_omap_h2() || machine_is_omap_h3() || - machine_is_omap_perseus2()) { + machine_is_omap_perseus2() || machine_is_omap_h6300()) { omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING); } /* scan current status and enable interrupt */ @@ -447,6 +636,6 @@ module_init(omap_kp_init); module_exit(omap_kp_exit); -MODULE_AUTHOR("Timo Teräs"); +MODULE_AUTHOR("Timo Ter�s"); MODULE_DESCRIPTION("OMAP Keypad Driver"); MODULE_LICENSE("GPL"); diff -Naur linux-2.6.16.16/drivers/input/touchscreen/omap/Makefile h6300_dev/drivers/input/touchscreen/omap/Makefile --- linux-2.6.16.16/drivers/input/touchscreen/omap/Makefile 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/input/touchscreen/omap/Makefile 2005-10-22 03:52:45.000000000 +0300 @@ -8,5 +8,6 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += ts_inn1510.o objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += ts_osk.o +objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += ts_hx.o omapts-objs := omap_ts.o $(objs-yy) diff -Naur linux-2.6.16.16/drivers/input/touchscreen/omap/omap_ts.c h6300_dev/drivers/input/touchscreen/omap/omap_ts.c --- linux-2.6.16.16/drivers/input/touchscreen/omap/omap_ts.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/input/touchscreen/omap/omap_ts.c 2006-02-21 23:54:33.000000000 +0200 @@ -46,7 +46,7 @@ #define OMAP_TS_NAME "omap_ts" static struct ts_device *__initdata ts_devs[] = { -#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) +#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H6300) &hx_ts, #endif #ifdef CONFIG_MACH_OMAP_OSK diff -Naur linux-2.6.16.16/drivers/input/touchscreen/omap/ts_hx.c h6300_dev/drivers/input/touchscreen/omap/ts_hx.c --- linux-2.6.16.16/drivers/input/touchscreen/omap/ts_hx.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/input/touchscreen/omap/ts_hx.c 2006-04-24 20:53:29.000000000 +0300 @@ -39,6 +39,7 @@ #define H2_GPIO_NUM 4 #define H3_GPIO_NUM 48 +#define H6300_GPIO_NUM 2 #define OMAP_TSC2101_XRES 500 #define TOUCHSCREEN_DATA_REGISTERS_PAGE 0x0 @@ -88,6 +89,9 @@ } else if (machine_is_omap_h3()) { gpio = H3_GPIO_NUM; omap_cfg_reg(W19_1610_GPIO48); + } else if (machine_is_omap_h6300 ()) { + gpio = H6300_GPIO_NUM; + omap_cfg_reg(M14_1510_GPIO2); } else return -ENODEV; @@ -180,5 +184,7 @@ omap_free_gpio(H2_GPIO_NUM); else if (machine_is_omap_h3()) omap_free_gpio(H3_GPIO_NUM); + else if (machine_is_omap_h6300()) + omap_free_gpio(H6300_GPIO_NUM); } #endif diff -Naur linux-2.6.16.16/drivers/mmc/mmc.c h6300_dev/drivers/mmc/mmc.c --- linux-2.6.16.16/drivers/mmc/mmc.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/mmc/mmc.c 2006-03-28 10:34:39.000000000 +0300 @@ -964,7 +964,7 @@ mmc_decode_scr(card); } - mmc_deselect_cards(host); + //mmc_deselect_cards(host); } static unsigned int mmc_calculate_clock(struct mmc_host *host) diff -Naur linux-2.6.16.16/drivers/ssi/omap-tsc2101.c h6300_dev/drivers/ssi/omap-tsc2101.c --- linux-2.6.16.16/drivers/ssi/omap-tsc2101.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/ssi/omap-tsc2101.c 2006-04-24 20:53:29.000000000 +0300 @@ -36,10 +36,11 @@ #include #include #include +#include #include "omap-tsc2101.h" -#if CONFIG_ARCH_OMAP16XX +#if CONFIG_ARCH_OMAP1 #include <../drivers/ssi/omap-uwire.h> #else #error "Unsupported configuration" @@ -66,27 +67,28 @@ if (count++ == 0) { int ret = 0; /* set the Mux to provide MCLK to TSC2101 */ - if (machine_is_omap_h3()) { + if (machine_is_omap_h3()) ret = omap_cfg_reg(V5_1710_MCLK_ON); - } else { - if (machine_is_omap_h2()) { - ret = omap_cfg_reg(R10_1610_MCLK_ON); + else if (machine_is_omap_h2()) + ret = omap_cfg_reg(R10_1610_MCLK_ON); + else if (machine_is_omap_h6300()) + ret = omap_cfg_reg(R10_1510_MCLK_ON); + + if (!cpu_is_omap1510 ()) { + /* Get the MCLK */ + tsc2101_mclk_ck = clk_get(NULL, "mclk"); + if (NULL == tsc2101_mclk_ck) { + printk(KERN_ERR "Unable to get the clock MCLK!!!\n");; + ret = -EPERM; + goto done; } - } - - /* Get the MCLK */ - tsc2101_mclk_ck = clk_get(NULL, "mclk"); - if (NULL == tsc2101_mclk_ck) { - printk(KERN_ERR "Unable to get the clock MCLK!!!\n");; - ret = -EPERM; - goto done; - } - if (clk_set_rate(tsc2101_mclk_ck, 12000000)) { - printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");; - ret = -EPERM; - goto done; - } - clk_enable(tsc2101_mclk_ck); + if (clk_set_rate(tsc2101_mclk_ck, 12000000)) { + printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");; + ret = -EPERM; + goto done; + } + clk_enable(tsc2101_mclk_ck); + } /* if (!cpu_is_omap1510 ()) */ ret = omap_tsc2101_configure(); @@ -116,10 +118,16 @@ } } - /* Release the MCLK */ - clk_disable(tsc2101_mclk_ck); - clk_put(tsc2101_mclk_ck); - tsc2101_mclk_ck = NULL; + if (!cpu_is_omap1510 ()) { + /* Release the MCLK */ + clk_disable(tsc2101_mclk_ck); + clk_put(tsc2101_mclk_ck); + tsc2101_mclk_ck = NULL; + } + +#if defined(CONFIG_MACH_OMAP_H6300) + omap_free_gpio(8); +#endif module_put(THIS_MODULE); } @@ -150,7 +158,10 @@ return; } } - if (machine_is_omap_h3()) { + if (machine_is_omap_h3() || machine_is_omap_h6300()) { + + if (machine_is_omap_h6300()) + omap_set_gpio_dataout (8, 0); ret = omap_uwire_data_transfer(0, ((page << 11) | (address << 5)), @@ -159,6 +170,8 @@ printk(KERN_ERR "uwire-write returned error for address %x\n", address); + if (machine_is_omap_h6300()) + omap_set_gpio_dataout (8, 1); return; } ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0); @@ -166,10 +179,14 @@ printk(KERN_ERR "uwire-write returned error for address %x\n", address); + if (machine_is_omap_h6300()) + omap_set_gpio_dataout (8, 1); return; } - } + if (machine_is_omap_h6300()) + omap_set_gpio_dataout (8, 1); + } } void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs) @@ -178,9 +195,13 @@ if (machine_is_omap_h2()) { cs = 1; } - if (machine_is_omap_h3()) { + if (machine_is_omap_h3() || machine_is_omap_h6300()) { cs = 0; } + + if (machine_is_omap_h6300()) + omap_set_gpio_dataout(8, 0); + (void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11) | (startaddress << 5)), 16, 0, NULL, 1); @@ -188,6 +209,9 @@ omap_uwire_data_transfer(cs, 0, 0, 16, data, 1); } omap_uwire_data_transfer(cs, 0, 0, 16, data, 0); + + if (machine_is_omap_h6300()) + omap_set_gpio_dataout(8, 1); } u16 omap_tsc2101_read(int page, u8 address) @@ -228,9 +252,24 @@ omap_cfg_reg(N14_1610_UWIRE_CS0); omap_uwire_configure_mode(0, uwire_flags); } + if (machine_is_omap_h6300()) { + uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE; + omap_cfg_reg(N14_1510_UWIRE_CS0); + omap_uwire_configure_mode(0, uwire_flags); + + omap_request_gpio(8); + omap_set_gpio_dataout(8, 0); + omap_set_gpio_direction (8, 0); + } /* Configure MCLK enable */ - omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2); + if (cpu_is_omap16xx() || cpu_is_omap1710()) + omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2); + if (machine_is_omap_h6300()) { + omap_cfg_reg(V19_1510_UWIRE_SCLK); + omap_cfg_reg(W21_1510_UWIRE_SDO); + omap_cfg_reg(U18_1510_UWIRE_SDI); + } return 0; } @@ -243,5 +282,5 @@ MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION - ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec."); + ("Glue audio driver for the TI OMAP1510/1610/OMAP1710 TSC2101 codec."); MODULE_LICENSE("GPL"); diff -Naur linux-2.6.16.16/drivers/ssi/omap-uwire.c h6300_dev/drivers/ssi/omap-uwire.c --- linux-2.6.16.16/drivers/ssi/omap-uwire.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/ssi/omap-uwire.c 2006-04-24 20:53:29.000000000 +0300 @@ -10,7 +10,7 @@ * Ported to 2.6 uwire interface. * Copyright (C) 2004 Texas Instruments. * - * Generalization patches by Juha Yrjölä + * Generalization patches by Juha Yrj�l� * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -212,6 +212,10 @@ omap_cfg_reg(N14_1610_UWIRE_CS0); omap_cfg_reg(P15_1610_UWIRE_CS3); } + if (machine_is_omap_h6300()) { + omap_cfg_reg(N14_1510_UWIRE_CS0); + omap_cfg_reg(P15_1510_UWIRE_CS3); + } if (machine_is_omap_perseus2()) { /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */ int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000; diff -Naur linux-2.6.16.16/drivers/telephony/Kconfig h6300_dev/drivers/telephony/Kconfig --- linux-2.6.16.16/drivers/telephony/Kconfig 2006-05-11 04:56:24.000000000 +0300 +++ h6300_dev/drivers/telephony/Kconfig 2005-10-06 02:34:39.000000000 +0300 @@ -41,7 +41,18 @@ help Say Y here to configure in PCMCIA service support for the Quicknet cards manufactured by Quicknet Technologies, Inc. This changes the - card initialization code to work with the card manager daemon. + card initialization code to work with the card manager daemon. + +config GSM_H6300 + tristate "H6300 P5186 GSM/GPRS DRIVER" + depends on PHONE && I2C && PCA9535 + help + Bluetooth H6300 P5186 gsm/gprs driver. + This driver provides the firmware loading mechanism for the P5185 + gsm/gprs hardware in iPAQ h6300. + + Say Y here to compile support for P5186 gsm/gprs devices into the + kernel or say M to compile it as module (h6300_gsm). endmenu diff -Naur linux-2.6.16.16/drivers/telephony/Makefile h6300_dev/drivers/telephony/Makefile --- linux-2.6.16.16/drivers/telephony/Makefile 2006-05-11 04:56:24.000000000 +0300 +++ h6300_dev/drivers/telephony/Makefile 2005-10-06 02:34:39.000000000 +0300 @@ -2,6 +2,7 @@ # Makefile for drivers/telephony # -obj-$(CONFIG_PHONE) += phonedev.o -obj-$(CONFIG_PHONE_IXJ) += ixj.o -obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o +obj-$(CONFIG_PHONE) += phonedev.o +obj-$(CONFIG_PHONE_IXJ) += ixj.o +obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o +obj-$(CONFIG_GSM_H6300) += omap/ diff -Naur linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.c h6300_dev/drivers/telephony/omap/h6300_gsm_led.c --- linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/telephony/omap/h6300_gsm_led.c 2005-10-06 02:34:39.000000000 +0300 @@ -0,0 +1,40 @@ +/* + * GSM interface driver helper for controlling bluetooth leds available in iPAQ h6300. + * + * Copyright (C) 2005 Mika Laitio + * + * 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 +#include +#include +#include + +#include +#include + +/* + * Low level access for disabling h6300 gsm led. + * + * TODO: implement for h6300 + */ +void h6300_clear_gsm_led(int led_num) +{ + printk(KERN_NOTICE "h6300_gsm_led.c h6300_clear_gsm_led() done\n"); + //hx4700_set_led(led_num, 0, 16); +} +EXPORT_SYMBOL(h6300_clear_gsm_led); + +/* + * Low level access for setting up the gsm led. + * + * TODO: implement for h6300 + */ +void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time) +{ + printk(KERN_NOTICE "h6300_gsm_led.c h6300_set_gsm_led() done\n"); +} +EXPORT_SYMBOL(h6300_set_gsm_led); diff -Naur linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.h h6300_dev/drivers/telephony/omap/h6300_gsm_led.h --- linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.h 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/telephony/omap/h6300_gsm_led.h 2005-10-06 02:34:39.000000000 +0300 @@ -0,0 +1,10 @@ +#ifndef H6300_GSM_LED_H_ +#define H6300_GSM_LED_H_ + +#define INDEX_GSM_LED 1 + +void h6300_clear_gsm_led(int led_num); +void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time); + + +#endif /*H6300_GSM_LED_H_*/ diff -Naur linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_p5186.c h6300_dev/drivers/telephony/omap/h6300_gsm_p5186.c --- linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_p5186.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/telephony/omap/h6300_gsm_p5186.c 2006-01-23 00:09:23.000000000 +0200 @@ -0,0 +1,172 @@ +/* + * Wavecom P5186 GPRS and GSM module driver for iPAQ h6300. + * + * Copyright (C) 2005 Mika Laitio + * + * 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 +#include +#include +#include + +#include +#include + +#include +#include +#include "h6300_gsm_led.h" + +static void +h6300_gsm_configure(struct uart_omap_port *up, int enable) +{ + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() started, enable = %d\n", enable); + + // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable ); + if (enable == 0) { + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_OFF); // turn off gpio + mdelay(5); + h6300_clear_gsm_led(INDEX_GSM_LED); + } + else if (enable == 1) { + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio + mdelay(5); + } + else if (enable == 2) { + h6300_set_gsm_led(INDEX_GSM_LED, 16, 16); + } + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() done\n"); +} + +static void +h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx) +{ + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_set_txrx(), txrx = %d done\n", txrx); + /* do nothing */ +} + +static int +h6300_gsm_get_txrx(struct uart_omap_port *up) +{ + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_get_txrx() done\n"); + /* do nothing */ + return 0; +} + +static int +h6300_gsm_probe(struct platform_device *pdev) +{ + int ii; + int curVal; + + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data; +/* + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_probe() started\n"); + for (ii = 0; ii < 8; ii++) + { + curVal = pca9535_gpio_read(ii); + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal); + } + for (ii = 10; ii < 18; ii++) + { + curVal = pca9535_gpio_read(ii); + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal); + } + printk(KERN_NOTICE "\nfirst check done\n"); +*/ + pca9535_gpio_direction(GPIO_I2C_GPRS_RESET, GPIO_DIR_OUTPUT); // set gpio direction to be output + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON); // turn on gpio + mdelay(200); + + pca9535_gpio_direction(GPIO_I2C_MIC_OP_EN, GPIO_DIR_OUTPUT); // set gpio direction to be output + pca9535_gpio_write(GPIO_I2C_MIC_OP_EN, GPIO_VALUE_ON); // turn on gpio + mdelay(200); + + pca9535_gpio_direction(GPIO_I2C_SPK_OP_PD, GPIO_DIR_OUTPUT); // set gpio direction to be output + pca9535_gpio_write(GPIO_I2C_SPK_OP_PD, GPIO_VALUE_ON); // pd = pulldown?, normal off = on + + mdelay(200); + + //pca9535_gpio_direction( + /* configure bluetooth UART */ + //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD); + + funcs->configure = h6300_gsm_configure; + funcs->set_txrx = h6300_gsm_set_txrx; + funcs->get_txrx = h6300_gsm_get_txrx; + + /* Make sure the LED is off */ + h6300_clear_gsm_led(INDEX_GSM_LED); +/* + for (ii = 0; ii < 8; ii++) + { + curVal = pca9535_gpio_read(ii); + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal); + } + for (ii = 10; ii < 18; ii++) + { + curVal = pca9535_gpio_read(ii); + printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal); + } +*/ + printk(KERN_NOTICE "\nh6300_gsm_p5186.c h6300_gsm_probe() done\n"); + + return 0; +} + +static int +h6300_gsm_remove(struct platform_device *pdev) +{ + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data; + + printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_remove() started\n"); + + pca9535_gpio_write(GPIO_I2C_GPRS_RESET, 0); // turn off gpio + + funcs->configure = NULL; + funcs->set_txrx = NULL; + funcs->get_txrx = NULL; + + /* Make sure the LED is off */ + h6300_clear_gsm_led(INDEX_GSM_LED); + + printk(KERN_NOTICE "h6300_gsm_p5186.c, h6300_gsm_remove() done\n"); + + return 0; +} + +static struct platform_driver gsm_driver = { + .probe = h6300_gsm_probe, + .remove = h6300_gsm_remove, + .driver = { + .name = "h6300_gsm", + }, +}; + +static int __init +h6300_gsm_init(void) +{ + printk(KERN_NOTICE "h6300 GSM Driver init()\n"); + return platform_driver_register(&gsm_driver); +} + +static void __exit +h6300_gsm_exit(void) +{ + printk(KERN_NOTICE "h6300 GSM Driver exit()\n"); + platform_driver_unregister(&gsm_driver); +} + +module_init(h6300_gsm_init); +module_exit(h6300_gsm_exit); + +MODULE_AUTHOR("Mika Laitio, "); +MODULE_DESCRIPTION("iPAQ h6300 Wavecom P5186 GPRS and GSM module driver."); +MODULE_LICENSE("GPL"); + diff -Naur linux-2.6.16.16/drivers/telephony/omap/Makefile h6300_dev/drivers/telephony/omap/Makefile --- linux-2.6.16.16/drivers/telephony/omap/Makefile 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/telephony/omap/Makefile 2005-10-06 02:34:39.000000000 +0300 @@ -0,0 +1,6 @@ +# +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers. +# + +h6300_gsm-objs := h6300_gsm_led.o h6300_gsm_p5186.o +obj-$(CONFIG_GSM_H6300) += h6300_gsm.o diff -Naur linux-2.6.16.16/drivers/usb/gadget/omap_udc.c h6300_dev/drivers/usb/gadget/omap_udc.c --- linux-2.6.16.16/drivers/usb/gadget/omap_udc.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/usb/gadget/omap_udc.c 2006-04-24 20:53:29.000000000 +0300 @@ -60,7 +60,8 @@ #undef USB_TRACE /* bulk DMA seems to be behaving for both IN and OUT */ -#define USE_DMA +//#define USE_DMA +#undef USE_DMA /* ISO too */ #define USE_ISO @@ -2147,7 +2148,7 @@ /* boards that don't have VBUS sensing can't autogate 48MHz; * can't enter deep sleep while a gadget driver is active. */ - if (machine_is_omap_innovator() || machine_is_omap_osk()) + if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_omap_h6300()) omap_vbus_session(&udc->gadget, 1); done: @@ -2170,7 +2171,7 @@ if (udc->dc_clk != NULL) omap_udc_enable_clock(1); - if (machine_is_omap_innovator() || machine_is_omap_osk()) + if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_omap_h6300()) omap_vbus_session(&udc->gadget, 0); if (udc->transceiver) @@ -2791,7 +2792,7 @@ hmc = HMC_1510; type = "(unknown)"; - if (machine_is_omap_innovator()) { + if (machine_is_omap_innovator() || machine_is_omap_h6300()) { /* just set up software VBUS detect, and then * later rig it so we always report VBUS. * FIXME without really sensing VBUS, we can't diff -Naur linux-2.6.16.16/drivers/usb/host/ohci-omap.c h6300_dev/drivers/usb/host/ohci-omap.c --- linux-2.6.16.16/drivers/usb/host/ohci-omap.c 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/usb/host/ohci-omap.c 2006-02-06 15:36:21.000000000 +0200 @@ -353,11 +353,7 @@ if (IS_ERR(usb_host_ck)) return PTR_ERR(usb_host_ck); - if (!cpu_is_omap1510()) - usb_dc_ck = clk_get(0, "usb_dc_ck"); - else - usb_dc_ck = clk_get(0, "lb_ck"); - + usb_dc_ck = clk_get(0, "usb_dc_ck"); if (IS_ERR(usb_dc_ck)) { clk_put(usb_host_ck); return PTR_ERR(usb_dc_ck); diff -Naur linux-2.6.16.16/drivers/video/omap/lcd_h6300.c h6300_dev/drivers/video/omap/lcd_h6300.c --- linux-2.6.16.16/drivers/video/omap/lcd_h6300.c 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/drivers/video/omap/lcd_h6300.c 2006-04-24 20:53:29.000000000 +0300 @@ -0,0 +1,159 @@ +/* + * File: drivers/video/omap_new/lcd-h6300.c + * + * LCD panel support for the TI OMAP1510 Innovator board + * + * Copyright (C) 2004 Nokia Corporation + * Author: Imre Deak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include +#include + +/* #define OMAPFB_DBG 1 */ + +#include "debug.h" + +//static struct clk *h6300_lcd_ck; + +static int h6300_panel_init(struct omapfb_device *fbdev) +{ + DBGENTER(1); +/* + if ((h6300_lcd_ck = clk_get (NULL, "lcd_ck")) == NULL) { + printk(KERN_ERR "Unable to get the clock LCD_CK!!!\n"); + return -EPERM; + } clk_enable(h6300_lcd_ck); +*/ + DBGLEAVE(1); + printk(KERN_INFO "lcd_h6300.c: h6300_panel_init() done\n"); + return 0; +} + +static void h6300_panel_cleanup(void) +{ + DBGENTER(1); +/* + if (h6300_lcd_ck) { + clk_disable(h6300_lcd_ck); + clk_put(h6300_lcd_ck); + h6300_lcd_ck = NULL; + } +*/ + DBGLEAVE(1); + printk(KERN_INFO "lcd_h6300.c: h6300_panel_cleanup() done\n"); +} + +static int h6300_panel_enable(void) +{ + DBGENTER(1); + DBGLEAVE(1); + printk(KERN_INFO "lcd_h6300.c: h6300_panel_enable() done\n"); + return 0; +} + +static void h6300_panel_disable(void) +{ + DBGENTER(1); + DBGLEAVE(1); + printk(KERN_INFO "lcd_h6300.c: h6300_panel_disable() done\n"); +} + +static unsigned long h6300_panel_get_caps(void) +{ + printk(KERN_INFO "lcd_h6300.c: h6300_panel_get_caps() called\n"); + return 0; +} + +struct lcd_panel h6300_panel = { + .name = "h6300", + .config = OMAP_LCDC_PANEL_TFT, + + .bpp = 16, + .data_lines = 16, + .x_res = 240, + .y_res = 320, + .pixel_clock = 21000, + .hsw = 12, + .hfp = 10, + .hbp = 10, + .vsw = 3, + .vfp = 10, + .vbp = 3, + .pcd = 0, + + .init = h6300_panel_init, + .cleanup = h6300_panel_cleanup, + .enable = h6300_panel_enable, + .disable = h6300_panel_disable, + .get_caps = h6300_panel_get_caps, +}; + +static int h6300_panel_probe(struct platform_device *pdev) +{ + DBGENTER(1); + omapfb_register_panel(&h6300_panel); + return 0; +} + +static int h6300_panel_remove(struct platform_device *pdev) +{ + DBGENTER(1); + return 0; +} + +static int h6300_panel_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + DBGENTER(1); + pca9535_gpio_write(GPIO3, HI); + return 0; +} + +static int h6300_panel_resume(struct platform_device *pdev) +{ + DBGENTER(1); + pca9535_gpio_write(GPIO3, LOW); + return 0; +} + +struct platform_driver h6300_panel_driver = { + .probe = h6300_panel_probe, + .remove = h6300_panel_remove, + .suspend = h6300_panel_suspend, + .resume = h6300_panel_resume, + .driver = { + .name = "lcd_h6300", + .owner = THIS_MODULE, + }, +}; + +static int h6300_panel_drv_init(void) +{ + return platform_driver_register(&h6300_panel_driver); +} + +static void h6300_panel_drv_cleanup(void) +{ + platform_driver_unregister(&h6300_panel_driver); +} + +module_init(h6300_panel_drv_init); +module_exit(h6300_panel_drv_cleanup); diff -Naur linux-2.6.16.16/drivers/video/omap/Makefile h6300_dev/drivers/video/omap/Makefile --- linux-2.6.16.16/drivers/video/omap/Makefile 2006-05-17 21:41:30.000000000 +0300 +++ h6300_dev/drivers/video/omap/Makefile 2006-02-21 23:54:33.000000000 +0200 @@ -23,6 +23,7 @@ objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o +objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += lcd_h6300.o objs-y$(CONFIG_FB_OMAP_LCD_LPH8923) += lcd_lph8923.o diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/board-h6300.h h6300_dev/include/asm-arm/arch-omap/board-h6300.h --- linux-2.6.16.16/include/asm-arm/arch-omap/board-h6300.h 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/include/asm-arm/arch-omap/board-h6300.h 2006-04-24 20:53:29.000000000 +0300 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-omap/board-innovator.h + * + * Copyright (C) 2001 RidgeRun, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __ASM_ARCH_OMAP_H6300_H +#define __ASM_ARCH_OMAP_H6300_H + +#ifndef OMAP_SDRAM_DEVICE +#define OMAP_SDRAM_DEVICE D256M_1X16_4B +#endif + +#define OMAP1510P1_IMIF_PRI_VALUE 0x00 +#define OMAP1510P1_EMIFS_PRI_VALUE 0x00 +#define OMAP1510P1_EMIFF_PRI_VALUE 0x00 + +#define NR_FPGA_IRQS 24 +#define NR_IRQS IH_BOARD_BASE + NR_FPGA_IRQS + +#endif /* __ASM_ARCH_OMAP_H6300_H */ diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/h6300_uart_info.h h6300_dev/include/asm-arm/arch-omap/h6300_uart_info.h --- linux-2.6.16.16/include/asm-arm/arch-omap/h6300_uart_info.h 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/include/asm-arm/arch-omap/h6300_uart_info.h 2005-10-14 18:55:31.000000000 +0300 @@ -0,0 +1,33 @@ +/* + * Support file for calling h6300 uart configuration functions. + * Used at least by h6300_bt driver. + * + * Copyright (c) 2005 SDG Systems, LLC + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700 + * 2005-10-03 Mika Laitio (lamikr@cc.jyu.fi) Reorganized for the iPAQ h6300 bt driver. + */ + +#ifndef _H6300_UART_INFO_H +#define _H6300_UART_INFO_H + +#include "omap_serial.h" + +#define GPIO_BT_PWR_EN 3 +#define GPIO_N_BT_RST 9 + +#define GPIO_I2C_GPRS_RESET 16 +#define GPIO_I2C_MIC_OP_EN 10 +#define GPIO_I2C_SPK_OP_PD 11 + +#define GPIO_VALUE_OFF 0 +#define GPIO_VALUE_ON 1 + +#define GPIO_DIR_OUTPUT 1 + +struct h6300_uart_funcs { + void (*configure)( struct uart_omap_port *up, int state); + void (*set_txrx)( struct uart_omap_port *up, int txrx); + int (*get_txrx)( struct uart_omap_port *up); +}; + +#endif diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/hardware.h h6300_dev/include/asm-arm/arch-omap/hardware.h --- linux-2.6.16.16/include/asm-arm/arch-omap/hardware.h 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/include/asm-arm/arch-omap/hardware.h 2006-02-06 15:36:21.000000000 +0200 @@ -290,6 +290,10 @@ #include "board-innovator.h" #endif +#ifdef CONFIG_MACH_OMAP_H6300 +#include "board-h6300.h" +#endif + #ifdef CONFIG_MACH_OMAP_H2 #include "board-h2.h" #endif diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/mux.h h6300_dev/include/asm-arm/arch-omap/mux.h --- linux-2.6.16.16/include/asm-arm/arch-omap/mux.h 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/include/asm-arm/arch-omap/mux.h 2006-05-18 00:38:24.000000000 +0300 @@ -320,6 +320,13 @@ P15_1610_UWIRE_CS3, N15_1610_UWIRE_CS1, + /* OMAP-1510 uWire */ + P15_1510_UWIRE_CS3, + N14_1510_UWIRE_CS0, + V19_1510_UWIRE_SCLK, + W21_1510_UWIRE_SDO, + U18_1510_UWIRE_SDI, + /* OMAP-1610 Flash */ L3_1610_FLASH_CS2B_OE, M8_1610_FLASH_CS2B_WE, @@ -384,6 +391,7 @@ T20_1610_LOW_PWR, /* MCLK Settings */ + R10_1510_MCLK_ON, V5_1710_MCLK_ON, V5_1710_MCLK_OFF, R10_1610_MCLK_ON, diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/omap-alsa.h h6300_dev/include/asm-arm/arch-omap/omap-alsa.h --- linux-2.6.16.16/include/asm-arm/arch-omap/omap-alsa.h 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/include/asm-arm/arch-omap/omap-alsa.h 2006-03-08 13:28:16.000000000 +0200 @@ -1,6 +1,6 @@ /* * linux/include/asm-arm/arch-omap/omap-alsa.h - * + * * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards. * * Copyright (C) 2006 Mika Laitio diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/omap_serial.h h6300_dev/include/asm-arm/arch-omap/omap_serial.h --- linux-2.6.16.16/include/asm-arm/arch-omap/omap_serial.h 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/include/asm-arm/arch-omap/omap_serial.h 2005-10-04 00:58:34.000000000 +0300 @@ -0,0 +1,62 @@ +/* + * Omap/h6300 serial driver private interface. + * Code originates from the pxa-serial.h available in the handheld org drivers + * for iPAQ PXA4700. + * + * Copyright (c) 2005 SDG Systems, LLC + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700 + * 2005-10-03 Mika Laitio (lamikr@cc.jyu.fi) Reorganized for the iPAQ h6300 bt driver. + */ + +#ifndef _OMAP_SERIAL_H +#define _OMAP_SERIAL_H + +#define OMAP_SERIAL_TX 1 +#define OMAP_SERIAL_RX 2 + +#include +#include + +struct platform_omap_serial_funcs; + +struct uart_omap_port { + struct uart_port port; + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned int lsr_break_flag; + unsigned int cken; + char *name; + struct platform_omap_serial_funcs *pf; +}; + +/* A pointer to such a structure can be contained in the platform_data + * field of every PXA UART platform_device. If the field is NULL, the + * serial port works as usual. + * + * For the sake of simplicity/performance no one of the function pointers + * in the structure below can be NULL. + */ +struct platform_omap_serial_funcs { + /* Platform-specific function to initialize whatever is connected + to this serial port... enable=1 -> enable transceiver, + 0 -> disable transceiver. */ + void (*configure) (struct uart_omap_port *up, int enable); + /* Platform-specific function to enable or disable the individual + transmitter/receiver submodules. On transceivers without echo + cancellation (e.g. SIR) transmitter always has priority, e.g. + if both bits are set, only the transmitter is enabled. */ + void (*set_txrx) (struct uart_omap_port *up, int txrx); + /* Get the current state of tx/rx (see bitflags above) */ + int (*get_txrx) (struct uart_omap_port *up); +}; + +/* + * The variables below are located in arch/arm/mach-omap/board_h6300.c + * Machine-specific code may want to put a pointer to a static + * platform_pxa_serial_funcs structure in the dev.platform_data + * field of the respective port device. + */ +extern struct platform_device btuart_device; + +#endif diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/pca9535.h h6300_dev/include/asm-arm/arch-omap/pca9535.h --- linux-2.6.16.16/include/asm-arm/arch-omap/pca9535.h 1970-01-01 02:00:00.000000000 +0200 +++ h6300_dev/include/asm-arm/arch-omap/pca9535.h 2005-10-25 03:24:45.000000000 +0300 @@ -0,0 +1,39 @@ +#ifndef _PCA9535_H +#define _PCA9535_H + +enum pca9535_gpios { + GPIO0 = 0, + GPIO1 = 1, + GPIO2 = 2, + GPIO3 = 3, + GPIO4 = 4, + GPIO5 = 5, + GPIO6 = 6, + GPIO7 = 7, + GPIO8 = 8, + GPIO9 = 9, + GPIO10 = 10, + GPIO11 = 11, + GPIO12 = 12, + GPIO13 = 13, + GPIO14 = 14, + GPIO15 = 15, + GPIO16 = 16, + GPIO17 = 17 +}; + +enum gpio_values { + HI = 0, + LOW = 1 +}; + +enum gpio_direction { + GPIO_INPUT = 0, + GPIO_OUTPUT = 1 +}; + +extern int pca9535_gpio_read(int gpio); +extern int pca9535_gpio_write(int gpio, unsigned char val); +extern int pca9535_gpio_direction(int gpio, unsigned char direction); + +#endif diff -Naur linux-2.6.16.16/Makefile h6300_dev/Makefile --- linux-2.6.16.16/Makefile 2006-05-17 21:41:27.000000000 +0300 +++ h6300_dev/Makefile 2006-05-18 01:45:17.000000000 +0300 @@ -11,7 +11,7 @@ # expect to learn how to build the kernel reading this file. # Add custom flags here to avoid conflict with updates -EXTRAVERSION := $(EXTRAVERSION)-omap2 +EXTRAVERSION := $(EXTRAVERSION)-omap1-h6300 # Do not print "Entering directory ..." MAKEFLAGS += --no-print-directory diff -Naur linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101.c h6300_dev/sound/arm/omap/omap-alsa-tsc2101.c --- linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101.c 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/sound/arm/omap/omap-alsa-tsc2101.c 2006-03-30 23:15:31.000000000 +0300 @@ -96,7 +96,11 @@ static snd_pcm_hardware_t tsc2101_snd_omap_alsa_playback = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_S16_LE), +#ifdef CONFIG_MACH_OMAP_H6300 + .formats = (SNDRV_PCM_FMTBIT_S8), +#else + .formats = (SNDRV_PCM_FMTBIT_S16_LE), +#endif .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | @@ -136,7 +140,7 @@ }; /* - * Simplified write for tsc Audio + * Simplified write for tsc2101 audio registers. */ inline void tsc2101_audio_write(u8 address, u16 data) { @@ -144,7 +148,7 @@ } /* - * Simplified read for tsc Audio + * Simplified read for tsc2101 audio registers. */ inline u16 tsc2101_audio_read(u8 address) { @@ -246,14 +250,17 @@ #endif /* #ifdef TSC_MASTER */ tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data); - /* program the PLLs */ + /* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use. + * If MCLK rate is something else, these values must be changed. + * See the tsc2101 specification for the details. + */ if (rate_reg_info[count].fs_44kHz) { - /* 44.1 khz - 12 MHz Mclk */ + /* samplerate = (44.1kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(7)); /* PVAL 1; I_VAL 7 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490)); /* D_VAL 5264 */ } else { - /* 48 khz - 12 Mhz Mclk */ + /* samplerate = (48.kHZ / x), where x is int. */ tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL | PLL1_PVAL(1) | PLL1_I_VAL(8)); /* PVAL 1; I_VAL 8 */ tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780)); /* D_VAL 1920 */ @@ -317,21 +324,14 @@ CODEC_CLOCK); } curRate = (uint)clk_get_rate(tsc2101_mclk); - DPRINTK("old clock rate = %d\n", curRate); if (curRate != CODEC_CLOCK) { err = clk_set_rate(tsc2101_mclk, CODEC_CLOCK); if (err) { printk(KERN_WARNING "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err); - //return -ECANCELED; + return -ECANCELED; } } - else - { - printk(KERN_INFO - "omap_alsa_tsc2101_clock_on(), no need to change rate, no need to change clock rate, rate already %d Hz.\n", - CODEC_CLOCK); - } err = clk_enable(tsc2101_mclk); curRate = (uint)clk_get_rate(tsc2101_mclk); curUseCount = clk_get_usecount(tsc2101_mclk); @@ -349,8 +349,7 @@ } /* - * Do some sanity check, turn clock off and then turn - * codec audio off + * Do some sanity check, turn clock off and then turn codec audio off */ int tsc2101_clock_off(void) { @@ -374,10 +373,6 @@ tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL, ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC)); DPRINTK("audio codec off\n"); -#ifdef DUMP_TSC2101_AUDIO_REGISTERS - printk("tsc2101_clock_off()\n"); - dump_tsc2101_audio_reg(); -#endif return 0; } @@ -420,18 +415,22 @@ }; static int __init omap_alsa_tsc2101_init(void) -{ - int err; - +{ ADEBUG(); - err = platform_driver_register(&omap_alsa_driver); - - return err; +#ifdef DUMP_TSC2101_AUDIO_REGISTERS + printk("omap_alsa_tsc2101_init()\n"); + dump_tsc2101_audio_reg(); +#endif + return platform_driver_register(&omap_alsa_driver); } static void __exit omap_alsa_tsc2101_exit(void) { ADEBUG(); +#ifdef DUMP_TSC2101_AUDIO_REGISTERS + printk("omap_alsa_tsc2101_exit()\n"); + dump_tsc2101_audio_reg(); +#endif platform_driver_unregister(&omap_alsa_driver); } diff -Naur linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.c h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.c --- linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.c 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.c 2006-05-10 02:42:13.000000000 +0300 @@ -50,47 +50,53 @@ //#define M_DPRINTK(ARGS...) printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS) #define M_DPRINTK(ARGS...) /* nop */ +#define CHECK_BIT(INDX, ARG) (((ARG) & TSC2101_BIT(INDX)) >> INDX) +#define IS_UNMUTED(INDX, ARG) (((CHECK_BIT(INDX, ARG)) == 0)) + #define DGC_DALVL_EXTRACT(ARG) ((ARG & 0x7f00) >> 8) #define DGC_DARVL_EXTRACT(ARG) ((ARG & 0x007f)) -#define GET_DGC_DALMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15) -#define GET_DGC_DARMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(7)) >> 7) -#define IS_DGC_DALMU_UNMUTED(ARG) (((GET_DGC_DALMU_BIT_VALUE(ARG)) == 0)) -#define IS_DGC_DARMU_UNMUTED(ARG) (((GET_DGC_DARMU_BIT_VALUE(ARG)) == 0)) #define HGC_ADPGA_HED_EXTRACT(ARG) ((ARG & 0x7f00) >> 8) -#define GET_DGC_HGCMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15) -#define IS_DGC_HGCMU_UNMUTED(ARG) (((GET_DGC_HGCMU_BIT_VALUE(ARG)) == 0)) - #define HNGC_ADPGA_HND_EXTRACT(ARG) ((ARG & 0x7f00) >> 8) -#define GET_DGC_HNGCMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15) -#define IS_DGC_HNGCMU_UNMUTED(ARG) (((GET_DGC_HNGCMU_BIT_VALUE(ARG)) == 0)) +#define BGC_ADPGA_BGC_EXTRACT(ARG) ((ARG & 0x7f00) >> 8) static int current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER; static int current_rec_src = REC_SRC_SINGLE_ENDED_MICIN_HED; +/* + * Simplified write for the tsc2101 audio registers. + */ +inline void omap_tsc2101_audio_write(u8 address, u16 data) +{ + omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data); +} + +/* + * Simplified read for the tsc2101 audio registers. + */ +inline u16 omap_tsc2101_audio_read(u8 address) +{ + return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address)); +} + /* - * Used for switching between TSC2101 recourd sources. - * Logic is adjusted from the TSC2101 OSS code. + * For selecting tsc2101 recourd source. */ -static int set_record_source(int val) +static void set_record_source(int val) { u16 data; - int maskedVal; - FN_IN; - maskedVal = 0xe0 & val; - - data = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_MIXER_PGA_CTRL); + /* Mute Analog Sidetone + * Analog sidetone gain db? + * Input selected by MICSEL connected to ADC + */ + data = MPC_ASTMU | MPC_ASTG(0x45); data &= ~MPC_MICSEL(7); /* clear all MICSEL bits */ - data |= maskedVal; - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_MIXER_PGA_CTRL, - data); + data |= MPC_MICSEL(val); + data |= MPC_MICADC; + omap_tsc2101_audio_write(TSC2101_MIXER_PGA_CTRL, data); + current_rec_src = val; - - FN_OUT(0); - return 0; } /* @@ -147,32 +153,34 @@ volL = get_mixer_volume_as_dac_gain_control_volume(mixerVolL); volR = get_mixer_volume_as_dac_gain_control_volume(mixerVolR); - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL); /* keep the old mute bit settings */ val &= ~(DGC_DALVL(OUTPUT_VOLUME_MIN) | DGC_DARVL(OUTPUT_VOLUME_MIN)); val |= DGC_DALVL(volL) | DGC_DARVL(volR); retVal = 2; if (retVal) { - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_DAC_GAIN_CTRL, - val); + omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val); } M_DPRINTK("to registry: left = %d, right = %d, total = %d\n", DGC_DALVL_EXTRACT(val), DGC_DARVL_EXTRACT(val), val); return retVal; } -int dac_gain_control_unmute_control(int muteLeft, int muteRight) +/** + * If unmuteLeft/unmuteRight == 0 --> mute + * If unmuteLeft/unmuteRight == 1 --> unmute + */ +int dac_gain_control_unmute(int unmuteLeft, int unmuteRight) { u16 val; int count; count = 0; - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL); /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on * so if values are same, it's time to change the registry value. */ - if (muteLeft == GET_DGC_DALMU_BIT_VALUE(val)) { - if (muteLeft == 0) { + if (unmuteLeft != IS_UNMUTED(15, val)) { + if (unmuteLeft == 0) { /* mute --> turn bit on */ val = val | DGC_DALMU; } @@ -182,8 +190,8 @@ } count++; } /* L */ - if (muteRight == GET_DGC_DARMU_BIT_VALUE(val)) { - if (muteRight == 0) { + if (unmuteRight != IS_UNMUTED(7, val)) { + if (unmuteRight == 0) { /* mute --> turn bit on */ val = val | DGC_DARMU; } @@ -194,14 +202,47 @@ count++; } /* R */ if (count) { - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL, val); + omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val); M_DPRINTK("changed value, is_unmuted left = %d, right = %d\n", - IS_DGC_DALMU_UNMUTED(val), - IS_DGC_DARMU_UNMUTED(val)); + IS_UNMUTED(15, val), + IS_UNMUTED(7, val)); } return count; } +/** + * unmute: 0 --> mute, 1 --> unmute + * page2RegIndx: Registry index in tsc2101 page2. + * muteBitIndx: Index number for the bit in registry that indicates whether muted or unmuted. + */ +int adc_pga_unmute_control(int unmute, int page2regIndx, int muteBitIndx) +{ + int count; + u16 val; + + count = 0; + val = omap_tsc2101_audio_read(page2regIndx); + /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on + * so if the values are same, it's time to change the registry value... + */ + if (unmute != IS_UNMUTED(muteBitIndx, val)) { + if (unmute == 0) { + /* mute --> turn bit on */ + val = val | TSC2101_BIT(muteBitIndx); + } + else { + /* unmute --> turn bit off */ + val = val & ~TSC2101_BIT(muteBitIndx); + } + M_DPRINTK("changed value, is_unmuted = %d\n", IS_UNMUTED(muteBitIndx, val)); + count++; + } + if (count) { + omap_tsc2101_audio_write(page2regIndx, val); + } + return count; +} + /* * Converts the DGC registry value read from the TSC2101 registry to * Alsa mixer volume format (0 - 100). @@ -271,14 +312,11 @@ /* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */ /* NOTE: 0 is minimum volume and not mute */ volume = get_mixer_volume_as_headset_gain_control_volume(mixerVol); - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HEADSET_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL); /* preserve the old mute settings */ val &= ~(HGC_ADPGA_HED(INPUT_VOLUME_MAX)); val |= HGC_ADPGA_HED(volume); - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HEADSET_GAIN_CTRL, - val); + omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val); retVal = 1; M_DPRINTK("to registry = %d\n", val); @@ -305,71 +343,37 @@ * NOTE: 0 is minimum volume and not mute */ volume = get_mixer_volume_as_headset_gain_control_volume(mixerVol); - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL); /* preserve the old mute settigns */ val &= ~(HNGC_ADPGA_HND(INPUT_VOLUME_MAX)); val |= HNGC_ADPGA_HND(volume); - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HANDSET_GAIN_CTRL, - val); + omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val); retVal = 1; M_DPRINTK("to registry = %d\n", val); return retVal; } -void init_record_sources(void) -{ - /* Mute Analog Sidetone - * analog sidetone gain db? - * Cell Phone In not connected to ADC - * Input selected by MICSEL connected to ADC - */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_MIXER_PGA_CTRL, - MPC_ASTMU | MPC_ASTG(0x40) | ~MPC_CPADC | MPC_MICADC); - /* Set record source, Select MIC_INHED input for headset */ - set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED); -} - void set_loudspeaker_to_playback_target(void) { - u16 val; - - /* power down sp1, sp2 and loudspeaker */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_CODEC_POWER_CTRL, + /* power down SPK1, SPK2 and loudspeaker */ + omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL, CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF); /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled * 1dB AGC hysteresis * MICes bias 2V */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_4, - AC4_MB_HED(0)); + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0)); /* DAC left and right routed to SPK1/SPK2 * SPK1/SPK2 unmuted - * keyclicks routed to SPK1/SPK2 - */ - val = AC5_DIFFIN | + * Keyclicks routed to SPK1/SPK2 */ + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5, + AC5_DIFFIN | AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 | - AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 | - AC5_HDSCPTC; - val = val & ~AC5_HDSCPTC; - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_5, - val); - - /* powerdown spk1/out32n and spk2 */ - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_POWERDOWN_STS); - val = val & ~(~PS_SPK1FL | ~PS_HNDFL | PS_LSPKFL); - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_POWERDOWN_STS, - val); - - /* routing selected to SPK1 goes to OUT8P/OUT84 alsa. (loudspeaker) + AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2); + + /* routing selected to SPK1 goes also to OUT8P/OUT8N. (loudspeaker) * analog sidetone routed to loudspeaker * buzzer pga routed to loudspeaker * keyclick routing to loudspeaker @@ -381,43 +385,242 @@ * Enable loudspeaker short protection control (0 = enable protection) * VGND short protection control (0 = enable protection) */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_6, + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6, AC6_SPL2LSK | AC6_AST2LSK | AC6_BUZ2LSK | AC6_KCL2LSK | - AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO | - ~AC6_MUTLSPK | ~AC6_MUTSPK2 | ~AC6_LDSCPTC | ~AC6_VGNDSCPTC); + AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO); current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER; } void set_headphone_to_playback_target(void) { - /* power down sp1, sp2 and loudspeaker */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_CODEC_POWER_CTRL, + /* power down SPK1, SPK2 and loudspeaker */ + omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL, CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF); /* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */ /* 1dB AGC hysteresis */ /* MICes bias 2V */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_4, - AC4_MB_HED(0)); - - /* DAC left and right routed to SPK2 */ - /* SPK1/2 unmuted */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_5, + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0)); + + /* DAC left and right routed to SPK1/SPK2 + * SPK1/SPK2 unmuted + * Keyclicks routed to SPK1/SPK2 */ + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5, AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 | AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 | AC5_HDSCPTC); - - /* OUT8P/N muted, CPOUT muted */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_6, + + /* OUT8P/OUT8N muted, CPOUT muted */ + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6, AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC | AC6_VGNDSCPTC); current_playback_target = PLAYBACK_TARGET_HEADPHONE; } +void set_telephone_to_playback_target(void) +{ + /* + * 0110 1101 0101 1100 + * power down MICBIAS_HED, Analog sidetone, SPK2, DAC, + * Driver virtual ground, loudspeaker. Values D2-d5 are flags. + */ + omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL, + CPC_MBIAS_HED | CPC_ASTPWD | CPC_SP2PWDN | CPC_DAPWDN | + CPC_VGPWDN | CPC_LSPWDN); + + /* + * 0010 1010 0100 0000 + * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled + * 1dB AGC hysteresis + * MICes bias 2V + */ + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, + AC4_MB_HND | AC4_MB_HED(0) | AC4_AGCHYS(1) | + AC4_BISTPD | AC4_ASSTPD | AC4_DASTPD); + printk("set_telephone_to_playback_target(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4)); + + /* + * 1110 0010 0000 0010 + * DAC left and right routed to SPK1/SPK2 + * SPK1/SPK2 unmuted + * keyclicks routed to SPK1/SPK2 + */ + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5, + AC5_DIFFIN | AC5_DAC2SPK1(3) | + AC5_CPI2SPK1 | AC5_MUTSPK2); + + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6, + AC6_MIC2CPO | AC6_MUTLSPK | + AC6_LDSCPTC | AC6_VGNDSCPTC | AC6_CAPINTF); + current_playback_target = PLAYBACK_TARGET_CELLPHONE; +} + +/* + * 1100 0101 1101 0000 + * + * #define MPC_ASTMU TSC2101_BIT(15) + * #define MPC_ASTG(ARG) (((ARG) & 0x7F) << 8) + * #define MPC_MICSEL(ARG) (((ARG) & 0x07) << 5) + * #define MPC_MICADC TSC2101_BIT(4) + * #define MPC_CPADC TSC2101_BIT(3) + * #define MPC_ASTGF (0x01) + */ +static void set_telephone_to_record_source(void) +{ + u16 val; + + /* + * D0 = 0: + * --> AGC is off for handset input. + * --> ADC PGA is controlled by the ADMUT_HDN + ADPGA_HND + * (D15, D14-D8) + * D4 - D1 = 0000 + * --> AGC time constant for handset input, + * attack time = 8 mc, decay time = 100 ms + * D7 - D5 = 000 + * --> AGC Target gain for handset input = -5.5 db + * D14 - D8 = 011 1100 + * --> ADC handset PGA settings = 60 = 30 db + * D15 = 0 + * --> Handset input ON (unmuted) + */ + val = 0x3c00; // 0011 1100 0000 0000 = 60 = 30 + omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val); + + /* + * D0 = 0 + * --> AGC is off for headset/Aux input + * --> ADC headset/Aux PGA is contoller by ADMUT_HED + ADPGA_HED + * (D15, D14-D8) + * D4 - D1 = 0000 + * --> Agc constant for headset/Aux input, + * attack time = 8 mc, decay time = 100 ms + * D7 - D5 = 000 + * --> AGC target gain for headset input = -5.5 db + * D14 - D8 = 000 0000 + * --> Adc headset/AUX pga settings = 0 db + * D15 = 1 + * --> Headset/AUX input muted + * + * Mute headset aux input + */ + val = 0x8000; // 1000 0000 0000 0000 + omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val); + set_record_source(REC_SRC_MICIN_HND_AND_AUX1); + + // hacks start + /* D0 = flag, Headset/Aux or handset PGA flag + * --> & with 1 (= 1 -->gain applied == pga register settings) + * D1 = 0, DAC channel PGA soft stepping control + * --> 0.5 db change every WCLK + * D2 = flag, DAC right channel PGA flag + * --> & with 1 + * D3 = flag, DAC left channel PGA flag + * -- > & with 1 + * D7 - D4 = 0001, keyclick length + * --> 4 periods key clicks + * D10 - D8 = 100, keyclick frequenzy + * --> 1 kHz, + * D11 = 0, Headset/Aux or handset soft stepping control + * --> 0,5 db change every WCLK or ADWS + * D14 -D12 = 100, Keyclick applitude control + * --> Medium amplitude + * D15 = 0, keyclick disabled + */ + val = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_2); + val = val & 0x441d; + val = val | 0x4410; // D14, D10, D4 bits == 1 + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_2, val); + + /* + * D0 = 0 (reserved, write always 0) + * D1 = flag, + * --> & with 1 + * D2 - D5 = 0000 (reserved, write always 0000) + * D6 = 1 + * --> MICBIAS_HND = 2.0 v + * D8 - D7 = 00 + * --> MICBIAS_HED = 3.3 v + * D10 - D9 = 01, + * --> Mic AGC hysteric selection = 2 db + * D11 = 1, + * --> Disable buzzer PGA soft stepping + * D12 = 0, + * --> Enable CELL phone PGA soft stepping control + * D13 = 1 + * --> Disable analog sidetone soft stepping control + * D14 = 0 + * --> Enable DAC PGA soft stepping control + * D15 = 0, + * --> Enable headset/Aux or Handset soft stepping control + */ + val = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4); + val = val & 0x2a42; // 0010 1010 0100 0010 + val = val | 0x2a40; // bits D13, D11, D9, D6 == 1 + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, val); + printk("set_telephone_to_record_source(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4)); + /* + * D0 = 0 + * --> reserved, write always = 0 + * D1 = flag, read only + * --> & with 1 + * D5 - D2 = 1111, Buzzer input PGA settings + * --> 0 db + * D6 = 1, + * --> power down buzzer input pga + * D7 = flag, read only + * --> & with 1 + * D14 - D8 = 101 1101 + * --> 12 DB + * D15 = 0 + * --> power up cell phone input PGA + */ + val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL); + val = val & 0x5dfe; + val = val | 0x5dfe; // bits, D14, D12, D11, D10, D8, D6, D5,D4,D3,D2 + omap_tsc2101_audio_write(TSC2101_BUZZER_GAIN_CTRL, val); + + /* D6 - D0 = 000 1001 + * --> -4.5 db for DAC right channel volume control + * D7 = 1 + * --> DAC right channel muted + * D14 - D8 = 000 1001 + * --> -4.5 db for DAC left channel volume control + * D15 = 1 + * --> DAC left channel muted + */ + //val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL); + val = 0x8989; + omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val); + + /* 0000 0000 0100 0000 + * + * D1 - D0 = 0 + * --> GPIO 1 pin output is three stated + * D2 = 0 + * --> Disaple GPIO2 for CLKOUT mode + * D3 = 0 + * --> Disable GPUI1 for interrupt detection + * D4 = 0 + * --> Disable GPIO2 for headset detection interrupt + * D5 = reserved, always 0 + * D7 - D6 = 01 + * --> 8 ms clitch detection + * D8 = reserved, write only 0 + * D10 -D9 = 00 + * --> 16 ms de bouncing programmatitily + * for glitch detection during headset detection + * D11 = flag for button press + * D12 = flag for headset detection + * D14-D13 = 00 + * --> type of headset detected = 00 == no stereo headset deected + * D15 = 0 + * --> Disable headset detection + * + * */ + val = 0x40; + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, val); +} + /* * Checks whether the headset is detected. * If headset is detected, the type is returned. Type can be @@ -433,8 +636,7 @@ u16 curVal; curType = 0; /* not detected */ - curVal = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_7); + curVal = omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_7); curDetected = curVal & AC7_HDDETFL; if (curDetected) { printk("headset detected, checking type from %d \n", curVal); @@ -461,13 +663,10 @@ * AGC enable for handset input * Handset input not muted */ - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HANDSET_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL); val = val | HNGC_AGCEN_HND; val = val & ~HNGC_ADMUT_HND; - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HANDSET_GAIN_CTRL, - val); + omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val); /* mic input volume control * SET_MIC in the OSS driver @@ -479,7 +678,7 @@ */ set_mixer_volume_as_dac_gain_control_volume(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME); /* unmute */ - dac_gain_control_unmute_control(1, 1); + dac_gain_control_unmute(1, 1); } /* @@ -490,11 +689,11 @@ FN_IN; /* Headset/Hook switch detect enabled */ - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_AUDIO_CTRL_7, - AC7_DETECT); + omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, AC7_DETECT); - init_record_sources(); + /* Select headset to record source (MIC_INHED)*/ + set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED); + /* Init loudspeaker as a default playback target*/ init_playback_targets(); FN_OUT(0); @@ -503,7 +702,7 @@ static int __pcm_playback_target_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { static char *texts[PLAYBACK_TARGET_COUNT] = { - "Loudspeaker", "Headphone" + "Loudspeaker", "Headphone", "Cellphone" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -533,12 +732,18 @@ if ((curVal >= 0) && (curVal < PLAYBACK_TARGET_COUNT) && (curVal != current_playback_target)) { - if (curVal == 0) { - set_loudspeaker_to_playback_target(); + if (curVal == PLAYBACK_TARGET_LOUDSPEAKER) { + set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED); + set_loudspeaker_to_playback_target(); } - else { + else if (curVal == PLAYBACK_TARGET_HEADPHONE) { + set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HND); set_headphone_to_playback_target(); } + else if (curVal == PLAYBACK_TARGET_CELLPHONE) { + set_telephone_to_record_source(); + set_telephone_to_playback_target(); + } retVal = 1; } return retVal; @@ -563,7 +768,7 @@ u16 volR; u16 val; - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL); M_DPRINTK("registry value = %d!\n", val); volL = DGC_DALVL_EXTRACT(val); volR = DGC_DARVL_EXTRACT(val); @@ -603,16 +808,16 @@ */ static int __pcm_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL); + u16 val = omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL); - ucontrol->value.integer.value[0] = IS_DGC_DALMU_UNMUTED(val); - ucontrol->value.integer.value[1] = IS_DGC_DARMU_UNMUTED(val); + ucontrol->value.integer.value[0] = IS_UNMUTED(15, val); // left + ucontrol->value.integer.value[1] = IS_UNMUTED(7, val); // right return 0; } static int __pcm_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - return dac_gain_control_unmute_control(ucontrol->value.integer.value[0], + return dac_gain_control_unmute(ucontrol->value.integer.value[0], ucontrol->value.integer.value[1]); } @@ -630,8 +835,7 @@ u16 val; u16 vol; - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HEADSET_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL); M_DPRINTK("registry value = %d\n", val); vol = HGC_ADPGA_HED_EXTRACT(val); vol = vol & ~HGC_ADMUT_HED; @@ -662,38 +866,17 @@ */ static int __headset_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HEADSET_GAIN_CTRL); - ucontrol->value.integer.value[0] = IS_DGC_HGCMU_UNMUTED(val); + u16 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL); + ucontrol->value.integer.value[0] = IS_UNMUTED(15, val); return 0; } static int __headset_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - int count = 0; - u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HEADSET_GAIN_CTRL); - /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on - * so if values are same, it's time to change the registry value... - */ - if (ucontrol->value.integer.value[0] == GET_DGC_HGCMU_BIT_VALUE(val)) { - if (ucontrol->value.integer.value[0] == 0) { - /* mute --> turn bit on */ - val = val | HGC_ADMUT_HED; - } - else { - /* unmute --> turn bit off */ - val = val & ~HGC_ADMUT_HED; - } - count++; - M_DPRINTK("changed value, is_unmuted = %d\n", IS_DGC_HGCMU_UNMUTED(val)); - } - if (count) { - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HEADSET_GAIN_CTRL, - val); - } - return count; + // mute/unmute headset + return adc_pga_unmute_control(ucontrol->value.integer.value[0], + TSC2101_HEADSET_GAIN_CTRL, + 15); } static int __handset_playback_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -710,7 +893,7 @@ u16 val; u16 vol; - val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL); + val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL); M_DPRINTK("registry value = %d\n", val); vol = HNGC_ADPGA_HND_EXTRACT(val); vol = vol & ~HNGC_ADMUT_HND; @@ -740,42 +923,74 @@ */ static int __handset_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL); - ucontrol->value.integer.value[0] = IS_DGC_HNGCMU_UNMUTED(val); + u16 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL); + ucontrol->value.integer.value[0] = IS_UNMUTED(15, val); return 0; } static int __handset_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { - int count = 0; - u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL); - - /* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on - * so if values are same, it's time to change the registry value... - */ - if (ucontrol->value.integer.value[0] == GET_DGC_HNGCMU_BIT_VALUE(val)) { - if (ucontrol->value.integer.value[0] == 0) { - /* mute --> turn bit on */ - val = val | HNGC_ADMUT_HND; - } - else { - /* unmute --> turn bit off */ - val = val & ~HNGC_ADMUT_HND; - } - M_DPRINTK("changed value, is_unmuted = %d\n", IS_DGC_HNGCMU_UNMUTED(val)); - count++; - } - if (count) { - omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, - TSC2101_HANDSET_GAIN_CTRL, - val); - } - return count; + // handset mute/unmute + return adc_pga_unmute_control(ucontrol->value.integer.value[0], + TSC2101_HANDSET_GAIN_CTRL, + 15); +} + +static int __cellphone_input_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +/* When BGC_MUT_CP (bit 15) = 1, power down cellphone input pga. + * When BGC_MUT_CP = 0, power up cellphone input pga. + */ +static int __cellphone_input_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL); + ucontrol->value.integer.value[0] = IS_UNMUTED(15, val); + return 0; +} + +static int __cellphone_input_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + return adc_pga_unmute_control(ucontrol->value.integer.value[0], + TSC2101_BUZZER_GAIN_CTRL, + 15); +} + +static int __buzzer_input_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +/* When BGC_MUT_BU (bit 6) = 1, power down cellphone input pga. + * When BGC_MUT_BU = 0, power up cellphone input pga. + */ +static int __buzzer_input_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL); + ucontrol->value.integer.value[0] = IS_UNMUTED(6, val); + return 0; +} + +static int __buzzer_input_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + return adc_pga_unmute_control(ucontrol->value.integer.value[0], + TSC2101_BUZZER_GAIN_CTRL, + 6); } static snd_kcontrol_new_t tsc2101_control[] __devinitdata = { { - .name = "Playback Playback Route", + .name = "Target Playback Route", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .index = 0, .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -801,7 +1016,7 @@ }, { .name = "Headset Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .index = 1, + .index = 0, .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = __headset_playback_volume_info, .get = __headset_playback_volume_get, @@ -809,7 +1024,7 @@ }, { .name = "Headset Playback Switch", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .index = 1, + .index = 0, .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = __headset_playback_switch_info, .get = __headset_playback_switch_get, @@ -817,7 +1032,7 @@ }, { .name = "Handset Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .index = 2, + .index = 0, .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = __handset_playback_volume_info, .get = __handset_playback_volume_get, @@ -825,12 +1040,28 @@ }, { .name = "Handset Playback Switch", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .index = 2, + .index = 0, .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = __handset_playback_switch_info, .get = __handset_playback_switch_get, .put = __handset_playback_switch_put, - } + }, { + .name = "Cellphone Input Switch", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .index = 0, + .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = __cellphone_input_switch_info, + .get = __cellphone_input_switch_get, + .put = __cellphone_input_switch_put, + }, { + .name = "Buzzer Input Switch", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .index = 0, + .access= SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = __buzzer_input_switch_info, + .get = __buzzer_input_switch_get, + .put = __buzzer_input_switch_put, + } }; #ifdef CONFIG_PM diff -Naur linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.h h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.h --- linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.h 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.h 2006-03-30 23:15:31.000000000 +0300 @@ -56,20 +56,21 @@ #define INPUT_VOLUME_MAX 0x7D #define INPUT_VOLUME_RANGE (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN) -#define PLAYBACK_TARGET_COUNT 0x02 +#define PLAYBACK_TARGET_COUNT 0x03 #define PLAYBACK_TARGET_LOUDSPEAKER 0x00 #define PLAYBACK_TARGET_HEADPHONE 0x01 +#define PLAYBACK_TARGET_CELLPHONE 0x02 /* following are used for register 03h Mixer PGA control bits D7-D5 for selecting record source */ #define REC_SRC_TARGET_COUNT 0x08 -#define REC_SRC_SINGLE_ENDED_MICIN_HED MPC_MICSEL(0) // oss code referred to MIXER_LINE -#define REC_SRC_SINGLE_ENDED_MICIN_HND MPC_MICSEL(1) // oss code referred to MIXER_MIC -#define REC_SRC_SINGLE_ENDED_AUX1 MPC_MICSEL(2) -#define REC_SRC_SINGLE_ENDED_AUX2 MPC_MICSEL(3) -#define REC_SRC_MICIN_HED_AND_AUX1 MPC_MICSEL(4) -#define REC_SRC_MICIN_HED_AND_AUX2 MPC_MICSEL(5) -#define REC_SRC_MICIN_HND_AND_AUX1 MPC_MICSEL(6) -#define REC_SRC_MICIN_HND_AND_AUX2 MPC_MICSEL(7) +#define REC_SRC_SINGLE_ENDED_MICIN_HED 0x00 // oss code referred to MIXER_LINE +#define REC_SRC_SINGLE_ENDED_MICIN_HND 0x01 // oss code referred to MIXER_MIC +#define REC_SRC_SINGLE_ENDED_AUX1 0x02 +#define REC_SRC_SINGLE_ENDED_AUX2 0x03 +#define REC_SRC_MICIN_HED_AND_AUX1 0x04 +#define REC_SRC_MICIN_HED_AND_AUX2 0x05 +#define REC_SRC_MICIN_HND_AND_AUX1 0x06 +#define REC_SRC_MICIN_HND_AND_AUX2 0x07 #define DEFAULT_OUTPUT_VOLUME 90 // default output volume to dac dgc #define DEFAULT_INPUT_VOLUME 20 // default record volume diff -Naur linux-2.6.16.16/sound/oss/Kconfig h6300_dev/sound/oss/Kconfig --- linux-2.6.16.16/sound/oss/Kconfig 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/sound/oss/Kconfig 2006-02-06 15:36:21.000000000 +0200 @@ -13,8 +13,8 @@ config SOUND_OMAP_TSC2101 tristate "TSC2101 Stereo Codec" - depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4 || MACH_OMAP_APOLLON) - select OMAP_TSC2101 if ( MACH_OMAP_H2 || MACH_OMAP_H3 ) + depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4 || MACH_OMAP_APOLLON || MACH_OMAP_H6300) + select OMAP_TSC2101 if ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H6300 ) select OMAP_UWIRE if ARCH_OMAP1 ---help--- Tsc2101 Audio Codec Driver for OMAP will be enabled. diff -Naur linux-2.6.16.16/sound/oss/omap-audio-tsc2101.c h6300_dev/sound/oss/omap-audio-tsc2101.c --- linux-2.6.16.16/sound/oss/omap-audio-tsc2101.c 2006-05-17 21:41:31.000000000 +0300 +++ h6300_dev/sound/oss/omap-audio-tsc2101.c 2006-04-02 00:23:01.000000000 +0300 @@ -48,7 +48,7 @@ #include "omap-audio.h" #include "omap-audio-dma-intfc.h" #include -#ifdef CONFIG_ARCH_OMAP16XX +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300) #include <../drivers/ssi/omap-uwire.h> #include #elif defined(CONFIG_ARCH_OMAP24XX) @@ -73,10 +73,16 @@ #ifdef CONFIG_ARCH_OMAP16XX #define PLATFORM_NAME "OMAP16XX" +#elif CONFIG_MACH_OMAP_H6300 +#define PLATFORM_NAME "OMAP15XX" #elif defined(CONFIG_ARCH_OMAP24XX) #define PLATFORM_NAME "OMAP2" #endif +#if CONFIG_ARCH_OMAP16XX +#define OMAP_DSP_BASE 0xE0000000 +#endif + /* Define to set the tsc as the master w.r.t McBSP */ #define TSC_MASTER @@ -123,7 +129,7 @@ /*********** Debug Macros ********/ /* To Generate a rather shrill tone -test the entire path */ //#define TONE_GEN -/* To Generate a tone for each keyclick - test the tsc,spi paths*/ +///* To Generate a tone for each keyclick - test the tsc,spi paths*/ //#define TEST_KEYCLICK /* To dump the tsc registers for debug */ //#define TSC_DUMP_REGISTERS @@ -230,6 +236,17 @@ }; static struct omap_mcbsp_reg_cfg initial_config = { +#ifdef CONFIG_MACH_OMAP_H6300 + .spcr2 = 0x0005, + .spcr1 = 0x0005, + .rcr2 = 0x8041, + .rcr1 = 0x8041, + .xcr2 = 0x00a1, + .xcr1 = 0x00a1, + .srgr2 = 0xb000, + .srgr1 = 0xb000, + .pcr0 = 0x0081, +#else .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), .spcr1 = RINTM(3) | RRST, .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) | @@ -253,6 +270,7 @@ #endif /* tsc Master defs */ #endif /* platform specific inits */ +#endif /* CONFIG_MACH_OMAP_H6300 */ }; /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/