Browse files

GT-I9100_JB_Opensource

  • Loading branch information...
1 parent 41561c8 commit ae5dd48f006a339a5f3ec879fe1fd2bfdaa5e874 @gokhanmoral committed Feb 16, 2013
Showing with 24,104 additions and 60 deletions.
  1. +3 −3 Makefile
  2. +3,155 −0 arch/arm/configs/u1_defconfig
  3. +6 −13 arch/arm/configs/{u1nfc_defconfig → u1_defconfig____}
  4. +0 −2 arch/arm/mach-exynos/Kconfig
  5. +11 −0 arch/arm/mach-exynos/include/mach/secmem.h
  6. +12 −0 arch/arm/mach-exynos/mach-midas.c
  7. +0 −5 arch/arm/mach-exynos/mach-u1.c
  8. +114 −3 arch/arm/mach-exynos/secmem-allocdev.c
  9. +2 −7 arch/arm/mach-exynos/u1-gpio.c
  10. +0 −2 drivers/Kconfig
  11. +0 −2 drivers/Makefile
  12. +1 −0 drivers/char/Kconfig
  13. +10 −4 drivers/char/exynos_mem.c
  14. +2 −2 drivers/char/mem.c
  15. +17 −0 drivers/char/s3c_mem.c
  16. +2 −2 drivers/gpu/Makefile
  17. +0 −1 drivers/gpu/drm/Makefile
  18. +2 −2 drivers/gpu/ion/ion.c
  19. +0 −1 drivers/input/keyboard/Makefile
  20. +2,651 −0 drivers/input/touchscreen/465GS37_V12.h
  21. +479 −0 drivers/input/touchscreen/cyttsp4_btn.c
  22. +753 −0 drivers/input/touchscreen/cyttsp4_bus.c
  23. +530 −0 drivers/input/touchscreen/cyttsp4_debug.c
  24. +1,907 −0 drivers/input/touchscreen/cyttsp4_device_access.c
  25. +128 −0 drivers/input/touchscreen/cyttsp4_device_access.h
  26. +35 −0 drivers/input/touchscreen/cyttsp4_i2c.h
  27. +1,453 −0 drivers/input/touchscreen/cyttsp4_loader.c
  28. +684 −0 drivers/input/touchscreen/cyttsp4_mt_common.c
  29. +83 −0 drivers/input/touchscreen/cyttsp4_mt_common.h
  30. +108 −0 drivers/input/touchscreen/cyttsp4_mtb.c
  31. +500 −0 drivers/input/touchscreen/cyttsp4_regs.h
  32. +5 −6 drivers/media/tdmb/tdmb.c
  33. +4 −4 drivers/media/video/samsung/Makefile
  34. +144 −1 drivers/media/video/samsung/fimc/fimc_output.c
  35. +12 −0 drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_core.c
  36. +11 −0 drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
  37. +295 −0 drivers/media/video/samsung/mali_r3p1/Kbuild_module
  38. +30 −0 drivers/media/video/samsung/mali_r3p1/Kconfig_module
  39. +338 −0 drivers/media/video/samsung/mali_r3p1/Makefile
  40. +97 −0 drivers/media/video/samsung/mali_r3p1/Makefile_module
  41. +1 −0 drivers/media/video/samsung/mali_r3p1/arch
  42. +1 −0 drivers/media/video/samsung/mali_r3p1/arch-debug
  43. +85 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m300/config.h
  44. +92 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m400-1-direct/config.h
  45. +85 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m400-1-pmu/config.h
  46. +77 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m400-1/config.h
  47. +91 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m400-2/config.h
  48. +105 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m400-3/config.h
  49. +119 −0 drivers/media/video/samsung/mali_r3p1/arch-pb-virtex5-m400-4/config.h
  50. +154 −0 drivers/media/video/samsung/mali_r3p1/arch-pegasus-m400/config.h
  51. +1 −0 drivers/media/video/samsung/mali_r3p1/arch-release
  52. +174 −0 drivers/media/video/samsung/mali_r3p1/arch-ve-virtex6-m450-8/config.h
  53. +391 −0 drivers/media/video/samsung/mali_r3p1/common/mali_block_allocator.c
  54. +18 −0 drivers/media/video/samsung/mali_r3p1/common/mali_block_allocator.h
  55. +218 −0 drivers/media/video/samsung/mali_r3p1/common/mali_cluster.c
  56. +44 −0 drivers/media/video/samsung/mali_r3p1/common/mali_cluster.h
  57. +46 −0 drivers/media/video/samsung/mali_r3p1/common/mali_device_pause_resume.c
  58. +31 −0 drivers/media/video/samsung/mali_r3p1/common/mali_device_pause_resume.h
  59. +285 −0 drivers/media/video/samsung/mali_r3p1/common/mali_dlbu.c
  60. +45 −0 drivers/media/video/samsung/mali_r3p1/common/mali_dlbu.h
  61. +746 −0 drivers/media/video/samsung/mali_r3p1/common/mali_gp.c
  62. +46 −0 drivers/media/video/samsung/mali_r3p1/common/mali_gp.h
  63. +49 −0 drivers/media/video/samsung/mali_r3p1/common/mali_gp_job.c
  64. +131 −0 drivers/media/video/samsung/mali_r3p1/common/mali_gp_job.h
  65. +443 −0 drivers/media/video/samsung/mali_r3p1/common/mali_gp_scheduler.c
  66. +30 −0 drivers/media/video/samsung/mali_r3p1/common/mali_gp_scheduler.h
  67. +841 −0 drivers/media/video/samsung/mali_r3p1/common/mali_group.c
  68. +146 −0 drivers/media/video/samsung/mali_r3p1/common/mali_group.h
  69. +46 −0 drivers/media/video/samsung/mali_r3p1/common/mali_hw_core.c
  70. +71 −0 drivers/media/video/samsung/mali_r3p1/common/mali_hw_core.h
  71. +183 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_common.h
  72. +980 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_core.c
  73. +39 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_core.h
  74. +184 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_descriptor_mapping.c
  75. +101 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_descriptor_mapping.h
  76. +346 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_mem_os.c
  77. +37 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_mem_os.h
  78. +376 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_memory_engine.c
  79. +152 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_memory_engine.h
  80. +218 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_utilization.c
  81. +44 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_utilization.h
  82. +51 −0 drivers/media/video/samsung/mali_r3p1/common/mali_kernel_vsync.c
  83. +414 −0 drivers/media/video/samsung/mali_r3p1/common/mali_l2_cache.c
  84. +43 −0 drivers/media/video/samsung/mali_r3p1/common/mali_l2_cache.h
  85. +71 −0 drivers/media/video/samsung/mali_r3p1/common/mali_mem_validation.c
  86. +19 −0 drivers/media/video/samsung/mali_r3p1/common/mali_mem_validation.h
  87. +1,319 −0 drivers/media/video/samsung/mali_r3p1/common/mali_memory.c
  88. +82 −0 drivers/media/video/samsung/mali_r3p1/common/mali_memory.h
  89. +619 −0 drivers/media/video/samsung/mali_r3p1/common/mali_mmu.c
  90. +55 −0 drivers/media/video/samsung/mali_r3p1/common/mali_mmu.h
  91. +475 −0 drivers/media/video/samsung/mali_r3p1/common/mali_mmu_page_directory.c
  92. +100 −0 drivers/media/video/samsung/mali_r3p1/common/mali_mmu_page_directory.h
Sorry, we could not display the entire diff because it was too big.
View
6 Makefile
@@ -192,9 +192,9 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
export KBUILD_BUILDHOST := $(SUBARCH)
-ARCH = arm
-CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
-
+ARCH ?= arm
+CROSS_COMPILE ?= /opt/toolchains/arm-eabi-4.4.3/bin/arm-eabi-
+
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
SRCARCH := $(ARCH)
View
3,155 arch/arm/configs/u1_defconfig
3,155 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
19 arch/arm/configs/u1nfc_defconfig → arch/arm/configs/u1_defconfig____
@@ -129,7 +129,7 @@ CONFIG_PERF_USE_VMALLOC=y
#
# Kernel Performance Events And Counters
#
-CONFIG_PERF_EVENTS=y
+# CONFIG_PERF_EVENTS is not set
# CONFIG_PERF_COUNTERS is not set
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
CONFIG_VM_EVENT_COUNTERS=y
@@ -138,7 +138,7 @@ CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
-CONFIG_PROFILING=y
+# CONFIG_PROFILING is not set
CONFIG_TRACEPOINTS=y
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -421,7 +421,7 @@ CONFIG_TARGET_LOCALE_EUR=y
# CONFIG_TARGET_LOCALE_LTN is not set
# CONFIG_TARGET_LOCALE_KOR is not set
# CONFIG_TARGET_LOCALE_NAATT_TEMP is not set
-CONFIG_TARGET_LOCALE_EUR_U1_NFC=y
+# CONFIG_TARGET_LOCALE_EUR_U1_NFC is not set
# CONFIG_TARGET_LOCALE_NTT is not set
# CONFIG_MACH_SMDK4X12 is not set
# CONFIG_MACH_MIDAS is not set
@@ -568,7 +568,7 @@ CONFIG_PREEMPT=y
CONFIG_HZ=200
# CONFIG_THUMB2_KERNEL is not set
CONFIG_AEABI=y
-CONFIG_OABI_COMPAT=y
+# CONFIG_OABI_COMPAT is not set
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
CONFIG_HAVE_ARCH_PFN_VALID=y
@@ -2627,13 +2627,6 @@ CONFIG_WTL_ENCRYPTION_FILTER=y
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-CONFIG_J4FS=m
-# CONFIG_J4FS_USE_XSR is not set
-# CONFIG_J4FS_USE_FSR is not set
-CONFIG_J4FS_USE_MOVI=y
-CONFIG_J4FS_DEVNAME="/dev/block/mmcblk0p4"
-CONFIG_J4FS_PAGE_SHIFT=11
-CONFIG_J4FS_BLOCK_COUNT=20
# CONFIG_NETWORK_FILESYSTEMS is not set
#
@@ -2733,8 +2726,8 @@ CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_SPARSE_RCU_POINTER is not set
View
2 arch/arm/mach-exynos/Kconfig
@@ -1142,8 +1142,6 @@ config IRON_BD
config GRANDE_BD
bool "Grande common Board"
-
-
config WRITEBACK_ENABLED
bool "Samsung Writeback Enable"
help
View
11 arch/arm/mach-exynos/include/mach/secmem.h
@@ -24,6 +24,17 @@ struct secchunk_info {
size_t size;
};
+struct secmem_fd_info {
+ uint32_t phys_addr;
+ size_t size;
+};
+
+struct secmem_fd_list {
+ struct secmem_fd_list *next;
+ struct secmem_fd_list *prev;
+ struct secmem_fd_info fdinfo;
+};
+
extern struct miscdevice secmem;
#if defined(CONFIG_ION)
struct secfd_info {
View
12 arch/arm/mach-exynos/mach-midas.c
@@ -3793,6 +3793,18 @@ static void __init exynos4_reserve(void)
CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMC1 * SZ_1K, 0x65800000, 0);
if (ret != 0)
panic("alloc failed for FIMC1\n");
+ else {
+ static struct cma_region fimc_reg = {
+ .name = "fimc1",
+ .size = CONFIG_VIDEO_SAMSUNG_MEMSIZE_FIMC1 * SZ_1K,
+ .start = 0x65800000,
+ .reserved = 1,
+ };
+
+ if (cma_early_region_register(&fimc_reg))
+ pr_err("S5P/CMA: Failed to register '%s'\n",
+ fimc_reg.name);
+ }
#endif
#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_M0)
View
5 arch/arm/mach-exynos/mach-u1.c
@@ -4681,7 +4681,6 @@ static struct sec_bat_adc_table_data temper_table_ADC7[] = {
};
#endif
-#define ADC_CH_VF 2
#define ADC_CH_TEMPERATURE_PMIC 6
#define ADC_CH_TEMPERATURE_LCD 7
@@ -4728,10 +4727,6 @@ static struct sec_bat_platform_data sec_bat_pdata = {
.adc_sub_table = temper_table_ADC7,
.adc_sub_channel = ADC_CH_TEMPERATURE_LCD,
.get_lpcharging_state = sec_bat_get_lpcharging_state,
-#if defined(CONFIG_TARGET_LOCALE_NAATT) || \
- defined(CONFIG_TARGET_LOCALE_NAATT_TEMP)
- .adc_vf_channel = ADC_CH_VF,
-#endif
#if defined(CONFIG_MACH_Q1_BD)
.initial_check = sec_bat_initial_check,
#else
View
117 arch/arm/mach-exynos/secmem-allocdev.c
@@ -34,6 +34,8 @@
struct miscdevice secmem;
struct secmem_crypto_driver_ftn *crypto_driver;
+struct secmem_fd_list g_fd_head;
+
#if defined(CONFIG_ION)
extern struct ion_device *ion_exynos;
#endif
@@ -63,16 +65,113 @@ static bool drm_onoff = false;
#define SECMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
+
+static void secmem_fd_list_init(struct secmem_fd_list *list)
+{
+ list->next = list;
+ list->prev = list;
+ list->fdinfo.phys_addr = 0;
+ list->fdinfo.size = 0;
+}
+
+static void secmem_fd_list_clear(struct secmem_fd_list *head)
+{
+ head->next = head;
+ head->prev = head;
+}
+
+static void secmem_fd_list_add(struct secmem_fd_list *new, struct secmem_fd_list *head)
+{
+ head->next->prev = new;
+ new->next = head->next;
+ new->prev = head;
+ head->next = new;
+}
+
+static void secmem_fd_list_del(struct secmem_fd_list *list)
+{
+ list->prev->next = list->next;
+ list->next->prev = list->prev;
+}
+
+static void init_secmem_fd_list(void)
+{
+ secmem_fd_list_init(&g_fd_head);
+}
+
+static void clear_secmem_fd_list(void)
+{
+ secmem_fd_list_clear(&g_fd_head);
+}
+
+static struct secmem_fd_list *secmem_fd_list_find(struct secmem_fd_list *head, uint32_t phys_addr, size_t size)
+{
+ struct secmem_fd_list *pos;
+
+ for (pos = head->next; pos != head; pos = pos->next) {
+ if ((pos->fdinfo.phys_addr == phys_addr) &&
+ (pos->fdinfo.size >= size))
+ return pos;
+ }
+
+ return NULL;
+}
+
+static int find_secmem_fd_list(struct secmem_fd_list *head, uint32_t phys_addr, size_t size)
+{
+ struct secmem_fd_list *fd_ent = NULL;
+
+ fd_ent = secmem_fd_list_find(head, phys_addr, size);
+ if (fd_ent == NULL)
+ return -1;
+
+ return 0;
+}
+
+static void put_secmem_fd_list(struct secmem_fd_info *secmem_fd)
+{
+ struct secmem_fd_list *new = NULL;
+
+ new = (struct secmem_fd_list *)kzalloc(sizeof(struct secmem_fd_list), GFP_KERNEL);
+
+ new->fdinfo.phys_addr = secmem_fd->phys_addr;
+ new->fdinfo.size = secmem_fd->size;
+
+ secmem_fd_list_add(new, &g_fd_head);
+}
+
+static int del_secmem_fd_list(struct secmem_region *region)
+{
+ struct secmem_fd_list *fd_ent = NULL;
+
+ fd_ent = secmem_fd_list_find(&g_fd_head, region->phys_addr, region->len);
+ if (fd_ent == NULL)
+ return -1;
+
+ secmem_fd_list_del(fd_ent);
+ kfree(fd_ent);
+
+ return 0;
+}
+
static int secmem_mmap(struct file *file, struct vm_area_struct *vma)
{
+ int ret;
unsigned long size = vma->vm_end - vma->vm_start;
+ uint32_t phys_addr = vma->vm_pgoff << 12;
BUG_ON(!SECMEM_IS_PAGE_ALIGNED(vma->vm_start));
BUG_ON(!SECMEM_IS_PAGE_ALIGNED(vma->vm_end));
vma->vm_flags |= VM_RESERVED;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ ret = find_secmem_fd_list(&g_fd_head, phys_addr, size);
+ if (ret < 0) {
+ printk(KERN_ERR "%s : Fail mmap due to Invalid address\n", __func__);
+ return -EAGAIN;
+ }
+
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
size, vma->vm_page_prot)) {
printk(KERN_ERR "%s : remap_pfn_range() failed!\n", __func__);
@@ -213,6 +312,7 @@ static long secmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case SECMEM_IOC_GET_ADDR:
{
struct secmem_region region;
+ struct secmem_fd_info secmem_fd;
if (copy_from_user(&region, (void __user *)arg,
sizeof(struct secmem_region)))
@@ -243,6 +343,11 @@ static long secmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
region.len, DMA_TO_DEVICE);
#endif
+ secmem_fd.phys_addr = region.phys_addr;
+ secmem_fd.size = region.len;
+
+ put_secmem_fd_list(&secmem_fd);
+
if (copy_to_user((void __user *)arg, &region,
sizeof(struct secmem_region)))
return -EFAULT;
@@ -262,12 +367,18 @@ static long secmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
pr_info("SECMEM_IOC_RELEASE_ADDR: size:%lu\n", region.len);
+ if (del_secmem_fd_list(&region) < 0) {
+ printk(KERN_ERR "%s: Release memory failed.\n", __func__);
+ return -EFAULT;
+ }
+
#ifndef CONFIG_DMA_CMA
kfree(region.virt_addr);
#else
dma_free_coherent(NULL, region.len, region.virt_addr,
region.phys_addr);
#endif
+
break;
}
@@ -308,9 +419,6 @@ static long secmem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
minfo.base = info.lower_bound;
minfo.size = info.total_size;
- printk("[minfo base] : 0x%x", minfo.base);
- printk("[minfo size] : 0x%x", minfo.size);
-
if (copy_to_user((void __user *)arg, &minfo, sizeof(minfo)))
return -EFAULT;
break;
@@ -353,6 +461,8 @@ static int __init secmem_init(void)
crypto_driver = NULL;
+ init_secmem_fd_list();
+
pm_runtime_enable(secmem.this_device);
return 0;
@@ -361,6 +471,7 @@ static int __init secmem_init(void)
static void __exit secmem_exit(void)
{
__pm_runtime_disable(secmem.this_device, false);
+ clear_secmem_fd_list();
misc_deregister(&secmem);
}
View
9 arch/arm/mach-exynos/u1-gpio.c
@@ -196,10 +196,6 @@ static struct gpio_init_data u1_init_gpios[] = {
S3C_GPIO_PULL_NONE, S5P_GPIO_DRVSTR_LV1}, /* GPIO_BOOT_MODE */
{EXYNOS4_GPX2(3), S3C_GPIO_INPUT, S3C_GPIO_SETPIN_NONE,
S3C_GPIO_PULL_NONE, S5P_GPIO_DRVSTR_LV1}, /* GPIO_FUEL_ALERT */
-#if defined(CONFIG_TARGET_LOCALE_NAATT_TEMP)
- {EXYNOS4_GPX2(4), S3C_GPIO_INPUT, S3C_GPIO_SETPIN_NONE,
- S3C_GPIO_PULL_DOWN, S5P_GPIO_DRVSTR_LV1}, /* NC */
-#endif
{EXYNOS4_GPX3(1), S3C_GPIO_OUTPUT, S3C_GPIO_SETPIN_ZERO,
S3C_GPIO_PULL_NONE, S5P_GPIO_DRVSTR_LV1}, /* GPIO_BT_WAKE */
{EXYNOS4_GPX3(2), S3C_GPIO_SFN(GPIO_DET_35_AF), S3C_GPIO_SETPIN_NONE,
@@ -215,7 +211,7 @@ static struct gpio_init_data u1_init_gpios[] = {
S3C_GPIO_PULL_NONE, S5P_GPIO_DRVSTR_LV1},
#endif /*CONFIG_TARGET_LOCALE_NA*/
-#if defined(CONFIG_TARGET_LOCALE_NA) || defined(CONFIG_TARGET_LOCALE_NAATT_TEMP)
+#if defined(CONFIG_TARGET_LOCALE_NA)
/* NC*/
{EXYNOS4_GPX3(5), S3C_GPIO_INPUT, S3C_GPIO_SETPIN_ZERO,
S3C_GPIO_PULL_DOWN, S5P_GPIO_DRVSTR_LV1},
@@ -472,8 +468,7 @@ static unsigned int u1_sleep_gpio_table[][3] = {
{EXYNOS4_GPB(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
{EXYNOS4_GPB(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
{EXYNOS4_GPB(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
-#elif defined(CONFIG_TARGET_LOCALE_NTT) \
- || defined(CONFIG_TARGET_LOCALE_NAATT_TEMP)
+#elif defined(CONFIG_TARGET_LOCALE_NTT)
{EXYNOS4_GPB(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
{EXYNOS4_GPB(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
{EXYNOS4_GPB(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
View
2 drivers/Kconfig
@@ -163,6 +163,4 @@ source "drivers/felica/Kconfig"
# Authentec
source "drivers/interceptor/Kconfig"
-
-
endmenu
View
2 drivers/Makefile
@@ -151,5 +151,3 @@ obj-$(CONFIG_AUTHENTEC_VPNCLIENT_INTERCEPTOR) += interceptor/
ifeq (1, $(shell if [ -d ./drivers/exfat ]; then echo 1; fi))
obj-y += exfat/
endif
-
-
View
1 drivers/char/Kconfig
@@ -638,6 +638,7 @@ config S3C_MEM
config EXYNOS_MEM
bool "Support for /dev/exynos-mem"
+ depends on CMA
default y
help
If you do say Y here, you can mmap using physically linear memories.
View
14 drivers/char/exynos_mem.c
@@ -18,6 +18,7 @@
#include <linux/uaccess.h>
#include <linux/highmem.h>
#include <linux/dma-mapping.h>
+#include <linux/cma.h>
#include <asm/cacheflush.h>
#include <plat/cpu.h>
@@ -83,6 +84,12 @@ static void cache_maint_phys(phys_addr_t start, size_t length, enum cacheop op)
size_t left = length;
phys_addr_t begin = start;
+ if (!cma_is_registered_region(start, length)) {
+ pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n",
+ __func__, length, start);
+ return;
+ }
+
if (!soc_is_exynos5250() && !soc_is_exynos5210()) {
if (length > (size_t) L1_FLUSH_ALL) {
flush_cache_all();
@@ -257,10 +264,9 @@ int exynos_mem_mmap(struct file *filp, struct vm_area_struct *vma)
pfn = mem->phybase;
}
- /* TODO: currently lowmem is only avaiable */
- if ((phys_to_virt(start) < (void *)PAGE_OFFSET) ||
- (phys_to_virt(start) >= high_memory)) {
- pr_err("[%s] invalid paddr(0x%08x)\n", __func__, start);
+ if (!cma_is_registered_region(start, size)) {
+ pr_err("[%s] handling non-cma region (%#x@%#x)is prohibited\n",
+ __func__, size, start);
return -EINVAL;
}
View
4 drivers/char/mem.c
@@ -934,8 +934,8 @@ static const struct memdev {
},
#endif
#ifdef CONFIG_EXYNOS_MEM
- [14] = {"exynos-mem", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
- | S_IWOTH, &exynos_mem_fops},
+ [14] = {"exynos-mem", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+ &exynos_mem_fops},
#endif
};
View
17 drivers/char/s3c_mem.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/mman.h>
#include <linux/dma-mapping.h>
+#include <linux/cma.h>
#include <linux/unistd.h>
#include <linux/version.h>
@@ -324,6 +325,14 @@ long s3c_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mutex_unlock(&mem_share_alloc_lock);
return -EFAULT;
}
+
+ if (!cma_is_registered_region(param.phy_addr, param.size)) {
+ pr_err("%s: %#x@%#x is allowed to map\n",
+ __func__, param.size, param.phy_addr);
+ mutex_unlock(&mem_cacheable_share_alloc_lock);
+ return -EINVAL;
+ }
+
flag = MEM_ALLOC_SHARE;
physical_address = param.phy_addr;
DEBUG("param.phy_addr = %08x, %d\n",
@@ -361,6 +370,14 @@ long s3c_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mutex_unlock(&mem_cacheable_share_alloc_lock);
return -EFAULT;
}
+
+ if (!cma_is_registered_region(param.phy_addr, param.size)) {
+ pr_err("%s: %#x@%#x is allowed to map\n",
+ __func__, param.size, param.phy_addr);
+ mutex_unlock(&mem_cacheable_share_alloc_lock);
+ return -EINVAL;
+ }
+
flag = MEM_ALLOC_CACHEABLE_SHARE;
physical_address = param.phy_addr;
DEBUG("param.phy_addr = %08x, %d\n",
View
4 drivers/gpu/Makefile
@@ -1,6 +1,6 @@
ifeq ($(CONFIG_VITHAR_HWVER_R0P0),y)
-obj-y += drm/ vga/ stub/ ion/
+obj-y += drm/ vga/ stub/ ion/
else
-obj-y += drm/ vga/ stub/ ion/
+obj-y += drm/ vga/ stub/ ion/
endif
View
1 drivers/gpu/drm/Makefile
@@ -39,7 +39,6 @@ obj-$(CONFIG_DRM_SAVAGE)+= savage/
obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
obj-$(CONFIG_DRM_VIA) +=via/
obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
-obj-$(CONFIG_DRM_EXYNOS) +=exynos/
obj-$(CONFIG_DRM_GMA500) += gma500/
obj-$(CONFIG_DRM_UDL) += udl/
obj-y += i2c/
View
4 drivers/gpu/ion/ion.c
@@ -1034,8 +1034,8 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
return -EINVAL;
}
- if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) >
- buffer->size)) {
+ if (((vma->vm_pgoff << PAGE_SHIFT) >= buffer->size) ||
+ (size > (buffer->size - (vma->vm_pgoff << PAGE_SHIFT)))) {
pr_err("%s: trying to map larger area than handle has available"
"\n", __func__);
ret = -EINVAL;
View
1 drivers/input/keyboard/Makefile
@@ -52,7 +52,6 @@ obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
-
ifeq ($(TARGET_BUILD_VARIANT), eng)
KBUILD_CFLAGS += -DSEC_TKEY_EVENT_DEBUG
endif
View
2,651 drivers/input/touchscreen/465GS37_V12.h
2,651 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
479 drivers/input/touchscreen/cyttsp4_btn.c
@@ -0,0 +1,479 @@
+/*
+ * cyttsp4_btn.c
+ * Cypress TrueTouch(TM) Standard Product V4 CapSense touch reports module.
+ * For use with Cypress Txx4xx parts.
+ * Supported parts include:
+ * TMA4XX
+ * TMA1036
+ *
+ * Copyright (C) 2012 Cypress Semiconductor
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
+ *
+ */
+
+#include <linux/cyttsp4_bus.h>
+
+#include <linux/delay.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <linux/cyttsp4_btn.h>
+#include <linux/cyttsp4_core.h>
+#include "cyttsp4_regs.h"
+
+struct cyttsp4_btn_data {
+ struct cyttsp4_device *ttsp;
+ struct cyttsp4_btn_platform_data *pdata;
+ struct cyttsp4_sysinfo *si;
+ struct input_dev *input;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend es;
+ bool is_suspended;
+#endif
+ char phys[NAME_MAX];
+ u8 pr_buf[CY_MAX_PRBUF_SIZE];
+};
+
+static void cyttsp4_btn_key_action(struct cyttsp4_btn_data *bd,
+ int cur_btn, u8 cur_btn_mask, int num_btns, int new_btn_state)
+{
+ struct device *dev = &bd->ttsp->dev;
+ struct cyttsp4_sysinfo *si = bd->si;
+ int btn;
+ int cur_btn_state;
+
+ cur_btn_state = new_btn_state == CY_BTN_PRESSED ? CY_BTN_RELEASED :
+ CY_BTN_PRESSED;
+
+ for (btn = 0; btn < num_btns; btn++) {
+ if ((si->btn[cur_btn + btn].enabled) &&
+ (((cur_btn_mask >> (btn * CY_BITS_PER_BTN)) &
+ (CY_NUM_BTN_EVENT_ID - 1)) == new_btn_state) &&
+ (si->btn[cur_btn + btn].state == cur_btn_state)) {
+ input_report_key(bd->input, si->btn
+ [cur_btn + btn].key_code, new_btn_state);
+ si->btn[cur_btn + btn].state = new_btn_state;
+ input_sync(bd->input);
+ dev_dbg(dev, "%s: btn=%d key_code=%d %s\n", __func__,
+ cur_btn + btn, si->btn[cur_btn + btn].key_code,
+ new_btn_state == CY_BTN_PRESSED ?
+ "PRESSED" : "RELEASED");
+ }
+ }
+ return;
+}
+
+static void cyttsp4_get_btn_touches(struct cyttsp4_btn_data *bd)
+{
+ enum cyttsp4_btn_state btn_state = CY_BTN_RELEASED;
+ struct cyttsp4_sysinfo *si = bd->si;
+ int num_btn;
+ int num_cur_btn;
+ int cur_reg;
+ int cur_btn;
+ u8 cur_btn_mask;
+
+ for (btn_state = CY_BTN_RELEASED; btn_state < CY_BTN_NUM_STATE;
+ btn_state++) {
+ for (cur_reg = cur_btn = 0, num_cur_btn = si->si_ofs.num_btns;
+ cur_reg < si->si_ofs.num_btn_regs;
+ cur_reg++, cur_btn += CY_NUM_BTN_PER_REG,
+ num_cur_btn -= CY_NUM_BTN_PER_REG) {
+ if (num_cur_btn > 0) {
+ cur_btn_mask = si->xy_mode[si->si_ofs.rep_ofs +
+ 2 + cur_reg];
+ num_btn = num_cur_btn / CY_NUM_BTN_PER_REG ?
+ CY_NUM_BTN_PER_REG : num_cur_btn;
+ cyttsp4_btn_key_action(bd, cur_btn,
+ cur_btn_mask, num_btn, btn_state);
+ }
+ }
+ }
+ return;
+}
+
+static void cyttsp4_btn_lift_all(struct cyttsp4_btn_data *bd)
+{
+ struct cyttsp4_sysinfo *si = bd->si;
+ int btn_reg;
+ int num_regs;
+ if (si->si_ofs.num_btns == 0)
+ return;
+
+ num_regs = (si->si_ofs.num_btns + CY_NUM_BTN_PER_REG - 1)
+ / CY_NUM_BTN_PER_REG;
+
+ for (btn_reg = 0; btn_reg < num_regs; btn_reg++)
+ si->xy_mode[si->si_ofs.rep_ofs + 2 + btn_reg] = 0;
+
+ cyttsp4_get_btn_touches(bd);
+}
+
+#ifdef VERBOSE_DEBUG
+static void cyttsp4_log_btn_data(struct cyttsp4_btn_data *bd)
+{
+ struct device *dev = &bd->ttsp->dev;
+ struct cyttsp4_sysinfo *si = bd->si;
+ int cur;
+ int t;
+
+ for (cur = 0; cur < si->si_ofs.num_btns; cur++) {
+ bd->pr_buf[0] = 0;
+ snprintf(bd->pr_buf, CY_MAX_PRBUF_SIZE, "btn_rec[%d]=0x", cur);
+ for (t = 0; t < si->si_ofs.btn_rec_size; t++)
+ snprintf(bd->pr_buf, CY_MAX_PRBUF_SIZE, "%s%02X",
+ bd->pr_buf, si->btn_rec_data
+ [(cur * si->si_ofs.btn_rec_size) + t]);
+
+ dev_vdbg(dev, "%s: %s\n", __func__, bd->pr_buf);
+ }
+ return;
+}
+#endif
+
+/* read xy_data for all current CapSense button touches */
+static int cyttsp4_xy_worker(struct cyttsp4_btn_data *bd)
+{
+ struct device *dev = &bd->ttsp->dev;
+ struct cyttsp4_sysinfo *si = bd->si;
+ u8 rep_stat = si->xy_mode[si->si_ofs.rep_ofs + 1];
+#ifdef VERBOSE_DEBUG
+ int rc;
+#endif
+
+ /* rep_data for bad packet check */
+ if (IS_BAD_PKT(rep_stat)) {
+ dev_dbg(dev, "%s: Invalid buffer detected\n", __func__);
+ return 0;
+ }
+
+ /* extract button press/release touch information */
+ if (si->si_ofs.num_btns > 0) {
+ cyttsp4_get_btn_touches(bd);
+#ifdef VERBOSE_DEBUG
+ /* read button diff data */
+ rc = cyttsp4_read(bd->ttsp, CY_MODE_OPERATIONAL,
+ si->si_ofs.tt_stat_ofs + 1 +
+ si->si_ofs.max_tchs * si->si_ofs.tch_rec_size,
+ si->btn_rec_data,
+ si->si_ofs.num_btns * si->si_ofs.btn_rec_size);
+ if (rc < 0) {
+ dev_err(dev, "%s: read fail on button regs r=%d\n",
+ __func__, rc);
+ return 0;
+ }
+
+ /* log button press/release touch information */
+ cyttsp4_log_btn_data(bd);
+#endif
+ }
+
+ dev_vdbg(dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int cyttsp4_btn_attention(struct cyttsp4_device *ttsp)
+{
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
+ int rc = 0;
+
+ dev_vdbg(dev, "%s\n", __func__);
+
+ /* core handles handshake */
+ rc = cyttsp4_xy_worker(bd);
+ if (rc < 0)
+ dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
+
+ return rc;
+}
+
+static int cyttsp4_startup_attention(struct cyttsp4_device *ttsp)
+{
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
+ struct cyttsp4_sysinfo *si = bd->si;
+ int btn;
+
+ dev_vdbg(dev, "%s\n", __func__);
+
+ for (btn = 0; btn < si->si_ofs.num_btns; btn++)
+ bd->si->btn[btn].state = CY_BTN_RELEASED;
+
+ return 0;
+}
+
+int cyttsp4_btn_open(struct input_dev *input)
+{
+ struct device *dev = input->dev.parent;
+ struct cyttsp4_device *ttsp =
+ container_of(dev, struct cyttsp4_device, dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ pm_runtime_get_sync(dev);
+
+ dev_vdbg(dev, "%s: setup subscriptions\n", __func__);
+
+ /* set up touch call back */
+ cyttsp4_subscribe_attention(ttsp, CY_ATTEN_IRQ,
+ cyttsp4_btn_attention, CY_MODE_OPERATIONAL);
+
+ /* set up startup call back */
+ cyttsp4_subscribe_attention(ttsp, CY_ATTEN_STARTUP,
+ cyttsp4_startup_attention, 0);
+
+ return 0;
+}
+
+void cyttsp4_btn_close(struct input_dev *input)
+{
+ struct device *dev = input->dev.parent;
+ struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
+ struct cyttsp4_device *ttsp =
+ container_of(dev, struct cyttsp4_device, dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ cyttsp4_btn_lift_all(bd);
+
+ cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_IRQ,
+ cyttsp4_btn_attention, CY_MODE_OPERATIONAL);
+
+ cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_STARTUP,
+ cyttsp4_startup_attention, 0);
+
+ pm_runtime_put(dev);
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cyttsp4_btn_early_suspend(struct early_suspend *h)
+{
+ struct cyttsp4_btn_data *bd =
+ container_of(h, struct cyttsp4_btn_data, es);
+ struct device *dev = &bd->ttsp->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ cyttsp4_btn_lift_all(bd);
+ pm_runtime_put(dev);
+
+ bd->is_suspended = true;
+}
+
+static void cyttsp4_btn_late_resume(struct early_suspend *h)
+{
+ struct cyttsp4_btn_data *bd =
+ container_of(h, struct cyttsp4_btn_data, es);
+ struct device *dev = &bd->ttsp->dev;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ pm_runtime_get_sync(dev);
+
+ bd->is_suspended = false;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int cyttsp4_btn_suspend(struct device *dev)
+{
+ struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ cyttsp4_btn_lift_all(bd);
+ return 0;
+}
+
+static int cyttsp4_btn_resume(struct device *dev)
+{
+ dev_dbg(dev, "%s\n", __func__);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops cyttsp4_btn_pm_ops = {
+ SET_RUNTIME_PM_OPS(cyttsp4_btn_suspend, cyttsp4_btn_resume, NULL)
+};
+
+static int cyttsp4_btn_probe(struct cyttsp4_device *ttsp)
+{
+ struct cyttsp4_btn_data *bd;
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_btn_platform_data *pdata = dev_get_platdata(dev);
+ int i;
+ int rc = 0;
+
+ dev_info(dev, "%s\n", __func__);
+ dev_dbg(dev, "%s: debug on\n", __func__);
+ dev_vdbg(dev, "%s: verbose debug on\n", __func__);
+
+ bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+ if (bd == NULL) {
+ dev_err(dev, "%s: Error, kzalloc\n", __func__);
+ rc = -ENOMEM;
+ goto error_alloc_data_failed;
+ }
+
+ bd->ttsp = ttsp;
+ bd->pdata = pdata;
+ dev_set_drvdata(dev, bd);
+ /* Create the input device and register it. */
+ dev_vdbg(dev, "%s: Create the input device and register it\n",
+ __func__);
+ bd->input = input_allocate_device();
+ if (bd->input == NULL) {
+ dev_err(dev, "%s: Error, failed to allocate input device\n",
+ __func__);
+ rc = -ENOSYS;
+ goto error_alloc_failed;
+ }
+
+ bd->input->name = ttsp->name;
+ scnprintf(bd->phys, sizeof(bd->phys)-1, "%s", dev_name(dev));
+ bd->input->phys = bd->phys;
+ bd->input->dev.parent = &bd->ttsp->dev;
+ bd->input->open = cyttsp4_btn_open;
+ bd->input->close = cyttsp4_btn_close;
+ input_set_drvdata(bd->input, bd);
+
+ pm_runtime_enable(dev);
+
+ pm_runtime_get_sync(dev);
+ /* get sysinfo */
+ bd->si = cyttsp4_request_sysinfo(ttsp);
+ pm_runtime_put(dev);
+
+ if (bd->si == NULL) {
+ dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
+ __func__, bd->si);
+ rc = -ENODEV;
+ goto error_get_sysinfo;
+ }
+
+ dev_vdbg(dev, "%s: Initialize event signals\n", __func__);
+ __set_bit(EV_KEY, bd->input->evbit);
+ __set_bit(EV_LED, bd->input->evbit);
+ __set_bit(LED_MISC, bd->input->ledbit);
+
+ for (i = 0; i < bd->si->si_ofs.num_btns; i++)
+ __set_bit(bd->si->btn[i].key_code, bd->input->keybit);
+
+ rc = input_register_device(bd->input);
+ if (rc < 0) {
+ dev_err(dev, "%s: Error, failed register input device r=%d\n",
+ __func__, rc);
+ goto error_init_input;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ bd->es.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ bd->es.suspend = cyttsp4_btn_early_suspend;
+ bd->es.resume = cyttsp4_btn_late_resume;
+
+ register_early_suspend(&bd->es);
+#endif
+
+ dev_dbg(dev, "%s: ok\n", __func__);
+ return 0;
+
+error_init_input:
+ input_free_device(bd->input);
+error_get_sysinfo:
+ pm_runtime_suspend(dev);
+ pm_runtime_disable(dev);
+error_alloc_failed:
+ kfree(bd);
+error_alloc_data_failed:
+ dev_err(dev, "%s failed.\n", __func__);
+ return rc;
+}
+
+static int cyttsp4_btn_release(struct cyttsp4_device *ttsp)
+{
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s\n", __func__);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ /*
+ * This check is to prevent pm_runtime usage_count drop below zero
+ * because of removing the module while in suspended state
+ */
+ if (bd->is_suspended)
+ pm_runtime_get_noresume(dev);
+
+ unregister_early_suspend(&bd->es);
+#endif
+
+ input_unregister_device(bd->input);
+
+ pm_runtime_suspend(dev);
+ pm_runtime_disable(dev);
+
+ dev_set_drvdata(dev, NULL);
+ kfree(bd);
+ return 0;
+}
+
+struct cyttsp4_driver cyttsp4_btn_driver = {
+ .probe = cyttsp4_btn_probe,
+ .remove = cyttsp4_btn_release,
+ .driver = {
+ .name = CYTTSP4_BTN_NAME,
+ .bus = &cyttsp4_bus_type,
+ .owner = THIS_MODULE,
+ .pm = &cyttsp4_btn_pm_ops,
+ },
+};
+
+static int __init cyttsp4_btn_init(void)
+{
+ int rc = 0;
+ rc = cyttsp4_register_driver(&cyttsp4_btn_driver);
+ pr_info("%s: Cypress TTSP MT v4 CapSense BTN (Built %s), rc=%d\n",
+ __func__, CY_DRIVER_DATE, rc);
+ return rc;
+}
+module_init(cyttsp4_btn_init);
+
+static void __exit cyttsp4_btn_exit(void)
+{
+ cyttsp4_unregister_driver(&cyttsp4_btn_driver);
+ pr_info("%s: module exit\n", __func__);
+}
+module_exit(cyttsp4_btn_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TTSP 2D multi-touch CapSense BTN driver");
+MODULE_AUTHOR("Cypress Semiconductor");
View
753 drivers/input/touchscreen/cyttsp4_bus.c
@@ -0,0 +1,753 @@
+/*
+ * cyttsp4_bus.c
+ * Cypress TrueTouch(TM) Standard Product V4 Bus Driver.
+ * For use with Cypress Txx4xx parts.
+ * Supported parts include:
+ * TMA4XX
+ * TMA1036
+ *
+ * Copyright (C) 2012 Cypress Semiconductor
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
+ *
+ * Author: Aleksej Makarov aleksej.makarov@sonyericsson.com
+ * Modified by: Cypress Semiconductor for complete set of TTSP Bus interfaces.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
+ *
+ */
+
+#include <linux/cyttsp4_bus.h>
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/limits.h>
+
+static DEFINE_MUTEX(core_lock);
+static LIST_HEAD(adapter_list);
+static LIST_HEAD(core_dev_list);
+static LIST_HEAD(cyttsp4_dev_list);
+
+struct bus_type cyttsp4_bus_type;
+
+static void cyttsp4_dev_release(struct device *dev)
+{
+ dev_vdbg(dev, "%s: Enter\n", __func__);
+ put_device(dev->parent);
+}
+
+static struct device_type cyttsp4_dev_type = {
+ .release = cyttsp4_dev_release
+};
+
+static struct device_type cyttsp4_core_type = {
+ .release = cyttsp4_dev_release
+};
+
+static int cyttsp4_match_dev(struct device *dev, void *data)
+{
+ return dev == (struct device *)data;
+}
+
+static void cyttsp4_initialize_device(struct cyttsp4_device *dev,
+ struct cyttsp4_device_info const *dev_info)
+{
+ dev->name = dev_info->name;
+ dev->core_id = dev_info->core_id;
+ dev->dev.platform_data = dev_info->platform_data;
+}
+
+static void _cyttsp4_reinitialize_device(struct cyttsp4_device *dev)
+{
+ void *platform_data = dev->dev.platform_data;
+
+ memset(&dev->dev, 0, sizeof(dev->dev));
+ dev->dev.platform_data = platform_data;
+ dev->core = NULL;
+}
+
+static void cyttsp4_initialize_core(struct cyttsp4_core *core,
+ struct cyttsp4_core_info const *core_info)
+{
+ core->name = core_info->name;
+ core->id = core_info->id;
+ core->adap_id = core_info->adap_id;
+ core->dev.platform_data = core_info->platform_data;
+}
+
+static void _cyttsp4_reinitialize_core(struct cyttsp4_core *core)
+{
+ void *platform_data = core->dev.platform_data;
+
+ memset(&core->dev, 0, sizeof(core->dev));
+ core->dev.platform_data = platform_data;
+ core->adap = NULL;
+}
+
+static int _cyttsp4_register_dev(struct cyttsp4_device *pdev,
+ struct cyttsp4_core *core)
+{
+ int ret;
+
+ BUG_ON(bus_find_device(&cyttsp4_bus_type, NULL, &pdev->dev,
+ cyttsp4_match_dev));
+
+ pdev->core = core;
+ pdev->dev.parent = get_device(&core->dev);
+ pdev->dev.bus = &cyttsp4_bus_type;
+ pdev->dev.type = &cyttsp4_dev_type;
+ dev_set_name(&pdev->dev, "%s.%s", pdev->name, core->id);
+
+ ret = device_register(&pdev->dev);
+ dev_dbg(&pdev->dev,
+ "%s: Registering device '%s'. Parent at '%s', err = %d\n",
+ __func__, dev_name(&pdev->dev),
+ dev_name(pdev->dev.parent), ret);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: failed to register device, err %d\n",
+ __func__, ret);
+ pdev->core = NULL;
+ }
+ return ret;
+}
+
+static void _cyttsp4_unregister_dev(struct cyttsp4_device *pdev)
+{
+ /* Check if the device is registered with the system */
+ if (!bus_find_device(&cyttsp4_bus_type, NULL, &pdev->dev,
+ cyttsp4_match_dev))
+ return;
+
+ dev_dbg(&pdev->dev, "%s: Unregistering device '%s'.\n",
+ __func__, dev_name(&pdev->dev));
+ /* Put reference taken by bus_find_device() */
+ put_device(&pdev->dev);
+ device_unregister(&pdev->dev);
+}
+
+static int _cyttsp4_register_core(struct cyttsp4_core *pdev,
+ struct cyttsp4_adapter *adap)
+{
+ int ret;
+
+ BUG_ON(bus_find_device(&cyttsp4_bus_type, NULL, &pdev->dev,
+ cyttsp4_match_dev));
+
+ pdev->adap = adap;
+ pdev->dev.parent = get_device(adap->dev);
+ pdev->dev.bus = &cyttsp4_bus_type;
+ pdev->dev.type = &cyttsp4_core_type;
+ dev_set_name(&pdev->dev, "%s.%s", pdev->id, adap->id);
+
+ ret = device_register(&pdev->dev);
+ dev_dbg(&pdev->dev,
+ "%s: Registering device '%s'. Parent at '%s', err = %d\n",
+ __func__, dev_name(&pdev->dev),
+ dev_name(pdev->dev.parent), ret);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: failed to register device, err %d\n",
+ __func__, ret);
+ pdev->adap = NULL;
+ }
+ return ret;
+}
+
+static void _cyttsp4_unregister_core(struct cyttsp4_core *pdev)
+{
+ /* Check if the core is registered with the system */
+ if (!bus_find_device(&cyttsp4_bus_type, NULL, &pdev->dev,
+ cyttsp4_match_dev))
+ return;
+
+ dev_dbg(&pdev->dev, "%s: Unregistering core '%s'.\n",
+ __func__, dev_name(&pdev->dev));
+ /* Put reference taken by bus_find_device() */
+ put_device(&pdev->dev);
+ device_unregister(&pdev->dev);
+}
+
+static void _cyttsp4_unregister_and_reinitialize_devices(
+ struct cyttsp4_core *core)
+{
+ struct cyttsp4_device *dev;
+
+ list_for_each_entry(dev, &cyttsp4_dev_list, node)
+ if (dev->core == core) {
+ _cyttsp4_unregister_dev(dev);
+ _cyttsp4_reinitialize_device(dev);
+ }
+}
+
+static struct cyttsp4_adapter *find_adapter(char const *adap_id)
+{
+ struct cyttsp4_adapter *a;
+
+ list_for_each_entry(a, &adapter_list, node)
+ if (!strncmp(a->id, adap_id, NAME_MAX))
+ return a;
+ return NULL;
+}
+
+static struct cyttsp4_core *find_core(char const *core_id)
+{
+ struct cyttsp4_core *d;
+
+ list_for_each_entry(d, &core_dev_list, node)
+ if (!strncmp(d->id, core_id, NAME_MAX))
+ return d;
+ return NULL;
+}
+
+static struct cyttsp4_core *find_core_with_driver(char const *core_id)
+{
+ struct cyttsp4_core *d;
+
+ d = find_core(core_id);
+ if (d && d->dev.driver)
+ return d;
+ return NULL;
+}
+
+static struct cyttsp4_device *find_device(char const *name,
+ char const *core_id)
+{
+ struct cyttsp4_device *d;
+
+ list_for_each_entry(d, &cyttsp4_dev_list, node)
+ if (!strncmp(d->name, name, NAME_MAX) &&
+ !strncmp(d->core_id, core_id, NAME_MAX))
+ return d;
+ return NULL;
+}
+
+static void rescan_devices(struct cyttsp4_core *core)
+{
+ struct cyttsp4_device *d;
+
+ list_for_each_entry(d, &cyttsp4_dev_list, node)
+ if (!d->core && !strncmp(core->id, d->core_id, NAME_MAX))
+ _cyttsp4_register_dev(d, core);
+}
+
+static void rescan_cores(struct cyttsp4_adapter *adap)
+{
+ struct cyttsp4_core *d;
+
+ list_for_each_entry(d, &core_dev_list, node)
+ if (!d->adap && !strncmp(adap->id, d->adap_id, NAME_MAX))
+ _cyttsp4_register_core(d, adap);
+}
+
+static int cyttsp4_check_device_info(
+ struct cyttsp4_device_info const *dev_info)
+{
+ int len;
+
+ if (!dev_info->name)
+ return -EINVAL;
+ if (!dev_info->core_id)
+ return -EINVAL;
+
+ len = strnlen(dev_info->name, NAME_MAX);
+ if (len == 0 || len == NAME_MAX)
+ return -EINVAL;
+
+ len = strnlen(dev_info->core_id, NAME_MAX);
+ if (len == 0 || len == NAME_MAX)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int cyttsp4_check_core_info(
+ struct cyttsp4_core_info const *core_info)
+{
+ int len;
+
+ if (!core_info->name)
+ return -EINVAL;
+ if (!core_info->id)
+ return -EINVAL;
+ if (!core_info->adap_id)
+ return -EINVAL;
+
+ len = strnlen(core_info->name, NAME_MAX);
+ if (len == 0 || len == NAME_MAX)
+ return -EINVAL;
+
+ len = strnlen(core_info->id, NAME_MAX);
+ if (len == 0 || len == NAME_MAX)
+ return -EINVAL;
+
+ len = strnlen(core_info->adap_id, NAME_MAX);
+ if (len == 0 || len == NAME_MAX)
+ return -EINVAL;
+
+ return 0;
+}
+
+int cyttsp4_register_device(struct cyttsp4_device_info const *dev_info)
+{
+ struct cyttsp4_device *dev;
+ struct cyttsp4_core *core;
+ int ret;
+
+ if (!dev_info) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cyttsp4_check_device_info(dev_info);
+ if (ret) {
+ pr_debug("%s: dev_info is invalid\n", __func__);
+ goto fail;
+ }
+
+ mutex_lock(&core_lock);
+ if (find_device(dev_info->name, dev_info->core_id)) {
+ pr_debug("%s: device '%s' with core id '%s' already exists\n",
+ __func__, dev_info->name, dev_info->core_id);
+ ret = -EEXIST;
+ goto fail_unlock;
+ }
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ pr_err("%s: failed to allocate device '%s'\n",
+ __func__, dev_info->name);
+ ret = -ENOMEM;
+ goto fail_unlock;
+ }
+ cyttsp4_initialize_device(dev, dev_info);
+ list_add(&dev->node, &cyttsp4_dev_list);
+ pr_debug("%s: '%s' added to cyttsp4_dev_list\n", __func__, dev->name);
+ core = find_core_with_driver(dev->core_id);
+ if (core)
+ ret = _cyttsp4_register_dev(dev, core);
+fail_unlock:
+ mutex_unlock(&core_lock);
+fail:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_register_device);
+
+int cyttsp4_unregister_device(char const *name, char const *core_id)
+{
+ struct cyttsp4_device *dev;
+ int ret = 0;
+
+ if (!name || !core_id) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ mutex_lock(&core_lock);
+ dev = find_device(name, core_id);
+ if (!dev) {
+ pr_err("%s: device '%s' could not be found\n", __func__, name);
+ ret = -ENODEV;
+ goto fail_unlock;
+ }
+ _cyttsp4_unregister_dev(dev);
+ list_del(&dev->node);
+ pr_debug("%s: '%s' removed from cyttsp4_dev_list\n", __func__,
+ dev->name);
+ kfree(dev);
+fail_unlock:
+ mutex_unlock(&core_lock);
+fail:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_unregister_device);
+
+int cyttsp4_register_core_device(struct cyttsp4_core_info const *core_info)
+{
+ struct cyttsp4_core *core;
+ struct cyttsp4_adapter *adap;
+ int ret;
+
+ if (!core_info) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cyttsp4_check_core_info(core_info);
+ if (ret) {
+ pr_debug("%s: core_info is invalid\n", __func__);
+ goto fail;
+ }
+
+ mutex_lock(&core_lock);
+ if (find_core(core_info->id)) {
+ pr_debug("%s: core id '%s' already exists\n",
+ __func__, core_info->id);
+ ret = -EEXIST;
+ goto fail_unlock;
+ }
+ core = kzalloc(sizeof(*core), GFP_KERNEL);
+ if (!core) {
+ pr_err("%s: failed to allocate core device '%s'\n",
+ __func__, core_info->name);
+ ret = -ENOMEM;
+ goto fail_unlock;
+ }
+ cyttsp4_initialize_core(core, core_info);
+ list_add(&core->node, &core_dev_list);
+ pr_debug("%s: '%s' added to core_dev_list\n", __func__, core->name);
+ adap = find_adapter(core->adap_id);
+ if (adap) {
+ pr_debug("%s: adapter for '%s' is '%s'\n", __func__,
+ core->id, dev_name(adap->dev));
+ ret = _cyttsp4_register_core(core, adap);
+ if (!ret)
+ rescan_devices(core);
+ }
+fail_unlock:
+ mutex_unlock(&core_lock);
+fail:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_register_core_device);
+
+int cyttsp4_add_adapter(char const *id, struct cyttsp4_ops const *ops,
+ struct device *parent)
+{
+ int rc = 0;
+ struct cyttsp4_adapter *a;
+
+ if (!parent) {
+ dev_err(parent, "%s: need parent for '%s'\n", __func__, id);
+ return -EINVAL;
+ }
+ mutex_lock(&core_lock);
+ if (find_adapter(id)) {
+ dev_err(parent, "%s: adapter '%s' already exists\n",
+ __func__, id);
+ rc = -EEXIST;
+ goto fail;
+ }
+ a = kzalloc(sizeof(*a), GFP_KERNEL);
+ if (!a) {
+ dev_err(parent, "%s: failed to allocate adapter '%s'\n",
+ __func__, id);
+ rc = -ENOMEM;
+ goto fail;
+ }
+ memcpy(a->id, id, sizeof(a->id));
+ a->id[sizeof(a->id) - 1] = 0;
+ a->read = ops->read;
+ a->write = ops->write;
+ a->dev = parent;
+ list_add(&a->node, &adapter_list);
+ dev_dbg(parent, "%s: '%s' added to adapter_list\n", __func__, id);
+ rescan_cores(a);
+fail:
+ mutex_unlock(&core_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_add_adapter);
+
+int cyttsp4_del_adapter(char const *id)
+{
+ int rc = 0;
+ struct cyttsp4_adapter *adap;
+ struct cyttsp4_core *core;
+
+ mutex_lock(&core_lock);
+ adap = find_adapter(id);
+ if (!adap) {
+ pr_err("%s: adapter '%s' does not exist\n",
+ __func__, id);
+ rc = -ENODEV;
+ goto fail;
+ }
+
+ /* Unregister core and devices linked to this adapter
+ * This is to prevent core and devices get probed until
+ * their corresponding adapter is re-added
+ */
+ list_for_each_entry(core, &core_dev_list, node) {
+ if (core->adap != adap)
+ continue;
+ _cyttsp4_unregister_and_reinitialize_devices(core);
+ _cyttsp4_unregister_core(core);
+ _cyttsp4_reinitialize_core(core);
+ }
+
+ list_del(&adap->node);
+ kfree(adap);
+ pr_debug("%s: '%s' removed from adapter_list\n", __func__, id);
+fail:
+ mutex_unlock(&core_lock);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_del_adapter);
+
+static struct cyttsp4_device *verify_device_type(struct device *dev)
+{
+ return dev->type == &cyttsp4_dev_type ? to_cyttsp4_device(dev) : NULL;
+}
+
+static struct cyttsp4_core *verify_core_type(struct device *dev)
+{
+ return dev->type == &cyttsp4_core_type ? to_cyttsp4_core(dev) : NULL;
+}
+
+static int cyttsp4_device_match(struct device *dev, struct device_driver *drv)
+{
+ struct cyttsp4_device *cyttsp4_dev = verify_device_type(dev);
+ struct cyttsp4_core *cyttsp4_core;
+ int match;
+
+ if (cyttsp4_dev) {
+ match = strncmp(cyttsp4_dev->name, drv->name, NAME_MAX) == 0;
+ goto exit;
+ }
+ cyttsp4_core = verify_core_type(dev);
+ if (cyttsp4_core) {
+ match = strncmp(cyttsp4_core->name, drv->name, NAME_MAX) == 0;
+ goto exit;
+ }
+ match = 0;
+exit:
+ dev_dbg(dev, "%s: %s matching '%s' driver\n", __func__,
+ match ? "is" : "isn't", drv->name);
+ return match;
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct cyttsp4_device *cyttsp4_dev = verify_device_type(dev);
+ struct cyttsp4_core *cyttsp4_core;
+
+ char const *name;
+ int len;
+
+ if (cyttsp4_dev) {
+ name = cyttsp4_dev->name;
+ goto exit;
+ }
+ cyttsp4_core = verify_core_type(dev);
+ if (cyttsp4_core) {
+ name = cyttsp4_core->id;
+ goto exit;
+ }
+ name = "none";
+exit:
+ len = snprintf(buf, PAGE_SIZE, "ttsp4:%s\n", name);
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute cyttsp4_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
+#ifdef CONFIG_SUSPEND
+static int cyttsp4_pm_suspend(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+
+ dev_dbg(dev, "%s\n", __func__);
+ if (drv && drv->pm && drv->pm->suspend)
+ return drv->pm->suspend(dev);
+ return 0;
+}
+
+static int cyttsp4_pm_resume(struct device *dev)
+{
+ struct device_driver *drv = dev->driver;
+
+ dev_dbg(dev, "%s\n", __func__);
+ if (drv && drv->pm && drv->pm->resume)
+ return drv->pm->resume(dev);
+ return 0;
+}
+#else /* !CONFIG_SUSPEND */
+#define cyttsp4_pm_suspend NULL
+#define cyttsp4_pm_resume NULL
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_PM_RUNTIME
+#define cyttsp4_pm_rt_suspend pm_generic_runtime_suspend
+#define cyytsp4_pm_rt_resume pm_generic_runtime_resume
+#define cyytsp4_pm_rt_idle pm_generic_runtime_idle
+#else /* !CONFIG_PM_RUNTIME */
+#define cyttsp4_pm_rt_suspend NULL
+#define cyytsp4_pm_rt_resume NULL
+#define cyytsp4_pm_rt_idle NULL
+#endif /* !CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops cyttsp4_dev_pm_ops = {
+ .suspend = cyttsp4_pm_suspend,
+ .resume = cyttsp4_pm_resume,
+ .runtime_suspend = cyttsp4_pm_rt_suspend,
+ .runtime_resume = cyytsp4_pm_rt_resume,
+ .runtime_idle = cyytsp4_pm_rt_idle,
+};
+
+struct bus_type cyttsp4_bus_type = {
+ .name = "ttsp4",
+ .dev_attrs = cyttsp4_dev_attrs,
+ .match = cyttsp4_device_match,
+ .uevent = NULL,
+ .pm = &cyttsp4_dev_pm_ops,
+};
+EXPORT_SYMBOL_GPL(cyttsp4_bus_type);
+
+static int cyttsp4_drv_remove(struct device *_dev)
+{
+ struct cyttsp4_driver *drv = to_cyttsp4_driver(_dev->driver);
+ struct cyttsp4_device *dev = to_cyttsp4_device(_dev);
+ struct cyttsp4_core *core = dev->core;
+ int ret;
+
+ ret = drv->remove(dev);
+ /* Decrease usage count of the core driver */
+ module_put(core->dev.driver->owner);
+ return ret;
+}
+
+static int cyttsp4_core_drv_remove(struct device *_dev)
+{
+ struct cyttsp4_core_driver *drv = to_cyttsp4_core_driver(_dev->driver);
+ struct cyttsp4_core *core = to_cyttsp4_core(_dev);
+ struct cyttsp4_adapter *adap = core->adap;
+ int ret;
+
+ ret = drv->remove(core);
+ /* Decrease usage count of the adapter driver */
+ module_put(adap->dev->driver->owner);
+
+ mutex_lock(&core_lock);
+ /* Unregister devices linked to this core
+ * This is to prevent devices get probed until
+ * their corresponding core driver is re-added
+ */
+ _cyttsp4_unregister_and_reinitialize_devices(core);
+ mutex_unlock(&core_lock);
+
+ return ret;
+}
+
+static int cyttsp4_drv_probe(struct device *_dev)
+{
+ struct cyttsp4_driver *drv = to_cyttsp4_driver(_dev->driver);
+ struct cyttsp4_device *dev = to_cyttsp4_device(_dev);
+ struct cyttsp4_core *core = dev->core;
+ int rc;
+
+ BUG_ON(!core);
+ BUG_ON(!core->dev.driver);
+
+ /* Increase usage count of the core driver*/
+ __module_get(core->dev.driver->owner);
+
+ rc = drv->probe(dev);
+ if (rc)
+ module_put(core->dev.driver->owner);
+ dev_dbg(_dev, "%s: for %s = %d\n", __func__, dev->name, rc);
+ return rc;
+}
+
+static int cyttsp4_core_drv_probe(struct device *_dev)
+{
+ struct cyttsp4_core_driver *drv = to_cyttsp4_core_driver(_dev->driver);
+ struct cyttsp4_core *dev = to_cyttsp4_core(_dev);
+ struct cyttsp4_adapter *adap = dev->adap;
+ int rc;
+
+ BUG_ON(!adap);
+ BUG_ON(!adap->dev->driver);
+
+ /* Increase usage count of the adapter driver*/
+ __module_get(adap->dev->driver->owner);
+
+ rc = drv->probe(dev);
+ dev_dbg(_dev, "%s: for %s = %d\n", __func__, dev->name, rc);
+ if (!rc)
+ rescan_devices(dev);
+ else
+ module_put(adap->dev->driver->owner);
+ return rc;
+}
+
+int cyttsp4_register_driver(struct cyttsp4_driver *drv)
+{
+ int ret;
+
+ drv->driver.bus = &cyttsp4_bus_type;
+ if (drv->probe)
+ drv->driver.probe = cyttsp4_drv_probe;
+ if (drv->remove)
+ drv->driver.remove = cyttsp4_drv_remove;
+ ret = driver_register(&drv->driver);
+ pr_debug("%s: '%s' returned %d\n", __func__, drv->driver.name, ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_register_driver);
+
+int cyttsp4_register_core_driver(struct cyttsp4_core_driver *drv)
+{
+ int ret;
+
+ drv->driver.bus = &cyttsp4_bus_type;
+ if (drv->probe)
+ drv->driver.probe = cyttsp4_core_drv_probe;
+ if (drv->remove)
+ drv->driver.remove = cyttsp4_core_drv_remove;
+ ret = driver_register(&drv->driver);
+ pr_debug("%s: '%s' returned %d\n", __func__, drv->driver.name, ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cyttsp4_register_core_driver);
+
+void cyttsp4_unregister_driver(struct cyttsp4_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(cyttsp4_unregister_driver);
+
+void cyttsp4_unregister_core_driver(struct cyttsp4_core_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(cyttsp4_unregister_core_driver);
+
+int __init cyttsp4_bus_init(void)
+{
+ int error;
+ error = bus_register(&cyttsp4_bus_type);
+ if (error)
+ pr_err("%s: error %d\n", __func__, error);
+ else
+ pr_debug("%s: ok\n", __func__);
+ return error;
+}
+
+static void __exit cyttsp4_bus_exit(void)
+{
+ pr_debug("%s: ok\n", __func__);
+}
+
+subsys_initcall(cyttsp4_bus_init);
+module_exit(cyttsp4_bus_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Aleksej Makarov <aleksej.makarov@sonyericsson.com>");
View
530 drivers/input/touchscreen/cyttsp4_debug.c
@@ -0,0 +1,530 @@
+/*
+ * cyttsp4_debug.c
+ * Cypress TrueTouch(TM) Standard Product V4 Core driver module.
+ * For use with Cypress Txx4xx parts.
+ * Supported parts include:
+ * TMA4XX
+ * TMA1036
+ *
+ * Copyright (C) 2012 Cypress Semiconductor
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
+ *
+ * Author: Aleksej Makarov <aleksej.makarov@sonyericsson.com>
+ * Modified by: Cypress Semiconductor to add device functions
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
+ *
+ */
+
+#include <linux/cyttsp4_bus.h>
+#include <linux/cyttsp4_core.h>
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include "cyttsp4_regs.h"
+
+#define CYTTSP4_DEBUG_NAME "cyttsp4_debug"
+
+struct cyttsp4_debug_data {
+ struct cyttsp4_device *ttsp;
+ struct cyttsp4_debug_platform_data *pdata;
+ struct cyttsp4_sysinfo *si;
+ uint32_t interrupt_count;
+ uint32_t formated_output;
+ struct mutex sysfs_lock;
+ u8 pr_buf[CY_MAX_PRBUF_SIZE];
+};
+
+struct cyttsp4_debug_platform_data {
+ char const *debug_dev_name;
+};
+
+/*
+ * This function provide output of combined xy_mode and xy_data.
+ * Required by TTHE.
+ */
+void cyttsp4_pr_buf_op_mode(struct device *dev, u8 *pr_buf,
+ struct cyttsp4_sysinfo *si, u8 curTouch)
+{
+ int i, k;
+ const char fmt[] = "%02X ";
+ int max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_PR_TRUNCATED);
+ int totalSize = si->si_ofs.mode_size
+ + (curTouch * si->si_ofs.tch_rec_size);
+ u8 num_btns = si->si_ofs.num_btns;
+
+ pr_buf[0] = 0;
+ for (i = k = 0; i < si->si_ofs.mode_size && i < max; i++, k += 3)
+ scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, si->xy_mode[i]);
+
+ for (i = 0; i < (curTouch * si->si_ofs.tch_rec_size) && i < max;
+ i++, k += 3)
+ scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, si->xy_data[i]);
+
+ if (num_btns) {
+ /* print btn diff data for TTHE */
+ scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, "%s", "=");
+ k++;
+ for (i = 0; i < (num_btns * si->si_ofs.btn_rec_size) && i < max;
+ i++, k += 3)
+ scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt,
+ si->btn_rec_data[i]);
+ totalSize += num_btns * si->si_ofs.btn_rec_size + 1;
+ }
+ /* pr_info("%s=%s%s\n", "cyttsp4_OpModeData", pr_buf,
+ totalSize <= max ? "" : CY_PR_TRUNCATED); */
+}
+
+static void cyttsp4_debug_print(struct device *dev, u8 *pr_buf, u8 *sptr,
+ int size, const char *data_name)
+{
+ int i, j;
+ int elem_size = sizeof("XX ") - 1;
+ int max = (CY_MAX_PRBUF_SIZE - 1) / elem_size;
+ int limit = size < max ? size : max;
+
+ if (limit < 0)
+ limit = 0;
+
+ pr_buf[0] = 0;
+ for (i = j = 0; i < limit; i++, j += elem_size)
+ scnprintf(pr_buf + j, CY_MAX_PRBUF_SIZE - j, "%02X ", sptr[i]);
+
+ pr_info("%s[0..%d]=%s%s\n", data_name, size - 1, pr_buf,
+ size <= max ? "" : CY_PR_TRUNCATED);
+}
+
+static void cyttsp4_debug_formated(struct device *dev, u8 *pr_buf,
+ struct cyttsp4_sysinfo *si, u8 num_cur_tch)
+{
+ u8 mode_size = si->si_ofs.mode_size;
+ u8 rep_len = si->xy_mode[si->si_ofs.rep_ofs];
+ u8 tch_rec_size = si->si_ofs.tch_rec_size;
+ u8 num_btns = si->si_ofs.num_btns;
+ u8 num_btn_regs = (num_btns + CY_NUM_BTN_PER_REG - 1)
+ / CY_NUM_BTN_PER_REG;
+ u8 num_btn_tch;
+ u8 data_name[] = "touch[99]";
+ int max_print_length = 18;
+ int i;
+
+ /* xy_mode */
+ cyttsp4_debug_print(dev, pr_buf, si->xy_mode, mode_size, "xy_mode");
+
+ /* xy_data */
+ if (rep_len > max_print_length) {
+ pr_info("xy_data[0..%d]:\n", rep_len);
+ for (i = 0; i < rep_len - max_print_length;
+ i += max_print_length) {
+ cyttsp4_debug_print(dev, pr_buf, si->xy_data + i,
+ max_print_length, " ");
+ }
+ if (rep_len - i)
+ cyttsp4_debug_print(dev, pr_buf, si->xy_data + i,
+ rep_len - i, " ");
+ } else {
+ cyttsp4_debug_print(dev, pr_buf, si->xy_data, rep_len,
+ "xy_data");
+ }
+
+ /* touches */
+ for (i = 0; i < num_cur_tch; i++) {
+ scnprintf(data_name, sizeof(data_name) - 1, "touch[%u]", i);
+ cyttsp4_debug_print(dev, pr_buf,
+ si->xy_data + (i * tch_rec_size),
+ tch_rec_size, data_name);
+ }
+
+ /* buttons */
+ if (num_btns) {
+ num_btn_tch = 0;
+ for (i = 0; i < num_btn_regs; i++) {
+ if (si->xy_mode[si->si_ofs.rep_ofs + 2 + i]) {
+ num_btn_tch++;
+ break;
+ }
+ }
+ if (num_btn_tch)
+ cyttsp4_debug_print(dev, pr_buf,
+ &si->xy_mode[si->si_ofs.rep_ofs + 2],
+ num_btn_regs, "button");
+ }
+}
+
+/* read xy_data for all touches for debug */
+static int cyttsp4_xy_worker(struct cyttsp4_debug_data *dd)
+{
+ struct device *dev = &dd->ttsp->dev;
+ struct cyttsp4_sysinfo *si = dd->si;
+ u8 tt_stat = si->xy_mode[si->si_ofs.tt_stat_ofs];
+ u8 num_cur_tch = GET_NUM_TOUCHES(tt_stat);
+ uint32_t formated_output;
+ int rc;
+
+ mutex_lock(&dd->sysfs_lock);
+ dd->interrupt_count++;
+ formated_output = dd->formated_output;
+ mutex_unlock(&dd->sysfs_lock);
+
+ if (si->si_ofs.num_btns > 0) {
+ /* read button diff data */
+ rc = cyttsp4_read(dd->ttsp, CY_MODE_OPERATIONAL,
+ /* replace with btn_diff_ofs when that field
+ * becomes supported in the firmware */
+ si->si_ofs.tt_stat_ofs + 1 +
+ si->si_ofs.max_tchs * si->si_ofs.tch_rec_size,
+ si->btn_rec_data,
+ si->si_ofs.num_btns * si->si_ofs.btn_rec_size);
+ if (rc < 0) {
+ dev_err(dev, "%s: read fail on button regs r=%d\n",
+ __func__, rc);
+ }
+ }
+
+ /* Interrupt */
+ /* pr_info("Interrupt(%u)\n", dd->interrupt_count); */
+
+ if (formated_output)
+ cyttsp4_debug_formated(dev, dd->pr_buf, si, num_cur_tch);
+ else
+ /* print data for TTHE */
+ cyttsp4_pr_buf_op_mode(dev, dd->pr_buf, si, num_cur_tch);
+
+#ifdef SHOK_SENSOR_DATA_MODE
+ /* print data for the sensor monitor */
+ if (si->monitor.mntr_status == CY_MNTR_STARTED) {
+ cyttsp4_debug_print(dev, dd->pr_buf, si->monitor.sensor_data,
+ 150, "cyttsp4_sensor_monitor");
+ }
+#endif
+
+ pr_info("\n");
+
+ dev_vdbg(dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int cyttsp4_debug_attention(struct cyttsp4_device *ttsp)
+{
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_debug_data *dd = dev_get_drvdata(dev);
+ int rc = 0;
+
+ dev_vdbg(dev, "%s\n", __func__);
+
+ /* core handles handshake */
+ rc = cyttsp4_xy_worker(dd);
+ if (rc < 0)
+ dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
+
+ return rc;
+}
+
+static ssize_t cyttsp4_interrupt_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cyttsp4_debug_data *dd = dev_get_drvdata(dev);
+ int val;
+
+ mutex_lock(&dd->sysfs_lock);
+ val = dd->interrupt_count;
+ mutex_unlock(&dd->sysfs_lock);
+
+ return scnprintf(buf, CY_MAX_PRBUF_SIZE, "Interrupt Count: %d\n", val);
+}
+
+static ssize_t cyttsp4_interrupt_count_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct cyttsp4_debug_data *dd = dev_get_drvdata(dev);
+ mutex_lock(&dd->sysfs_lock);
+ dd->interrupt_count = 0;
+ mutex_unlock(&dd->sysfs_lock);
+ return size;
+}
+
+static DEVICE_ATTR(int_count, S_IRUSR | S_IWUSR,
+ cyttsp4_interrupt_count_show, cyttsp4_interrupt_count_store);
+
+static ssize_t cyttsp4_formated_output_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cyttsp4_debug_data *dd = dev_get_drvdata(dev);
+ int val;
+
+ mutex_lock(&dd->sysfs_lock);
+ val = dd->formated_output;
+ mutex_unlock(&dd->sysfs_lock);
+
+ return scnprintf(buf, CY_MAX_PRBUF_SIZE,
+ "Formated debug output: %x\n", val);
+}
+
+static ssize_t cyttsp4_formated_output_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct cyttsp4_debug_data *dd = dev_get_drvdata(dev);
+ unsigned long value;
+ int rc;
+
+ rc = strict_strtoul(buf, 10, &value);
+ if (rc < 0) {
+ dev_err(dev, "%s: Invalid value\n", __func__);
+ return size;
+ }
+
+ /* Expecting only 0 or 1 */
+ if (value != 0 && value != 1) {
+ dev_err(dev, "%s: Invalid value %lu\n", __func__, value);
+ return size;
+ }
+
+ mutex_lock(&dd->sysfs_lock);
+ dd->formated_output = value;
+ mutex_unlock(&dd->sysfs_lock);
+ return size;
+}
+
+static DEVICE_ATTR(formated_output, S_IRUSR | S_IWUSR,
+ cyttsp4_formated_output_show, cyttsp4_formated_output_store);
+
+static int cyttsp4_debug_probe(struct cyttsp4_device *ttsp)
+{
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_debug_data *dd;
+ struct cyttsp4_debug_platform_data *pdata = dev_get_platdata(dev);
+ int rc;
+
+ dev_info(dev, "%s: startup\n", __func__);
+ dev_dbg(dev, "%s: debug on\n", __func__);
+ dev_vdbg(dev, "%s: verbose debug on\n", __func__);
+
+ /* get context and debug print buffers */
+ dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+ if (dd == NULL) {
+ dev_err(dev, "%s: Error, kzalloc\n", __func__);
+ rc = -ENOMEM;
+ goto cyttsp4_debug_probe_alloc_failed;
+ }
+
+ rc = device_create_file(dev, &dev_attr_int_count);
+ if (rc) {
+ dev_err(dev, "%s: Error, could not create int_count\n",
+ __func__);
+ goto cyttsp4_debug_probe_create_int_count_failed;
+ }
+
+ rc = device_create_file(dev, &dev_attr_formated_output);
+ if (rc) {
+ dev_err(dev, "%s: Error, could not create formated_output\n",
+ __func__);
+ goto cyttsp4_debug_probe_create_formated_failed;
+ }
+
+ mutex_init(&dd->sysfs_lock);
+ dd->ttsp = ttsp;
+ dd->pdata = pdata;
+ dev_set_drvdata(dev, dd);
+
+ pm_runtime_enable(dev);
+
+ pm_runtime_get_sync(dev);
+ dd->si = cyttsp4_request_sysinfo(ttsp);
+ if (dd->si == NULL) {
+ dev_err(dev, "%s: Fail get sysinfo pointer from core\n",
+ __func__);
+ rc = -ENODEV;
+ goto cyttsp4_debug_probe_sysinfo_failed;
+ }
+
+ rc = cyttsp4_subscribe_attention(ttsp, CY_ATTEN_IRQ,
+ cyttsp4_debug_attention, CY_MODE_OPERATIONAL);
+ if (rc < 0) {
+ dev_err(dev, "%s: Error, could not subscribe attention cb\n",
+ __func__);
+ goto cyttsp4_debug_probe_subscribe_failed;
+ }
+ pm_runtime_put(dev);
+
+ return 0;
+
+cyttsp4_debug_probe_subscribe_failed:
+cyttsp4_debug_probe_sysinfo_failed:
+ pm_runtime_put(dev);
+ pm_runtime_suspend(dev);
+ pm_runtime_disable(dev);
+ dev_set_drvdata(dev, NULL);
+ device_remove_file(dev, &dev_attr_formated_output);
+cyttsp4_debug_probe_create_formated_failed:
+ device_remove_file(dev, &dev_attr_int_count);
+cyttsp4_debug_probe_create_int_count_failed:
+ kfree(dd);
+cyttsp4_debug_probe_alloc_failed:
+ dev_err(dev, "%s failed.\n", __func__);
+ return rc;
+}
+
+static int cyttsp4_debug_release(struct cyttsp4_device *ttsp)
+{
+ struct device *dev = &ttsp->dev;
+ struct cyttsp4_debug_data *dd = dev_get_drvdata(dev);
+ int rc = 0;
+ dev_dbg(dev, "%s\n", __func__);
+
+ if (dev_get_drvdata(&ttsp->core->dev) == NULL) {
+ dev_err(dev, "%s: Error, core driver does not exist. "
+ "Unable to un-subscribe attention\n",
+ __func__);
+ goto cyttsp4_debug_release_exit;
+ }
+
+ rc = cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_IRQ,
+ cyttsp4_debug_attention, CY_MODE_OPERATIONAL);
+ if (rc < 0) {
+ dev_err(dev, "%s: Error, "
+ "could not un-subscribe attention\n",
+ __func__);
+ goto cyttsp4_debug_release_exit;
+ }
+
+cyttsp4_debug_release_exit:
+ pm_runtime_suspend(dev);
+ pm_runtime_disable(dev);
+ device_remove_file(dev, &dev_attr_int_count);
+ dev_set_drvdata(dev, NULL);
+ kfree(dd);
+
+ return rc;
+}
+
+static struct cyttsp4_driver cyttsp4_debug_driver = {