Commit 8937346d4dca27fcf96080b6992e3c8d87f70046

Authored by 김태훈
Exists in master and in 2 other branches fhd, fhd-demo

Merge branch 'master' of 192.168.10.12:falinux/1611_0007_prime_oven

README.md
... ... @@ -1,196 +0,0 @@
1   -
2   -## [컴파일러 설치]
3   ----------------------------
4   -* docker/toolchain 디렉토리의 arm-buildroot-linux-gnueabihf-4.9.4.tar.gz 파일을 /opt 디렉토리에 풀어 사용한다.
5   -
6   - $ cd docker/toolchain/
7   - $ sudo tar zxvf arm-buildroot-linux-gnueabihf-4.9.4.tar.gz -C /opt
8   -
9   -
10   -## [컴파일을 위한 환경파일]
11   ----------------------------
12   -
13   -* 환경파일 env-4.9.4.env
14   -
15   - export WORK_TOP_PATH=$(pwd)
16   -
17   - export FA_COMPANY=falinux
18   - export FA_CHIPSET=imx6s
19   - export FA_PRODUCT=prime_oven
20   -
21   - export BR_TOOLCHAIN_PREFIX=arm-buildroot-linux-gnueabihf
22   - export BR_TOOLCHAIN_PATH=/opt/toolchain/${FA_CHIPSET}/${FA_PRODUCT}
23   -
24   - export CROSS_COMPILE=${BR_TOOLCHAIN_PREFIX}-
25   - export ARCH=arm
26   -
27   - export PATH=${BR_TOOLCHAIN_PATH}/usr/bin:$PATH
28   - export WORK_LD_LIBRARY_PATH=${BR_TOOLCHAIN_PATH}/usr/lib
29   -
30   -
31   -* source 유틸리티를 사용하여 환경을 설정한다.
32   -
33   - $ source env-4.9.4.env
34   -
35   -
36   -
37   -
38   -## [부트로더 컴파일]
39   ----------------------------
40   -
41   -* 부트로더 컴파일을 위해서 gcc-arm-none-eabi 가 필요하다.
42   -
43   - $ sudo apt-get install -y gcc-arm-none-eabi
44   -
45   -* 부트로더 디렉토리로 이동한다.
46   -
47   - $ cd bootloader/u-boot_2015_04
48   - $ cd ../../
49   - $ source env-4.9.4.env # (이미 실행하였다면 하지 않아도 된다)
50   - $ cd bootloader/u-boot_2015_04
51   -
52   -* u-boot 환경 파일
53   -
54   - imx6s_prime_oven_defconfig
55   -
56   -* 컴파일은 make.sh 를 사용한다.
57   -
58   - $ ./make.sh
59   -
60   - -- 필요한 경우 clean ----
61   - $ ./make.sh clean
62   -
63   -
64   -* 컴파일 결과물은 ../output-u-boot_2015_04 에 저장된다.
65   -
66   -* 빌드가 정상적으로 완료되면 u-boot.imx 파일이 /tftpboot/prime-oven 및 /nfs/prime-oven에 복사된다.
67   -
68   -
69   -
70   -
71   -## [커널 컴파일]
72   ----------------------------
73   -
74   -* 커널 디렉토리로 이동한다.
75   -
76   - $ cd kernel/linux-imx6_3.14.28
77   - $ cd ../../
78   - $ source env-4.9.4.env # (이미 실행하였다면 하지 않아도 된다)
79   - $ cd kernel/linux-imx6_3.14.28
80   -
81   -
82   -* kernel 환경 파일
83   -
84   - arch/arm/configs/imx6s_prime_oven_defconfig
85   -
86   -* 컴파일은 make.sh 를 사용한다.
87   -
88   - $ ./make.sh
89   -
90   - -- 필요한 경우 clean ----
91   - $ ./make.sh clean
92   -
93   - -- 환경수정이 필요하다면 ----
94   - $ ./make.sh menuconfig
95   -
96   -
97   -* 컴파일 결과물은 ../output-linux-imx6_3.14.28 에 저장된다.
98   -
99   -* 컴파일이 완료되면 uImage 파일과 imx6s-prime-oven.dtb 파일이 /tftpboot/prime-oven 및 /nfs/prime-oven에 복사된다.
100   -
101   -
102   -
103   -## [RFS, buildroot 컴파일]
104   ----------------------------
105   -
106   -* buildroot 디렉토리 buildroot 로 이동한다.
107   -
108   - $ cd buildroot/buildroot-2016.08.1
109   - $ cd ../../
110   - $ source env-4.9.4.env # (이미 실행하였다면 하지 않아도 된다)
111   - $ cd buildroot/buildroot-2016.08.1
112   -
113   -
114   -* 컴파일은 make.sh 를 사용한다.
115   -
116   - $ ./make.sh
117   -
118   -* 컴파일을 위한 도움말을 보기 위해서는 아래와 같이 사용한다.
119   -
120   - $ ./make.sh help
121   -
122   - [Help]
123   - ssh-key : generate ssh key
124   - defconfig : reload config
125   - toolchain : apply config file for toolchain
126   - qt4_gst : apply config file for QT4/Gstreamer
127   - qt5_gst : apply config file for QT5/Gstreamer
128   - image : generate ramdisk image file
129   - clean-target : clean target directory
130   - distclean : delete all non-source files (.config)
131   - savedefconfig : Save current config to BR2_DEFCONFIG (minimal confi
132   -
133   -* 환경 수정을 위해 menuconfig 를 사용할때는 아래와 같이 사용한다.
134   -
135   - $ ./make.sh menuconfig
136   -
137   -* 환경 파일을 defconfig 에 저장하려면 아래와 같이 사용한다. (함부로 저장하면 안되니 주의할것!!)
138   -
139   - $ ./make.sh savedefconfig
140   -
141   -* toolchain을 다시 빌드하고 싶으면 아래와 같이 실행한다. (/opt/toolchain 경로에 쓰기 권한이 있어야함)
142   -
143   - $ ./make.sh toolchain
144   - $ ./make.sh
145   -
146   -* 환경 파일을 저장하고 싶다면 새로운 환경파일을 만들어 사용하며, 이때는 menuconfig 명령을 통해 해당 파일 이름을 수정하여 사용한다.
147   -
148   -* 컴파일된 후 파일들은 ../output-buildroot-2016.08.1 디렉토리에 생성된다.
149   -
150   -* 램디스크 작업을 위해 아래와 같이 실행한다. 생성된 ramdisk-prime_oven-?M.gz 파일은 /tftpboot/prime-oven 및 /nfs/prime-oven에 복사된다.
151   -
152   - $ ./make.sh image
153   -
154   -* 기본 파일 시스템(램디스크 이미지)을 컴파일하기 위해서는 아래와 같이 사용한다.
155   -
156   - $ ./make.sh clean
157   - $ ./make.sh defconfig
158   - $ ./make.sh
159   - $ ./make.sh image
160   -
161   -* ssh-key를 다시 생성하고 싶으면 아래와 같이 실행한다.
162   -
163   - $ ./make.sh ssh-key
164   -
165   -* menuconfig 를 통해 환경을 수정한 이 후 컴파일시 에러가 발생할 경우 clean 명령을 실행한다.
166   -
167   - $ ./make.sh
168   - ...some errors...
169   - $ ./make.sh clean
170   - $ ./make.sh defconfig
171   - $ ./make.sh image
172   -
173   -
174   -## [파티션]
175   ----------------------------
176   -
177   - start size desc
178   - ---------- ---------- ----------------------------
179   - 0-MB 128-MB raw area
180   - 128-MB 128-MB partition#1, ext3 : BOOT0
181   - 256-MB 256-MB partition#2, ext4 : SYSTEM
182   - 512-MB 512-MB partition#3, ext4 : FALINUX
183   - 1024-MB all partition#4, ext4 : PRIME
184   -
185   -
186   - -----------------------------------------------------
187   - 0-MB 128-MB raw area
188   - -----------------------------------------------------
189   - start size start size
190   - -----------------------------------------------------
191   - U-boot : 1KB 640KB ( 0x2 0x500 )
192   - Logo : 1MB 4.5MB ( 0x800 0x2400 )
193   - DTB : 5.5MB 128KB ( 0x2C00 0x100 )
194   - KERNEL : 6MB 7MB ( 0x3000 0x3800 )
195   - RAMDISK : 14MB 64MB ( 0x7000 0x20000 )
196   -
buildroot/buildroot-2016.08.1/board/falinux/prime_oven/rootfs_overlay/root/.prime_oven/.buildroot_version
... ... @@ -1 +0,0 @@
1   -2017. 03. 10. (금) 13:02:36 KST
kernel/linux-imx6_3.14.28/arch/arm/boot/dts/imx6qdl-prime-oven.dtsi
... ... @@ -377,7 +377,15 @@
377 377 reg = <0x68>;
378 378 };
379 379  
380   - tsc2007: tsc2007@48 {
  380 +};
  381 +
  382 +&i2c3 {
  383 + clock-frequency = <100000>;
  384 + pinctrl-names = "default";
  385 + pinctrl-0 = <&pinctrl_i2c3>;
  386 + status = "okay";
  387 +
  388 + tsc2007: tsc2007@48 {
381 389 compatible = "ti,tsc2007";
382 390 reg = <0x48>;
383 391 pinctrl-names = "default";
... ... @@ -389,13 +397,6 @@
389 397 };
390 398 };
391 399  
392   -&i2c3 {
393   - clock-frequency = <100000>;
394   - pinctrl-names = "default";
395   - pinctrl-0 = <&pinctrl_i2c3>;
396   - status = "okay";
397   -};
398   -
399 400 &ldb {
400 401 split-mode = <1>;
401 402 status = "okay";
... ...
kernel/linux-imx6_3.14.28/arch/arm/boot/dts/imx6s-prime-oven.dts
... ... @@ -21,24 +21,14 @@
21 21 model = "Freescale i.MX6 Solo/DualLite Prime Oven Device Board(PFUZE100)";
22 22 compatible = "fsl,imx6dl-prime-oven", "fsl,imx6dl";
23 23  
24   - rotary@0 {
25   - compatible = "rotary-encoder";
26   - gpios = <&gpio6 11 1>, <&gpio6 10 1>;
27   - linux,axis = <1>; /* ABS_Y */
28   - rotary-encoder,steps = <24>;
29   - rotary-encoder,rollover;
30   - };
31   -
32   - gpio_keys {
33   - compatible = "gpio-keys";
34   - #address-cells = <1>;
35   - #size-cells = <0>;
36   - autorepeat;
37   - button@21 {
38   - label = "GPIO Key UP";
39   - linux,code = <KEY_UP>;
40   - gpios = <&gpio6 14 1>;
41   - };
  24 + prime_encoder@0 {
  25 + compatible = "prime-encoder";
  26 + gpios = <&gpio6 11 1>, <&gpio6 10 1>, <&gpio6 14 1>;
  27 + /* add larche@falinux.com - private value */
  28 + prime-encoder,button;
  29 + prime-encoder,left_code = <KEY_F1>;
  30 + prime-encoder,right_code = <KEY_F3>;
  31 + prime-encoder,center_code = <KEY_F2>;
42 32 };
43 33 };
44 34  
... ...
kernel/linux-imx6_3.14.28/arch/arm/configs/imx6s_prime_oven_defconfig
... ... @@ -1388,7 +1388,8 @@ CONFIG_INPUT_MISC=y
1388 1388 # CONFIG_INPUT_CM109 is not set
1389 1389 # CONFIG_INPUT_UINPUT is not set
1390 1390 # CONFIG_INPUT_PCF8574 is not set
1391   -CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
  1391 +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
  1392 +CONFIG_INPUT_GPIO_PRIME_ENCODER=y
1392 1393 # CONFIG_INPUT_ADXL34X is not set
1393 1394 # CONFIG_INPUT_IMS_PCU is not set
1394 1395 # CONFIG_INPUT_CMA3000 is not set
... ...
kernel/linux-imx6_3.14.28/drivers/input/misc/Kconfig
... ... @@ -490,6 +490,17 @@ config INPUT_GPIO_ROTARY_ENCODER
490 490 To compile this driver as a module, choose M here: the
491 491 module will be called rotary_encoder.
492 492  
  493 +config INPUT_GPIO_PRIME_ENCODER
  494 + tristate "Prime encoders connected to GPIO pins"
  495 + depends on GPIOLIB
  496 + help
  497 + Say Y here to add support for rotary encoders connected to GPIO lines.
  498 + Check file:Documentation/input/rotary-encoder.txt for more
  499 + information.
  500 +
  501 + To compile this driver as a module, choose M here: the
  502 + module will be called rotary_encoder.
  503 +
493 504 config INPUT_RB532_BUTTON
494 505 tristate "Mikrotik Routerboard 532 button interface"
495 506 depends on MIKROTIK_RB532
... ...
kernel/linux-imx6_3.14.28/drivers/input/misc/Makefile
... ... @@ -51,6 +51,7 @@ obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
51 51 obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
52 52 obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o
53 53 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
  54 +obj-$(CONFIG_INPUT_GPIO_PRIME_ENCODER) += prime_encoder.o
54 55 obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
55 56 obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
56 57 obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
... ...
kernel/linux-imx6_3.14.28/drivers/input/misc/prime_encoder.c
... ... @@ -0,0 +1,378 @@
  1 +/*
  2 + * rotary_encoder.c
  3 + *
  4 + * (c) 2009 Daniel Mack <daniel@caiaq.de>
  5 + * Copyright (C) 2011 Johan Hovold <jhovold@gmail.com>
  6 + *
  7 + * state machine code inspired by code from Tim Ruetz
  8 + *
  9 + * A generic driver for rotary encoders connected to GPIO lines.
  10 + * See file:Documentation/input/rotary-encoder.txt for more information
  11 + *
  12 + * This program is free software; you can redistribute it and/or modify
  13 + * it under the terms of the GNU General Public License version 2 as
  14 + * published by the Free Software Foundation.
  15 + */
  16 +
  17 +#include <linux/kernel.h>
  18 +#include <linux/module.h>
  19 +#include <linux/interrupt.h>
  20 +#include <linux/input.h>
  21 +#include <linux/device.h>
  22 +#include <linux/platform_device.h>
  23 +#include <linux/gpio.h>
  24 +#include <linux/prime_encoder.h>
  25 +#include <linux/slab.h>
  26 +#include <linux/of.h>
  27 +#include <linux/of_platform.h>
  28 +#include <linux/of_gpio.h>
  29 +
  30 +#define DRV_NAME "prime-encoder"
  31 +
  32 +struct rotary_encoder {
  33 + struct input_dev *input;
  34 + const struct rotary_encoder_platform_data *pdata;
  35 +
  36 + unsigned int irq_a;
  37 + unsigned int irq_b;
  38 + // add larche@falinux.com, for button
  39 + unsigned int irq_button;
  40 + char last_value;
  41 + unsigned int l_key_state;
  42 + unsigned int r_key_state;
  43 +};
  44 +
  45 +/***
  46 + * add larche@falinux.com
  47 + *
  48 + * ab
  49 + *
  50 + * 11
  51 + *{R} 10 01 {L}
  52 + * 00
  53 + */
  54 +static int rotary_encoder_get_value(const struct rotary_encoder_platform_data *pdata)
  55 +{
  56 + int a = !!gpio_get_value(pdata->gpio_a);
  57 + int b = !!gpio_get_value(pdata->gpio_b);
  58 + int val = 0;
  59 +
  60 + val&=0x0;
  61 + val|=(a<<1);
  62 + val|=(b<<0);
  63 +
  64 + return val;
  65 +}
  66 +
  67 +static irqreturn_t rotary_encoder_irq_center_button(int irq, void *dev_id)
  68 +{
  69 + struct rotary_encoder *encoder = dev_id;
  70 + const struct rotary_encoder_platform_data *pdata = encoder->pdata;
  71 + int key_state;
  72 +
  73 + key_state = gpio_get_value(pdata->gpio_button) ^ pdata->inverted_button;
  74 + input_event(encoder->input, EV_KEY, pdata->center_code, !!key_state);
  75 + input_sync(encoder->input);
  76 +
  77 + return IRQ_HANDLED;
  78 +}
  79 +
  80 +static irqreturn_t rotary_encoder_irq_single_step(int irq, void *dev_id)
  81 +{
  82 + struct rotary_encoder *encoder = dev_id;
  83 + const struct rotary_encoder_platform_data *pdata = encoder->pdata;
  84 + int state = 0;
  85 + int key_state = 0;
  86 +
  87 + state = rotary_encoder_get_value(pdata);
  88 +
  89 + switch(encoder->last_value)
  90 + {
  91 + case 0x0:
  92 + if(state == 0x2)
  93 + {
  94 + key_state = (encoder->r_key_state ? 0 : 1);
  95 + encoder->r_key_state = key_state;
  96 + input_event(encoder->input, EV_KEY, pdata->right_code, !!key_state);
  97 + }
  98 + else if(state == 0x1)
  99 + {
  100 + key_state = (encoder->l_key_state ? 0 : 1);
  101 + encoder->l_key_state = key_state;
  102 + input_event(encoder->input, EV_KEY, pdata->left_code, !!key_state);
  103 + }
  104 +
  105 + break;
  106 +
  107 + case 0x1:
  108 + if(state == 0x0)
  109 + {
  110 + key_state = (encoder->r_key_state ? 0 : 1);
  111 + encoder->r_key_state = key_state;
  112 + input_event(encoder->input, EV_KEY, pdata->right_code, !!key_state);
  113 + }
  114 + else if(state == 0x3)
  115 + {
  116 + key_state = (encoder->l_key_state ? 0 : 1);
  117 + encoder->l_key_state = key_state;
  118 + input_event(encoder->input, EV_KEY, pdata->left_code, !!key_state);
  119 + }
  120 +
  121 + break;
  122 +
  123 + case 0x2:
  124 + if(state == 0x3)
  125 + {
  126 + key_state = (encoder->r_key_state ? 0 : 1);
  127 + encoder->r_key_state = key_state;
  128 + input_event(encoder->input, EV_KEY, pdata->right_code, !!key_state);
  129 + }
  130 + else if(state == 0x0)
  131 + {
  132 + key_state = (encoder->l_key_state ? 0 : 1);
  133 + encoder->l_key_state = key_state;
  134 + input_event(encoder->input, EV_KEY, pdata->left_code, !!key_state);
  135 + }
  136 +
  137 + break;
  138 +
  139 + case 0x3:
  140 + if(state == 0x1)
  141 + {
  142 + key_state = (encoder->r_key_state ? 0 : 1);
  143 + encoder->r_key_state = key_state;
  144 + input_event(encoder->input, EV_KEY, pdata->right_code, !!key_state);
  145 + }
  146 + else if(state == 0x2)
  147 + {
  148 + key_state = (encoder->l_key_state ? 0 : 1);
  149 + encoder->l_key_state = key_state;
  150 + input_event(encoder->input, EV_KEY, pdata->left_code, !!key_state);
  151 + }
  152 +
  153 + break;
  154 + }
  155 +
  156 + input_sync(encoder->input);
  157 +
  158 + encoder->last_value = state;
  159 +
  160 + return IRQ_HANDLED;
  161 +}
  162 +
  163 +#ifdef CONFIG_OF
  164 +static struct of_device_id rotary_encoder_of_match[] = {
  165 + { .compatible = "prime-encoder", },
  166 + { },
  167 +};
  168 +MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
  169 +
  170 +static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct device *dev)
  171 +{
  172 + const struct of_device_id *of_id =
  173 + of_match_device(rotary_encoder_of_match, dev);
  174 + struct device_node *np = dev->of_node;
  175 + struct rotary_encoder_platform_data *pdata;
  176 + enum of_gpio_flags flags;
  177 +
  178 + if (!of_id || !np)
  179 + return NULL;
  180 +
  181 + pdata = kzalloc(sizeof(struct rotary_encoder_platform_data),
  182 + GFP_KERNEL);
  183 + if (!pdata)
  184 + return ERR_PTR(-ENOMEM);
  185 +
  186 + pdata->gpio_a = of_get_gpio_flags(np, 0, &flags);
  187 + pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW;
  188 +
  189 + pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
  190 + pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
  191 +
  192 + // add larche@falinux.com
  193 + pdata->is_button = !!of_get_property(np,
  194 + "prime-encoder,button", NULL);
  195 + if(pdata->is_button) {
  196 + pdata->gpio_button = of_get_gpio_flags(np, 2, &flags);
  197 + pdata->inverted_button = flags & OF_GPIO_ACTIVE_LOW;
  198 + if( of_property_read_u32( np, "prime-encoder,left_code", &pdata->left_code) )
  199 + pdata->left_code = KEY_F1;
  200 + if( of_property_read_u32( np, "prime-encoder,right_code", &pdata->right_code) )
  201 + pdata->right_code = KEY_F2;
  202 + if( of_property_read_u32( np, "prime-encoder,center_code", &pdata->center_code) )
  203 + pdata->center_code = KEY_F3;
  204 + }
  205 +
  206 + return pdata;
  207 +}
  208 +#else
  209 +static inline struct rotary_encoder_platform_data *
  210 +rotary_encoder_parse_dt(struct device *dev)
  211 +{
  212 + return NULL;
  213 +}
  214 +#endif
  215 +
  216 +static int rotary_encoder_probe(struct platform_device *pdev)
  217 +{
  218 + struct device *dev = &pdev->dev;
  219 + const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev);
  220 + struct rotary_encoder *encoder;
  221 + struct input_dev *input;
  222 + irq_handler_t handler;
  223 + irq_handler_t handler_button;
  224 + int err;
  225 +
  226 + if (!pdata) {
  227 + pdata = rotary_encoder_parse_dt(dev);
  228 + if (IS_ERR(pdata))
  229 + return PTR_ERR(pdata);
  230 +
  231 + if (!pdata) {
  232 + dev_err(dev, "missing platform data\n");
  233 + return -EINVAL;
  234 + }
  235 + }
  236 +
  237 + encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL);
  238 + input = input_allocate_device();
  239 + if (!encoder || !input) {
  240 + err = -ENOMEM;
  241 + goto exit_free_mem;
  242 + }
  243 +
  244 + encoder->input = input;
  245 + encoder->pdata = pdata;
  246 +
  247 + input->name = pdev->name;
  248 + input->id.bustype = BUS_HOST;
  249 + input->dev.parent = dev;
  250 +
  251 + /* request the GPIOs */
  252 + err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev));
  253 + if (err) {
  254 + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a);
  255 + goto exit_free_mem;
  256 + }
  257 +
  258 + err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev));
  259 + if (err) {
  260 + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b);
  261 + goto exit_free_gpio_a;
  262 + }
  263 +
  264 + if(pdata->is_button) {
  265 + err = gpio_request_one(pdata->gpio_button, GPIOF_IN, dev_name(dev));
  266 + if (err) {
  267 + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_button);
  268 + goto exit_free_gpio_b;
  269 + }
  270 + }
  271 +
  272 + encoder->irq_a = gpio_to_irq(pdata->gpio_a);
  273 + encoder->irq_b = gpio_to_irq(pdata->gpio_b);
  274 + encoder->irq_button = gpio_to_irq(pdata->gpio_button);
  275 +
  276 + handler = &rotary_encoder_irq_single_step;
  277 + handler_button = &rotary_encoder_irq_center_button;
  278 + encoder->last_value = rotary_encoder_get_value(pdata);
  279 +
  280 + err = request_irq(encoder->irq_a, handler,
  281 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  282 + DRV_NAME, encoder);
  283 + if (err) {
  284 + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
  285 + goto exit_free_gpio_button;
  286 + }
  287 +
  288 + err = request_irq(encoder->irq_b, handler,
  289 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  290 + DRV_NAME, encoder);
  291 + if (err) {
  292 + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
  293 + goto exit_free_irq_a;
  294 + }
  295 +
  296 + err = request_irq(encoder->irq_button, handler_button,
  297 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  298 + DRV_NAME, encoder);
  299 + if (err) {
  300 + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
  301 + goto exit_free_irq_b;
  302 + }
  303 +
  304 + err = input_register_device(input);
  305 + if (err) {
  306 + dev_err(dev, "failed to register input device\n");
  307 + goto exit_free_irq_button;
  308 + }
  309 +
  310 + input_set_capability(input, EV_KEY, pdata->left_code); // Left
  311 + input_set_capability(input, EV_KEY, pdata->right_code); // Right
  312 + input_set_capability(input, EV_KEY, pdata->center_code); // Center
  313 +
  314 + encoder->l_key_state = 0;
  315 + encoder->r_key_state = 0;
  316 +
  317 + platform_set_drvdata(pdev, encoder);
  318 +
  319 + return 0;
  320 +
  321 +exit_free_irq_button:
  322 + free_irq(encoder->irq_button, encoder);
  323 +exit_free_irq_b:
  324 + free_irq(encoder->irq_b, encoder);
  325 +exit_free_irq_a:
  326 + free_irq(encoder->irq_a, encoder);
  327 +exit_free_gpio_button:
  328 + if(pdata->is_button) {
  329 + gpio_free(pdata->gpio_button);
  330 + }
  331 +exit_free_gpio_b:
  332 + gpio_free(pdata->gpio_b);
  333 +exit_free_gpio_a:
  334 + gpio_free(pdata->gpio_a);
  335 +exit_free_mem:
  336 + input_free_device(input);
  337 + kfree(encoder);
  338 + if (!dev_get_platdata(&pdev->dev))
  339 + kfree(pdata);
  340 +
  341 + return err;
  342 +
  343 +}
  344 +
  345 +static int rotary_encoder_remove(struct platform_device *pdev)
  346 +{
  347 + struct rotary_encoder *encoder = platform_get_drvdata(pdev);
  348 + const struct rotary_encoder_platform_data *pdata = encoder->pdata;
  349 +
  350 + free_irq(encoder->irq_a, encoder);
  351 + free_irq(encoder->irq_b, encoder);
  352 + gpio_free(pdata->gpio_a);
  353 + gpio_free(pdata->gpio_b);
  354 +
  355 + input_unregister_device(encoder->input);
  356 + kfree(encoder);
  357 +
  358 + if (!dev_get_platdata(&pdev->dev))
  359 + kfree(pdata);
  360 +
  361 + return 0;
  362 +}
  363 +
  364 +static struct platform_driver rotary_encoder_driver = {
  365 + .probe = rotary_encoder_probe,
  366 + .remove = rotary_encoder_remove,
  367 + .driver = {
  368 + .name = DRV_NAME,
  369 + .owner = THIS_MODULE,
  370 + .of_match_table = of_match_ptr(rotary_encoder_of_match),
  371 + }
  372 +};
  373 +module_platform_driver(rotary_encoder_driver);
  374 +
  375 +MODULE_ALIAS("platform:" DRV_NAME);
  376 +MODULE_DESCRIPTION("GPIO rotary encoder driver");
  377 +MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold");
  378 +MODULE_LICENSE("GPL v2");
... ...
kernel/linux-imx6_3.14.28/include/linux/prime_encoder.h
... ... @@ -0,0 +1,17 @@
  1 +#ifndef __ROTARY_ENCODER_H__
  2 +#define __ROTARY_ENCODER_H__
  3 +
  4 +struct rotary_encoder_platform_data {
  5 + unsigned int gpio_a;
  6 + unsigned int gpio_b;
  7 + unsigned int gpio_button;
  8 + unsigned int inverted_a;
  9 + unsigned int inverted_b;
  10 + unsigned int inverted_button;
  11 + unsigned int left_code;
  12 + unsigned int right_code;
  13 + unsigned int center_code;
  14 + bool is_button;
  15 +};
  16 +
  17 +#endif /* __ROTARY_ENCODER_H__ */
... ...
release/imx6s-prime-oven.dtb
No preview for this file type