samsung-i927: Kernel updates (!217)

- Use separated patches
- Use new panel driver (with backlight support)
- Battery fixes
- Fix compass (AK8975) (not tested, only probing works, but sometimes
  doesn't - says "Unexpected device" - need to investigate that)
- Touchkey is working + LED
- Keyboard backlight + HALL for slideout detection
This commit is contained in:
Sergey Larin 2019-02-09 21:46:43 +03:00 committed by Oliver Smith
parent 62b145d8db
commit 6b1072a789
37 changed files with 5152 additions and 3098 deletions

View file

@ -0,0 +1,71 @@
From 2b9e681359e72c3ee0387dfc9b10ec9a7f548c97 Mon Sep 17 00:00:00 2001
From: Jonathan Bakker <xc-racer2@live.ca>
Date: Tue, 12 Jun 2018 11:32:26 -0700
Subject: [PATCH 01/34] dt-bindings: drm: panel: Add Samsung s6e63m0 panel
documentation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit adds documentation for Samsung s6e63m0 AMOLED LCD panel
driver.
Signed-off-by: Jonathan Bakker <xc-racer2@live.ca>
Signed-off-by: Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
---
Changes from v1:
- Add missing subject prefix
- Rename reset-gpio to reset-gpios
- Add link to spi properites documentation. They're required
for driver to work
- Removed delay properties, which are now hardcoded in driver
- Removed display timings, which are now hardcoded in driver
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
.../display/panel/samsung,s6e63m0.txt | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.txt
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.txt
new file mode 100644
index 000000000000..9fb9ebeef8e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e63m0.txt
@@ -0,0 +1,33 @@
+Samsung s6e63m0 AMOLED LCD panel
+
+Required properties:
+ - compatible: "samsung,s6e63m0"
+ - reset-gpios: GPIO spec for reset pin
+ - vdd3-supply: VDD regulator
+ - vci-supply: VCI regulator
+
+The panel must obey rules for SPI slave device specified in document [1].
+
+The device node can contain one 'port' child node with one child
+'endpoint' node, according to the bindings defined in [2]. This
+node should describe panel's video bus.
+
+[1]: Documentation/devicetree/bindings/spi/spi-bus.txt
+[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+
+ s6e63m0: display@0 {
+ compatible = "samsung,s6e63m0";
+ reg = <0>;
+ reset-gpio = <&mp05 5 1>;
+ vdd3-supply = <&ldo12_reg>;
+ vci-supply = <&ldo11_reg>;
+ spi-max-frequency = <1200000>;
+
+ port {
+ lcd_ep: endpoint {
+ remote-endpoint = <&fimd_ep>;
+ };
+ };
+ };
--
2.20.1

View file

@ -0,0 +1,620 @@
From 837ca6b151a2ffe19b622a22351ea4a19c1d2cfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Chmiel?= <pawel.mikolaj.chmiel@gmail.com>
Date: Fri, 25 Jan 2019 16:32:08 +0100
Subject: [PATCH 02/34] drm/panel: Add driver for Samsung S6E63M0 panel
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds Samsung S6E63M0 AMOLED LCD panel driver, connected over
spi. It's based on already removed, non dt s6e63m0 driver and
panel-samsung-ld9040. It can be found for example in some of Samsung
Aries based phones.
Signed-off-by: Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
---
Changes from v2:
- VIDEOMODE_HELPERS is not needed in Kconfig
- Added help text to Kconfig
- Remove unneeded videomode includes/fields
- Add sentinel comment in s6e63m0_of_match struct
- Handle errors during registration of backlight device. We shouldn't
register panel if we fail to register backlight device
- Added Reviewed-by
Changes from v1:
- Correct order of Kconfig/Makefile entry
- Fix SPDX tag, so it matches value of MODULE_LICENSE
- Remove inclusion of drmP.h
- Fix code formatting
- Use DRM_DEV_ERROR/DEBUG
- Extract hardcoded values
- Remove possibility to change gamma through sysfs, leaving only one
gamma table values
- Fix reset_gpio handling, so it'll be asserted in power_on and
deasserted in power_off. Also do it before turning voltage on.
- Disable backlight and enter sleep mode in disable callback.
Previously it was done in unprepare
- Enable display and backlight in enable callback. Previously it was
done in prepare
- Hardcode display timings and delays. Previously they were readed
from device tree
- We're using SPDX, so we don't need to have license body
- Use MIPI_DCS_EXIT_SLEEP_MODE and MIPI_DCS_SET_DISPLAY_ON
- Rename MAX_GAMMA_LEVEL to NUM_GAMMA_LEVELS
- Ommit get_brightness callback
- Use backlight_enable/disable API, like it's done in other panel
drivers (for example panel-simple)
- Make set_brightness called only from backlight api, like it's done
in other panel drivers (for example panel-simple).
- Reset gpio should be set to GPIOD_OUT_HIGH. It's declared as active
low in device tree
- Don't call power_off in remove callback
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/gpu/drm/panel/Kconfig | 9 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 517 ++++++++++++++++++
3 files changed, 527 insertions(+)
create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6020c30a33b3..1a2c1d756bd3 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -140,6 +140,15 @@ config DRM_PANEL_SAMSUNG_S6E63J0X03
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
+config DRM_PANEL_SAMSUNG_S6E63M0
+ tristate "Samsung S6E63M0 RGB/SPI panel"
+ depends on OF
+ depends on SPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Samsung s6e63m0
+ AMOLED LCD panel.
+
config DRM_PANEL_SAMSUNG_S6E8AA0
tristate "Samsung S6E8AA0 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 5ccaaa9d13af..fd6fbcf7808c 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
new file mode 100644
index 000000000000..4312aa3e4386
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -0,0 +1,517 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * S6E63M0 AMOLED LCD drm_panel driver.
+ *
+ * Copyright (C) 2019 Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
+ * Derived from drivers/gpu/drm/panel-samsung-ld9040.c
+ *
+ * Andrzej Hajda <a.hajda@samsung.com>
+ */
+
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <video/mipi_display.h>
+
+/* Manufacturer Command Set */
+#define MCS_ELVSS_ON 0xb1
+#define MCS_ACL_CTRL 0xc0
+#define MCS_DISPLAY_CONDITION 0xf2
+#define MCS_ETC_CONDITION 0xf6
+#define MCS_PANEL_CONDITION 0xF8
+#define MCS_GAMMA_CTRL 0xfa
+
+#define NUM_GAMMA_LEVELS 11
+#define GAMMA_TABLE_COUNT 23
+
+#define DATA_MASK 0x100
+
+#define MAX_BRIGHTNESS (NUM_GAMMA_LEVELS - 1)
+
+/* array of gamma tables for gamma value 2.2 */
+static u8 const s6e63m0_gamma_22[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = {
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8,
+ 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7,
+ 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0,
+ 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF,
+ 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF,
+ 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC,
+ 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC,
+ 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9,
+ 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB,
+ 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8,
+ 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA,
+ 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6,
+ 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8,
+ 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4,
+ 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9,
+ 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3,
+ 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6,
+ 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2,
+ 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6,
+ 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1,
+ 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 },
+ { MCS_GAMMA_CTRL, 0x00,
+ 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6,
+ 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0,
+ 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb },
+};
+
+struct s6e63m0 {
+ struct device *dev;
+ struct drm_panel panel;
+ struct backlight_device *bl_dev;
+
+ struct regulator_bulk_data supplies[2];
+ struct gpio_desc *reset_gpio;
+
+ bool prepared;
+ bool enabled;
+
+ /*
+ * This field is tested by functions directly accessing bus before
+ * transfer, transfer is skipped if it is set. In case of transfer
+ * failure or unexpected response the field is set to error value.
+ * Such construct allows to eliminate many checks in higher level
+ * functions.
+ */
+ int error;
+};
+
+static const struct drm_display_mode default_mode = {
+ .clock = 25628,
+ .hdisplay = 480,
+ .hsync_start = 480 + 16,
+ .hsync_end = 480 + 16 + 2,
+ .htotal = 480 + 16 + 2 + 16,
+ .vdisplay = 800,
+ .vsync_start = 800 + 28,
+ .vsync_end = 800 + 28 + 2,
+ .vtotal = 800 + 28 + 2 + 1,
+ .vrefresh = 60,
+ .width_mm = 53,
+ .height_mm = 89,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static inline struct s6e63m0 *panel_to_s6e63m0(struct drm_panel *panel)
+{
+ return container_of(panel, struct s6e63m0, panel);
+}
+
+static int s6e63m0_clear_error(struct s6e63m0 *ctx)
+{
+ int ret = ctx->error;
+
+ ctx->error = 0;
+ return ret;
+}
+
+static int s6e63m0_spi_write_word(struct s6e63m0 *ctx, u16 data)
+{
+ struct spi_device *spi = to_spi_device(ctx->dev);
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = &data,
+ };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(spi, &msg);
+}
+
+static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
+{
+ int ret = 0;
+
+ if (ctx->error < 0 || len == 0)
+ return;
+
+ DRM_DEV_DEBUG(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data);
+ ret = s6e63m0_spi_write_word(ctx, *data);
+
+ while (!ret && --len) {
+ ++data;
+ ret = s6e63m0_spi_write_word(ctx, *data | DATA_MASK);
+ }
+
+ if (ret) {
+ DRM_DEV_ERROR(ctx->dev, "error %d writing dcs seq: %*ph\n", ret,
+ (int)len, data);
+ ctx->error = ret;
+ }
+
+ usleep_range(300, 310);
+}
+
+#define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
+ ({ \
+ static const u8 d[] = { seq }; \
+ s6e63m0_dcs_write(ctx, d, ARRAY_SIZE(d)); \
+ })
+
+static void s6e63m0_brightness_set(struct s6e63m0 *ctx)
+{
+ int brightness = ctx->bl_dev->props.brightness;
+
+ /* disable and set new gamma */
+ s6e63m0_dcs_write(ctx, s6e63m0_gamma_22[brightness],
+ ARRAY_SIZE(s6e63m0_gamma_22[brightness]));
+
+ /* update gamma table. */
+ s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_CTRL, 0x01);
+}
+
+static void s6e63m0_init(struct s6e63m0 *ctx)
+{
+ s6e63m0_dcs_write_seq_static(ctx, MCS_PANEL_CONDITION,
+ 0x01, 0x27, 0x27, 0x07, 0x07, 0x54, 0x9f,
+ 0x63, 0x86, 0x1a, 0x33, 0x0d, 0x00, 0x00);
+
+ s6e63m0_dcs_write_seq_static(ctx, MCS_DISPLAY_CONDITION,
+ 0x02, 0x03, 0x1c, 0x10, 0x10);
+ s6e63m0_dcs_write_seq_static(ctx, 0xf7,
+ 0x03, 0x00, 0x00);
+
+ s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_CTRL,
+ 0x00, 0x18, 0x08, 0x24, 0x64, 0x56, 0x33,
+ 0xb6, 0xba, 0xa8, 0xac, 0xb1, 0x9d, 0xc1,
+ 0xc1, 0xb7, 0x00, 0x9c, 0x00, 0x9f, 0x00,
+ 0xd6);
+ s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_CTRL,
+ 0x01);
+
+ s6e63m0_dcs_write_seq_static(ctx, MCS_ETC_CONDITION,
+ 0x00, 0x8c, 0x07);
+ s6e63m0_dcs_write_seq_static(ctx, 0xb3,
+ 0xc);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xb5,
+ 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
+ 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
+ 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
+ 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
+ 0x21, 0x20, 0x1e, 0x1e);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xb6,
+ 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44,
+ 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xb7,
+ 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
+ 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
+ 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
+ 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
+ 0x21, 0x20, 0x1e, 0x1e, 0x00, 0x00, 0x11,
+ 0x22, 0x33, 0x44, 0x44, 0x44, 0x55, 0x55,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xb9,
+ 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
+ 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
+ 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
+ 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
+ 0x21, 0x20, 0x1e, 0x1e);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xba,
+ 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44,
+ 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xc1,
+ 0x4d, 0x96, 0x1d, 0x00, 0x00, 0x01, 0xdf,
+ 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06,
+ 0x09, 0x0d, 0x0f, 0x12, 0x15, 0x18);
+
+ s6e63m0_dcs_write_seq_static(ctx, 0xb2,
+ 0x10, 0x10, 0x0b, 0x05);
+
+ s6e63m0_dcs_write_seq_static(ctx, MCS_ACL_CTRL,
+ 0x01);
+
+ s6e63m0_dcs_write_seq_static(ctx, MCS_ELVSS_ON,
+ 0x0b);
+
+ s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
+}
+
+static int s6e63m0_power_on(struct s6e63m0 *ctx)
+{
+ int ret;
+
+ gpiod_set_value(ctx->reset_gpio, 0);
+ msleep(120);
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ msleep(25);
+
+ return 0;
+}
+
+static int s6e63m0_power_off(struct s6e63m0 *ctx)
+{
+ int ret;
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ gpiod_set_value(ctx->reset_gpio, 1);
+ msleep(120);
+
+ return 0;
+}
+
+static int s6e63m0_disable(struct drm_panel *panel)
+{
+ struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
+
+ if (!ctx->enabled)
+ return 0;
+
+ backlight_disable(ctx->bl_dev);
+
+ s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
+ msleep(200);
+
+ ctx->enabled = false;
+
+ return 0;
+}
+
+static int s6e63m0_unprepare(struct drm_panel *panel)
+{
+ struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
+ int ret;
+
+ if (!ctx->prepared)
+ return 0;
+
+ s6e63m0_clear_error(ctx);
+
+ ret = s6e63m0_power_off(ctx);
+ if (ret < 0)
+ return ret;
+
+ ctx->prepared = false;
+
+ return 0;
+}
+
+static int s6e63m0_prepare(struct drm_panel *panel)
+{
+ struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
+ int ret;
+
+ if (ctx->prepared)
+ return 0;
+
+ ret = s6e63m0_power_on(ctx);
+ if (ret < 0)
+ return ret;
+
+ s6e63m0_init(ctx);
+
+ ret = s6e63m0_clear_error(ctx);
+
+ if (ret < 0)
+ s6e63m0_unprepare(panel);
+
+ ctx->prepared = true;
+
+ return ret;
+}
+
+static int s6e63m0_enable(struct drm_panel *panel)
+{
+ struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
+
+ if (ctx->enabled)
+ return 0;
+
+ s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
+
+ backlight_enable(ctx->bl_dev);
+
+ ctx->enabled = true;
+
+ return 0;
+}
+
+static int s6e63m0_get_modes(struct drm_panel *panel)
+{
+ struct drm_connector *connector = panel->connector;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(panel->drm, &default_mode);
+ if (!mode) {
+ DRM_ERROR("failed to add mode %ux%ux@%u\n",
+ default_mode.hdisplay, default_mode.vdisplay,
+ default_mode.vrefresh);
+ return -ENOMEM;
+ }
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs s6e63m0_drm_funcs = {
+ .disable = s6e63m0_disable,
+ .unprepare = s6e63m0_unprepare,
+ .prepare = s6e63m0_prepare,
+ .enable = s6e63m0_enable,
+ .get_modes = s6e63m0_get_modes,
+};
+
+static int s6e63m0_set_brightness(struct backlight_device *bd)
+{
+ struct s6e63m0 *ctx = bl_get_data(bd);
+
+ s6e63m0_brightness_set(ctx);
+
+ return s6e63m0_clear_error(ctx);
+}
+
+static const struct backlight_ops s6e63m0_backlight_ops = {
+ .update_status = s6e63m0_set_brightness,
+};
+
+static int s6e63m0_backlight_register(struct s6e63m0 *ctx)
+{
+ struct backlight_properties props = {
+ .type = BACKLIGHT_RAW,
+ .brightness = MAX_BRIGHTNESS,
+ .max_brightness = MAX_BRIGHTNESS
+ };
+ struct device *dev = ctx->dev;
+ int ret = 0;
+
+ ctx->bl_dev = devm_backlight_device_register(dev, "panel", dev, ctx,
+ &s6e63m0_backlight_ops,
+ &props);
+ if (IS_ERR(ctx->bl_dev)) {
+ ret = PTR_ERR(ctx->bl_dev);
+ DRM_DEV_ERROR(dev, "error registering backlight device (%d)\n",
+ ret);
+ }
+
+ return ret;
+}
+
+static int s6e63m0_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct s6e63m0 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(struct s6e63m0), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, ctx);
+
+ ctx->dev = dev;
+ ctx->enabled = false;
+ ctx->prepared = false;
+
+ ctx->supplies[0].supply = "vdd3";
+ ctx->supplies[1].supply = "vci";
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+ ctx->supplies);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "failed to get regulators: %d\n", ret);
+ return ret;
+ }
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio)) {
+ DRM_DEV_ERROR(dev, "cannot get reset-gpios %ld\n",
+ PTR_ERR(ctx->reset_gpio));
+ return PTR_ERR(ctx->reset_gpio);
+ }
+
+ spi->bits_per_word = 9;
+ spi->mode = SPI_MODE_3;
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ DRM_DEV_ERROR(dev, "spi setup failed.\n");
+ return ret;
+ }
+
+ drm_panel_init(&ctx->panel);
+ ctx->panel.dev = dev;
+ ctx->panel.funcs = &s6e63m0_drm_funcs;
+
+ ret = s6e63m0_backlight_register(ctx);
+ if (ret < 0)
+ return ret;
+
+ return drm_panel_add(&ctx->panel);
+}
+
+static int s6e63m0_remove(struct spi_device *spi)
+{
+ struct s6e63m0 *ctx = spi_get_drvdata(spi);
+
+ drm_panel_remove(&ctx->panel);
+
+ return 0;
+}
+
+static const struct of_device_id s6e63m0_of_match[] = {
+ { .compatible = "samsung,s6e63m0" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s6e63m0_of_match);
+
+static struct spi_driver s6e63m0_driver = {
+ .probe = s6e63m0_probe,
+ .remove = s6e63m0_remove,
+ .driver = {
+ .name = "panel-samsung-s6e63m0",
+ .of_match_table = s6e63m0_of_match,
+ },
+};
+module_spi_driver(s6e63m0_driver);
+
+MODULE_AUTHOR("Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>");
+MODULE_DESCRIPTION("s6e63m0 LCD Driver");
+MODULE_LICENSE("GPL v2");
--
2.20.1

View file

@ -0,0 +1,38 @@
From 6dfb5189947dc913e9e643a82dd0f69efe7b16d7 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 26 Jan 2019 10:41:50 +0300
Subject: [PATCH 03/34] drm/tegra: Hacks for S6E63M0
Pins DATA_ENABLE, H_SYNC, V_SYNC, PIXEL_CLOCK are low polarity,
set this in the registers to make the panel working.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/gpu/drm/tegra/rgb.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index 28a78d3120bc..a61c01b1b6f5 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -39,9 +39,17 @@ static const struct reg_entry rgb_enable[] = {
{ DC_COM_PIN_OUTPUT_ENABLE(2), 0x00000000 },
{ DC_COM_PIN_OUTPUT_ENABLE(3), 0x00000000 },
{ DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
+#ifdef CONFIG_DRM_PANEL_SAMSUNG_S6E63M0
+ { DC_COM_PIN_OUTPUT_POLARITY(1), 0x51000000 },
+#else
{ DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
+#endif
{ DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
+#ifdef CONFIG_DRM_PANEL_SAMSUNG_S6E63M0
+ { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000100 },
+#else
{ DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
+#endif
{ DC_COM_PIN_OUTPUT_DATA(0), 0x00000000 },
{ DC_COM_PIN_OUTPUT_DATA(1), 0x00000000 },
{ DC_COM_PIN_OUTPUT_DATA(2), 0x00000000 },
--
2.20.1

View file

@ -0,0 +1,41 @@
From 081df7f8582115c7b87f3516946acb829a1aa357 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 26 Jan 2019 19:27:36 +0300
Subject: [PATCH 04/34] iio: gyro: mpu3050: get chip ID correctly
According to the datasheet, the first bit of CHIP_ID register specifies
the I2C bus state, and the last one does not belong to ID. Handle this
correctly.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/iio/gyro/mpu3050-core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 77fac81a3adc..0c541cbf13a4 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -29,7 +29,7 @@
#include "mpu3050.h"
-#define MPU3050_CHIP_ID 0x69
+#define MPU3050_CHIP_ID 0x68
/*
* Register map: anything suffixed *_H is a big-endian high byte and always
@@ -1176,8 +1176,8 @@ int mpu3050_common_probe(struct device *dev,
goto err_power_down;
}
- if (val != MPU3050_CHIP_ID) {
- dev_err(dev, "unsupported chip id %02x\n", (u8)val);
+ if ((val & 0x7E) != MPU3050_CHIP_ID) {
+ dev_err(dev, "unsupported chip id %02x\n", (u8)(val & 0x7E));
ret = -ENODEV;
goto err_power_down;
}
--
2.20.1

View file

@ -0,0 +1,28 @@
From baee924a1eb54c7b4283948f7a141134a351a188 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 26 Jan 2019 19:32:58 +0300
Subject: [PATCH 05/34] soc/tegra: fix build for Tegra
Last changes to Linux 4.20 kernel broke the build. Fix it by adding a
config option.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/soc/tegra/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index fe4481676da6..ad5ede8f84ce 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -126,6 +126,7 @@ config SOC_TEGRA_FLOWCTRL
bool
config SOC_TEGRA_PMC
+ select GENERIC_PINCONF
bool
config SOC_TEGRA_POWERGATE_BPMP
--
2.20.1

View file

@ -0,0 +1,38 @@
From 4cb4e6156fa5f942cf004b3e34677f1ee6f32cab Mon Sep 17 00:00:00 2001
From: Dmitry Osipenko <digetx@gmail.com>
Date: Tue, 6 Oct 2015 19:27:48 +0300
Subject: [PATCH 06/34] mmc: core: Add a quirk for NVIDIA Tegra EMMC
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
(cherry picked from commit ab6cd574c16380931529501c367ae50a3ee96b3e)
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/mmc/core/mmc.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 55997cf84b39..643fbe58eb0f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -408,8 +408,17 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
/* Cards with density > 2GiB are sector addressed */
- if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512)
+ if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) {
+ if (card->host->caps & MMC_CAP_NONREMOVABLE) {
+ /*
+ * Size is in 256K chunks, i.e. 512 sectors each.
+ * This algorithm is defined and used by NVIDIA,
+ * according to eMMC 4.41, size is in 128K chunks.
+ */
+ card->ext_csd.sectors -= ext_csd[EXT_CSD_BOOT_MULT] * 512;
+ }
mmc_card_set_blockaddr(card);
+ }
}
card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT];
--
2.20.1

View file

@ -0,0 +1,698 @@
From facbfc379074eb38b85351e78f7a22ae638ebd24 Mon Sep 17 00:00:00 2001
From: ryang <decatf@gmail.com>
Date: Tue, 31 Oct 2017 12:08:54 -0400
Subject: [PATCH 07/34] leds: Add led class support isa1200 vibration motor
(cherry picked from commit e510fd2c344d8f1967e186a3fa030ccee201a4d6)
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/leds/Kconfig | 8 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-isa1200.c | 565 ++++++++++++++++++++++++++++++++++++
drivers/leds/leds-isa1200.h | 71 +++++
4 files changed, 645 insertions(+)
create mode 100644 drivers/leds/leds-isa1200.c
create mode 100755 drivers/leds/leds-isa1200.h
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a72f97fca57b..d659f0174b92 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -766,6 +766,14 @@ config LEDS_NIC78BX
To compile this driver as a module, choose M here: the module
will be called leds-nic78bx.
+config LEDS_ISA1200
+ tristate "LES support for the ISA1200 motor"
+ default n
+ depends on I2C
+ help
+ Say Y to enalbe the ISA1200 IC.
+
+
comment "LED Triggers"
source "drivers/leds/trigger/Kconfig"
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 4c1b0054f379..0ec7806479e9 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_LEDS_MT6323) += leds-mt6323.o
obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o
obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o
obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o
+obj-$(CONFIG_LEDS_ISA1200) += leds-isa1200.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
diff --git a/drivers/leds/leds-isa1200.c b/drivers/leds/leds-isa1200.c
new file mode 100644
index 000000000000..3f14a38a4cbd
--- /dev/null
+++ b/drivers/leds/leds-isa1200.c
@@ -0,0 +1,565 @@
+/*
+ * drivers/motor/isa1200_vibrator.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+
+
+#include <linux/hrtimer.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/pwm.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pinctrl/consumer.h>
+
+#include <asm/mach-types.h>
+#include "leds-isa1200.h"
+
+#define AMPLITUDE_MIN 0
+#define AMPLITUDE_MAX 254
+
+
+struct isa1200_vibrator_drvdata {
+ struct i2c_client *client;
+ struct led_classdev cdev;
+
+ struct clk *vib_clk;
+ struct gpio_desc *enable_gpio;
+
+ struct pinctrl* pinctrl;
+ struct pinctrl_state *on_state;
+ struct pinctrl_state *off_state;
+
+ struct workqueue_struct *wq;
+ struct delayed_work work;
+
+ struct hrtimer timer;
+ spinlock_t lock;
+ int timeout;
+ int max_timeout;
+
+ bool running;
+
+ u8 amplitude;
+
+ u8 ctrl0;
+ u8 ctrl1;
+ u8 ctrl2;
+ u8 ctrl4;
+ u8 pll;
+ u8 duty;
+ u8 period;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+
+static int amplitude_to_duty(int period, int amplitude)
+{
+ int duty = (period * (amplitude + AMPLITUDE_MAX)) /
+ (2 *(AMPLITUDE_MAX - AMPLITUDE_MIN));
+ return duty;
+}
+
+static int isa1200_vibrator_i2c_write(struct i2c_client *client,
+ u8 addr, u8 val)
+{
+ int error = 0;
+ error = i2c_smbus_write_byte_data(client, addr, val);
+ if (error)
+ printk(KERN_ERR "[VIB] Failed to write addr=[0x%x], val=[0x%x]\n",
+ addr, val);
+
+ return error;
+}
+
+static void isa1200_vibrator_hw_init(struct isa1200_vibrator_drvdata *vib)
+{
+ msleep(20);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_CONTROL_REG0, vib->ctrl0);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_CONTROL_REG1, vib->ctrl1);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_CONTROL_REG2, vib->ctrl2);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_PLL_REG, vib->pll);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_CONTROL_REG4, vib->ctrl4);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_PWM_DUTY_REG, vib->period/2);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_PWM_PERIOD_REG, vib->period);
+
+#ifdef MOTOR_DEBUG
+ printk(KERN_DEBUG "[VIB] ctrl0 = 0x%x\n", vib->ctrl0);
+ printk(KERN_DEBUG "[VIB] ctrl1 = 0x%x\n", vib->ctrl1);
+ printk(KERN_DEBUG "[VIB] ctrl2 = 0x%x\n", vib->ctrl2);
+ printk(KERN_DEBUG "[VIB] pll = 0x%x\n", vib->pll);
+ printk(KERN_DEBUG "[VIB] ctrl4 = 0x%x\n", vib->ctrl4);
+ printk(KERN_DEBUG "[VIB] duty = 0x%x\n", vib->period/2);
+ printk(KERN_DEBUG "[VIB] period = 0x%x\n", vib->period);
+#endif
+
+}
+
+static void isa1200_vibrator_on(struct isa1200_vibrator_drvdata *vib)
+{
+ int duty = vib->duty;
+
+ pr_debug("%s\n", __func__);
+
+ if (vib->duty >= vib->period) {
+ duty -= 3;
+ }
+
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_CONTROL_REG0, vib->ctrl0 | CTL0_NORMAL_OP);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_PWM_DUTY_REG, vib->duty);
+#ifdef MOTOR_DEBUG
+ printk(KERN_DEBUG "[VIB] ctrl0 = 0x%x\n", vib->ctrl0 | CTL0_NORMAL_OP);
+ printk(KERN_DEBUG "[VIB] duty = 0x%x\n", duty);
+#endif
+}
+
+static void isa1200_vibrator_off(struct isa1200_vibrator_drvdata *vib)
+{
+ pr_debug("%s\n", __func__);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_PWM_DUTY_REG, vib->period/2);
+ isa1200_vibrator_i2c_write(vib->client,
+ HAPTIC_CONTROL_REG0, vib->ctrl0);
+}
+
+static void isa1200_vibrator_work(struct work_struct *work)
+{
+ struct isa1200_vibrator_drvdata *vib =
+ container_of(to_delayed_work(work), struct isa1200_vibrator_drvdata, work);
+ struct i2c_client* client = vib->client;
+ int err;
+
+ pr_debug("%s\n", __func__);
+
+ if (vib->timeout == 0) {
+ if (!vib->running)
+ return;
+
+ vib->running = false;
+ isa1200_vibrator_off(vib);
+ clk_disable_unprepare(vib->vib_clk);
+
+ if (vib->pinctrl && vib->off_state) {
+ err = pinctrl_select_state(vib->pinctrl, vib->off_state);
+ if (err != 0)
+ dev_err(&client->dev,
+ "%s: error setting pinctrl off state. err=%d\n", __func__, err);
+ }
+
+ } else {
+ if (vib->running)
+ return;
+
+ vib->running = true;
+
+ if (vib->pinctrl && vib->on_state) {
+ err = pinctrl_select_state(vib->pinctrl, vib->on_state);
+ if (err != 0) {
+ dev_err(&client->dev,
+ "%s: error setting pinctrl on state. err=%d\n", __func__, err);
+ return;
+ }
+ }
+
+ clk_prepare_enable(vib->vib_clk);
+ mdelay(1);
+ isa1200_vibrator_on(vib);
+ }
+}
+
+static enum hrtimer_restart isa1200_vibrator_timer_func(struct hrtimer *_timer)
+{
+ struct isa1200_vibrator_drvdata *vib =
+ container_of(_timer, struct isa1200_vibrator_drvdata, timer);
+
+ vib->timeout = 0;
+
+ queue_delayed_work(vib->wq, &vib->work, 0);
+ return HRTIMER_NORESTART;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+
+static void isa1200_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ pr_info("%s: value=%d\n", __func__, value);
+
+ led_cdev->brightness = value;
+}
+
+static int isa1200_blink_set(struct led_classdev *cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ pr_info("%s\n", __func__);
+ return 0;
+}
+
+static ssize_t enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct isa1200_vibrator_drvdata *vib =
+ container_of(led_cdev, struct isa1200_vibrator_drvdata, cdev);
+ unsigned long flags;
+ int value;
+
+ sscanf(buf, "%d", &value);
+ pr_debug("%s timeout=%d\n", __func__, value);
+
+#ifdef MOTOR_DEBUG
+ printk(KERN_DEBUG "[VIB] time = %dms\n", value);
+#endif
+ cancel_delayed_work(&vib->work);
+ hrtimer_cancel(&vib->timer);
+ vib->timeout = value;
+ queue_delayed_work(vib->wq, &vib->work, 0);
+ spin_lock_irqsave(&vib->lock, flags);
+ if (value > 0) {
+ if (value > vib->max_timeout)
+ value = vib->max_timeout;
+
+ hrtimer_start(&vib->timer,
+ ns_to_ktime((u64)value * NSEC_PER_MSEC),
+ HRTIMER_MODE_REL);
+ }
+ spin_unlock_irqrestore(&vib->lock, flags);
+
+ return size;
+}
+
+static ssize_t amplitude_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct isa1200_vibrator_drvdata *vib =
+ container_of(led_cdev, struct isa1200_vibrator_drvdata, cdev);
+
+ return sprintf(buf, "%d\n", vib->amplitude);
+}
+
+static ssize_t amplitude_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct isa1200_vibrator_drvdata *vib =
+ container_of(led_cdev, struct isa1200_vibrator_drvdata, cdev);
+ int amplitude;
+
+ sscanf(buf, "%d", &amplitude);
+
+ if (amplitude > AMPLITUDE_MAX)
+ amplitude = AMPLITUDE_MAX;
+ else if (amplitude < AMPLITUDE_MIN)
+ amplitude = AMPLITUDE_MIN;
+
+ vib->duty = amplitude_to_duty(vib->period, amplitude);
+ vib->amplitude = amplitude;
+
+ pr_debug("%s: amplitude=%d duty_cycle=%d\n", __func__, amplitude, vib->duty);
+
+ return size;
+}
+
+
+static struct device_attribute isa1200_device_attrs[] = {
+ __ATTR(enable, S_IWUSR,
+ NULL,
+ enable_store),
+ __ATTR(amplitude, S_IRUGO | S_IWUSR,
+ amplitude_show,
+ amplitude_store),
+};
+
+static int isa1200_init_pinctrl(struct isa1200_vibrator_drvdata *ddata)
+{
+ struct i2c_client *client = ddata->client;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *on_state, *off_state;
+ int err = 0;
+
+ pinctrl = devm_pinctrl_get(&client->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_info(&client->dev,
+ "%s: not using pinctrl.\n", __func__);
+ return 0;
+ }
+
+ off_state = pinctrl_lookup_state(pinctrl, "off");
+ if (IS_ERR(off_state)) {
+ dev_err(&client->dev,
+ "%s: error getting pinctrl off state\n", __func__);
+ err = -ENODEV;
+ goto err;
+ }
+
+ on_state = pinctrl_lookup_state(pinctrl, "on");
+ if (IS_ERR(on_state)) {
+ dev_err(&client->dev,
+ "%s: error getting pinctrl on state\n", __func__);
+ err = -ENODEV;
+ goto err;
+ }
+
+ err = pinctrl_select_state(pinctrl, off_state);
+ if (err) {
+ dev_err(&client->dev,
+ "%s: error setting pinctrl off state. err=%d\n", __func__, err);
+ err = -ENODEV;
+ goto err;
+ }
+
+ ddata->pinctrl = pinctrl;
+ ddata->off_state = off_state;
+ ddata->on_state = on_state;
+
+ return 0;
+
+err:
+ devm_pinctrl_put(pinctrl);
+ return err;
+}
+
+#ifdef CONFIG_OF
+static int isa1200_parse_dt(struct i2c_client *client,
+ struct isa1200_vibrator_drvdata *drvdata)
+{
+ struct device_node *np = client->dev.of_node;
+ struct clk *vib_clk;
+ int val, error;
+
+ drvdata->enable_gpio = devm_gpiod_get_optional(&client->dev,
+ "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(drvdata->enable_gpio)) {
+ error = PTR_ERR(drvdata->enable_gpio);
+ dev_err(&client->dev, "Failed to get enable gpio: %d\n", error);
+ return error;
+ }
+
+ if (!of_property_read_u32(np, "max-timeout", &val))
+ drvdata->max_timeout = val;
+ if (!of_property_read_u32(np, "ctrl0", &val))
+ drvdata->ctrl0 = val;
+ if (!of_property_read_u32(np, "ctrl1", &val))
+ drvdata->ctrl1 = val;
+ if (!of_property_read_u32(np, "ctrl2", &val))
+ drvdata->ctrl2 = val;
+ if (!of_property_read_u32(np, "ctrl4", &val))
+ drvdata->ctrl4 = val;
+ if (!of_property_read_u32(np, "pll", &val))
+ drvdata->pll = val;
+ if (!of_property_read_u32(np, "duty", &val))
+ drvdata->duty = val;
+ if (!of_property_read_u32(np, "period", &val))
+ drvdata->period = val;
+
+ vib_clk = of_clk_get_by_name(np, "vibrator-clk");
+ if (vib_clk == NULL) {
+ pr_err("%s: error getting clk.\n", __func__);
+ return -ENODEV;
+ }
+ drvdata->vib_clk = vib_clk;
+
+ return 0;
+}
+#else
+static int isa1200_parse_dt(struct i2c_client *client,
+ struct isa1200_vibrator_drvdata *drvdata)
+{
+ return -EINVAL;
+}
+#endif
+
+static int isa1200_vibrator_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct isa1200_vibrator_platform_data *pdata = NULL;
+ struct isa1200_vibrator_drvdata *ddata;
+ int i, ret = 0;
+
+ printk(KERN_DEBUG "[VIB] %s\n", __func__);
+
+ ddata = kzalloc(sizeof(struct isa1200_vibrator_drvdata), GFP_KERNEL);
+ if (NULL == ddata) {
+ printk(KERN_ERR "[VIB] Failed to alloc memory\n");
+ ret = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ if (client->dev.platform_data) {
+ pdata = client->dev.platform_data;
+
+ ddata->enable_gpio = pdata->enable_gpio;
+ ddata->vib_clk = pdata->get_clk();
+ ddata->ctrl0 = pdata->ctrl0;
+ ddata->ctrl1 = pdata->ctrl1;
+ ddata->ctrl2 = pdata->ctrl2;
+ ddata->ctrl4 = pdata->ctrl4;
+ ddata->pll = pdata->pll;
+ ddata->duty = pdata->duty;
+ ddata->period = pdata->period;
+ } else if (client->dev.of_node) {
+ ret = isa1200_parse_dt(client, ddata);
+ if (ret) {
+ pr_err("%s: error parsing device tree\n", __func__);
+ goto err_free_mem;
+ }
+ }
+
+ ddata->client = client;
+
+ ddata->cdev.name = "isa1200";
+ ddata->cdev.flags = LED_CORE_SUSPENDRESUME;
+ ddata->cdev.brightness_set = isa1200_brightness_set;
+ ddata->cdev.blink_set = isa1200_blink_set;
+ ddata->cdev.default_trigger = "none";
+ i2c_set_clientdata(client, ddata);
+
+ ret = isa1200_init_pinctrl(ddata);
+ if (ret)
+ goto err_free_mem;
+
+ isa1200_vibrator_hw_init(ddata);
+
+
+ hrtimer_init(&ddata->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ddata->timer.function = isa1200_vibrator_timer_func;
+
+ ddata->wq = create_singlethread_workqueue("isa1200");
+ INIT_DELAYED_WORK(&ddata->work, isa1200_vibrator_work);
+
+ ret = led_classdev_register(&client->dev, &ddata->cdev);
+ if (ret < 0)
+ goto err_free_mem;
+
+ for (i = 0; i < ARRAY_SIZE(isa1200_device_attrs); i++) {
+ ret = device_create_file(ddata->cdev.dev, &isa1200_device_attrs[i]);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "%s: failed to create sysfs attributes\n", __func__);
+ goto err_free_mem;
+ }
+ }
+
+ return 0;
+
+err_free_mem:
+ kfree(ddata);
+ return ret;
+
+}
+
+static int isa1200_vibrator_i2c_remove(struct i2c_client *client)
+{
+ struct isa1200_vibrator_drvdata *ddata = i2c_get_clientdata(client);
+ struct led_classdev *led_cdev = &ddata->cdev;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(isa1200_device_attrs); i++) {
+ device_remove_file(led_cdev->dev, &isa1200_device_attrs[i]);
+ }
+
+ led_classdev_unregister(led_cdev);
+
+ flush_workqueue(ddata->wq);
+ destroy_workqueue(ddata->wq);
+ ddata->wq = NULL;
+
+ kfree(ddata);
+
+ return 0;
+}
+
+#if 0
+static int isa1200_vibrator_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isa1200_vibrator_drvdata *vib = i2c_get_clientdata(client);
+ gpio_direction_output(vib->gpio_en, 0);
+ return 0;
+}
+
+static int isa1200_vibrator_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isa1200_vibrator_drvdata *vib = i2c_get_clientdata(client);
+ // isa1200_vibrator_hw_init(ddata);
+ gpio_direction_output(vib->gpio_en, 1);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(isa1200_pm,
+ isa1200_vibrator_suspend, isa1200_vibrator_resume);
+#define ISA1200_PM &isa1200_pm
+#else
+#define ISA1200_PM NULL
+#endif
+
+static const struct i2c_device_id isa1200_vibrator_device_id[] = {
+ {"isa1200_vibrator", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, isa1200_vibrator_device_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id isa1200_dt_match[] = {
+ { .compatible = "samsung_p3,isa1200_vibrator" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, isa1200_dt_match);
+#endif
+
+static struct i2c_driver isa1200_vibrator_i2c_driver = {
+ .driver = {
+ .name = "isa1200_vibrator",
+ .pm = ISA1200_PM,
+ .of_match_table = of_match_ptr(isa1200_dt_match),
+ .owner = THIS_MODULE,
+ },
+ .probe = isa1200_vibrator_i2c_probe,
+ .remove = isa1200_vibrator_i2c_remove,
+ .id_table = isa1200_vibrator_device_id,
+};
+
+module_i2c_driver(isa1200_vibrator_i2c_driver);
diff --git a/drivers/leds/leds-isa1200.h b/drivers/leds/leds-isa1200.h
new file mode 100755
index 000000000000..50713449003c
--- /dev/null
+++ b/drivers/leds/leds-isa1200.h
@@ -0,0 +1,71 @@
+/* arch/arm/mach-tegra/sec_vibrator.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_SEC_VIBRATOR_H
+#define _LINUX_SEC_VIBRATOR_H
+
+#define HAPTIC_CONTROL_REG0 0x30
+#define HAPTIC_CONTROL_REG1 0x31
+#define HAPTIC_CONTROL_REG2 0x32
+#define HAPTIC_PLL_REG 0x33
+#define HAPTIC_CONTROL_REG4 0x34
+#define HAPTIC_PWM_DUTY_REG 0x35
+#define HAPTIC_PWM_PERIOD_REG 0x36
+#define HAPTIC_AMPLITUDE_REG 0x37
+
+/* HAPTIC_CONTROL_REG0 */
+#define CTL0_DIVIDER128 0
+#define CTL0_DIVIDER256 1
+#define CTL0_DIVIDER512 2
+#define CTL0_DIVIDER1024 3
+#define CTL0_13MHZ 1 << 2
+#define CTL0_PWM_INPUT 1 << 3
+#define CTL0_PWM_GEN 2 << 3
+#define CTL0_WAVE_GEN 3 << 3
+#define CTL0_HIGH_DRIVE 1 << 5
+#define CTL0_OVER_DR_EN 1 << 6
+#define CTL0_NORMAL_OP 1 << 7
+
+/* HAPTIC_CONTROL_REG1 */
+#define CTL1_HAPTICOFF_16U 0
+#define CTL1_HAPTICOFF_32U 1
+#define CTL1_HAPTICOFF_64U 2
+#define CTL1_HAPTICOFF_100U 3
+#define CTL1_HAPTICON_1U 1 << 2
+#define CTL1_SMART_EN 1 << 3
+#define CTL1_PLL_EN 1 << 4
+#define CTL1_ERM_TYPE 1 << 5
+#define CTL1_DEFAULT 1 << 6
+#define CTL1_EXT_CLOCK 1 << 7
+
+/* HAPTIC_CONTROL_REG2 */
+#define CTL2_EFFECT_EN 1
+#define CTL2_START_EFF_EN 1 << 2
+#define CTL2_SOFT_RESET_EN 1 << 7
+
+struct isa1200_vibrator_platform_data {
+ struct gpio_desc *enable_gpio;
+ int max_timeout;
+ u8 ctrl0;
+ u8 ctrl1;
+ u8 ctrl2;
+ u8 ctrl4;
+ u8 pll;
+ u8 duty;
+ u8 period;
+ struct clk *(*get_clk) (void);
+};
+
+#endif
--
2.20.1

View file

@ -0,0 +1,43 @@
From 0a1b842f3974f3ee69129e598747a17921810bfd Mon Sep 17 00:00:00 2001
From: ryang <decatf@gmail.com>
Date: Tue, 18 Sep 2018 12:38:03 -0400
Subject: [PATCH 08/34] iio: accel: kxcjk: Add device tree support
(cherry picked from commit 3fb788f94dcb55414ba774211e21c80153fd21f5)
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/iio/accel/kxcjk-1013.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index af53a1084ee5..3e13a837eb85 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -1504,13 +1504,23 @@ static const struct i2c_device_id kxcjk1013_id[] = {
{"SMO8500", KXCJ91008},
{}
};
-
MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
+static const struct of_device_id kxcjk1013_of_match[] = {
+ { .compatible = "kionix,kxcjk1013", },
+ { .compatible = "kionix,kxcj91008", },
+ { .compatible = "kionix,kxtj21009", },
+ { .compatible = "kionix,kxtf9", },
+ { .compatible = "kionix,SMO8500", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, kxcjk1013_of_match);
+
static struct i2c_driver kxcjk1013_driver = {
.driver = {
.name = KXCJK1013_DRV_NAME,
.acpi_match_table = ACPI_PTR(kx_acpi_match),
+ .of_match_table = of_match_ptr(kxcjk1013_of_match),
.pm = &kxcjk1013_pm_ops,
},
.probe = kxcjk1013_probe,
--
2.20.1

View file

@ -0,0 +1,225 @@
From 2822f8beddd7daa36a8d6251c675646256f8dcee Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sun, 27 Jan 2019 02:11:24 +0300
Subject: [PATCH 10/34] Input: stmpe-keypad - add STMPE1801 support
This chip variant differs from others - it has different register
map and swapped rows/columns.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/input/keyboard/stmpe-keypad.c | 108 ++++++++++++++++++++------
1 file changed, 85 insertions(+), 23 deletions(-)
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index d69e631cfa0a..1e2423a0a598 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -13,7 +13,7 @@
#include <linux/input/matrix_keypad.h>
#include <linux/mfd/stmpe.h>
-/* These are at the same addresses in all STMPE variants */
+/* These are at the same addresses in all STMPE variants, except 1801 */
#define STMPE_KPC_COL 0x60
#define STMPE_KPC_ROW_MSB 0x61
#define STMPE_KPC_ROW_LSB 0x62
@@ -42,14 +42,15 @@
#define STMPE_KEYPAD_MAX_DEBOUNCE 127
#define STMPE_KEYPAD_MAX_SCAN_COUNT 15
-#define STMPE_KEYPAD_MAX_ROWS 8
-#define STMPE_KEYPAD_MAX_COLS 8
+#define STMPE_KEYPAD_MAX_ROWS 10
+#define STMPE_KEYPAD_MAX_COLS 12
#define STMPE_KEYPAD_ROW_SHIFT 3
#define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
(STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
#define STMPE1601_NUM_DATA 5
+#define STMPE1801_NUM_DATA 5
#define STMPE2401_NUM_DATA 3
#define STMPE2403_NUM_DATA 5
@@ -67,6 +68,12 @@
* @max_rows: maximum number of rows supported
* @col_gpios: bitmask of gpios which can be used for columns
* @row_gpios: bitmask of gpios which can be used for rows
+ * @col_regs: registers for setting column pins
+ * @row_regs: registers for setting row pins
+ * @data_regs: registers for reading key data
+ * @ctrl_msb_reg: register for setting scan count
+ * @ctrl_lsb_reg: register for setting debounce time
+ * @cmd_reg: register for toggling scan mode
*/
struct stmpe_keypad_variant {
bool auto_increment;
@@ -77,6 +84,18 @@ struct stmpe_keypad_variant {
int max_rows;
unsigned int col_gpios;
unsigned int row_gpios;
+
+#define MAX_COL_REGS 3
+#define MAX_ROW_REGS 3
+#define MAX_DATA_REGS 5
+
+ u8 col_regs[MAX_COL_REGS];
+ u8 row_regs[MAX_ROW_REGS];
+ u8 data_regs[MAX_DATA_REGS];
+ u8 ctrl_msb_reg;
+ u8 ctrl_lsb_reg;
+ u8 cmd_reg;
+ bool read_inverted;
};
static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
@@ -88,6 +107,29 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
.max_rows = 8,
.col_gpios = 0x000ff, /* GPIO 0 - 7 */
.row_gpios = 0x0ff00, /* GPIO 8 - 15 */
+ .col_regs = { 0x60 },
+ .row_regs = { 0x62, 0x61 },
+ .data_regs = { 0x68, 0x69, 0x6a, 0x6b, 0x6c },
+ .ctrl_msb_reg = 0x63,
+ .ctrl_lsb_reg = 0x64,
+ .cmd_reg = 0x64,
+ .read_inverted = 0,
+ },
+ [STMPE1801] = {
+ .auto_increment = true,
+ .num_data = STMPE1801_NUM_DATA,
+ .num_normal_data = 3,
+ .max_cols = 10,
+ .max_rows = 8,
+ .col_gpios = 0x3ff00, /* GPIO 8 - 17 */
+ .row_gpios = 0x000ff, /* GPIO 0 - 7 */
+ .col_regs = { 0x31, 0x32 },
+ .row_regs = { 0x30 },
+ .data_regs = { 0x3a, 0x3b, 0x3c, 0x3d, 0x3e },
+ .ctrl_msb_reg = 0x33,
+ .ctrl_lsb_reg = 0x34,
+ .cmd_reg = 0x36,
+ .read_inverted = 1,
},
[STMPE2401] = {
.auto_increment = false,
@@ -98,6 +140,13 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
.max_rows = 12,
.col_gpios = 0x0000ff, /* GPIO 0 - 7*/
.row_gpios = 0x1f7f00, /* GPIO 8-14, 16-20 */
+ .col_regs = { 0x60 },
+ .row_regs = { 0x62, 0x61 },
+ .data_regs = { 0x68, 0x69, 0x6a, 0x6b, 0x6c },
+ .ctrl_msb_reg = 0x63,
+ .ctrl_lsb_reg = 0x64,
+ .cmd_reg = 0x64,
+ .read_inverted = 0,
},
[STMPE2403] = {
.auto_increment = true,
@@ -108,6 +157,13 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
.max_rows = 12,
.col_gpios = 0x0000ff, /* GPIO 0 - 7*/
.row_gpios = 0x1fef00, /* GPIO 8-14, 16-20 */
+ .col_regs = { 0x60 },
+ .row_regs = { 0x62, 0x61 },
+ .data_regs = { 0x68, 0x69, 0x6a, 0x6b, 0x6c },
+ .ctrl_msb_reg = 0x63,
+ .ctrl_lsb_reg = 0x64,
+ .cmd_reg = 0x64,
+ .read_inverted = 0,
},
};
@@ -145,11 +201,11 @@ static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data)
int i;
if (variant->auto_increment)
- return stmpe_block_read(stmpe, STMPE_KPC_DATA_BYTE0,
+ return stmpe_block_read(stmpe, variant->data_regs[0],
variant->num_data, data);
for (i = 0; i < variant->num_data; i++) {
- ret = stmpe_reg_read(stmpe, STMPE_KPC_DATA_BYTE0 + i);
+ ret = stmpe_reg_read(stmpe, variant->data_regs[i]);
if (ret < 0)
return ret;
@@ -176,7 +232,9 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
u8 data = fifo[i];
int row = (data & STMPE_KPC_DATA_ROW) >> 3;
int col = data & STMPE_KPC_DATA_COL;
- int code = MATRIX_SCAN_CODE(row, col, STMPE_KEYPAD_ROW_SHIFT);
+ int code = variant->read_inverted ?
+ MATRIX_SCAN_CODE(col, row, STMPE_KEYPAD_ROW_SHIFT):
+ MATRIX_SCAN_CODE(row, col, STMPE_KEYPAD_ROW_SHIFT);
bool up = data & STMPE_KPC_DATA_UP;
if ((data & STMPE_KPC_DATA_NOKEY_MASK)
@@ -265,7 +323,7 @@ static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
{
const struct stmpe_keypad_variant *variant = keypad->variant;
struct stmpe *stmpe = keypad->stmpe;
- int ret;
+ int ret, val, i;
if (keypad->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE)
return -EINVAL;
@@ -281,33 +339,37 @@ static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
if (ret < 0)
return ret;
- ret = stmpe_reg_write(stmpe, STMPE_KPC_COL, keypad->cols);
- if (ret < 0)
- return ret;
-
- ret = stmpe_reg_write(stmpe, STMPE_KPC_ROW_LSB, keypad->rows);
- if (ret < 0)
- return ret;
+ val = keypad->cols;
+ i = 0;
+ do {
+ ret = stmpe_reg_write(stmpe, variant->col_regs[i++], val & 0xff);
+ if (ret < 0)
+ return ret;
+ } while ((val >>= 8) != 0);
- if (variant->max_rows > 8) {
- ret = stmpe_set_bits(stmpe, STMPE_KPC_ROW_MSB,
- STMPE_KPC_ROW_MSB_ROWS,
- keypad->rows >> 8);
+ val = keypad->rows;
+ i = 0;
+ do {
+ ret = stmpe_reg_write(stmpe, variant->row_regs[i++], val & 0xff);
if (ret < 0)
return ret;
- }
+ } while ((val >>= 8) != 0);
- ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB,
+ ret = stmpe_set_bits(stmpe, variant->ctrl_msb_reg,
STMPE_KPC_CTRL_MSB_SCAN_COUNT,
keypad->scan_count << 4);
if (ret < 0)
return ret;
- return stmpe_set_bits(stmpe, STMPE_KPC_CTRL_LSB,
- STMPE_KPC_CTRL_LSB_SCAN |
+ ret = stmpe_set_bits(stmpe, variant->ctrl_lsb_reg,
STMPE_KPC_CTRL_LSB_DEBOUNCE,
- STMPE_KPC_CTRL_LSB_SCAN |
(keypad->debounce_ms << 1));
+ if (ret < 0)
+ return ret;
+
+ return stmpe_set_bits(stmpe, variant->cmd_reg,
+ STMPE_KPC_CTRL_LSB_SCAN,
+ STMPE_KPC_CTRL_LSB_SCAN);
}
static void stmpe_keypad_fill_used_pins(struct stmpe_keypad *keypad,
--
2.20.1

View file

@ -0,0 +1,520 @@
From 0dd90d3d51bed50ce9753c06659f72c94536eeb7 Mon Sep 17 00:00:00 2001
From: ryang <decatf@gmail.com>
Date: Sat, 21 Apr 2018 09:33:37 -0400
Subject: [PATCH 11/34] Add tegra_wm8994 driver
(cherry picked from commit d58c0084b16491251b3871bfacbc070105eb9356)
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
sound/soc/tegra/Kconfig | 14 +
sound/soc/tegra/Makefile | 2 +
sound/soc/tegra/tegra_wm8994.c | 452 +++++++++++++++++++++++++++++++++
3 files changed, 468 insertions(+)
create mode 100755 sound/soc/tegra/tegra_wm8994.c
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 6875fc39a575..a95c7feee491 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -86,6 +86,20 @@ config SND_SOC_TEGRA_WM8903
boards using the WM8093 codec. Currently, the supported boards are
Harmony, Ventana, Seaboard, Kaen, and Aebl.
+config SND_SOC_TEGRA_WM8994
+ tristate "SoC Audio support for Tegra boards using a WM8994 codec"
+ depends on SND_SOC_TEGRA && I2C
+ select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
+ select SND_SOC_TEGRA20_SPDIF if ARCH_TEGRA_2x_SOC
+ select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
+ select SND_SOC_SPDIF
+ select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
+ help
+ Say Y or M here if you want to add support for SoC audio on Tegra
+ boards using the WM8994 codec. Currently, the supported boards are
+ Samsung P3.
+
config SND_SOC_TEGRA_WM9712
tristate "SoC Audio support for Tegra boards using a WM9712 codec"
depends on SND_SOC_TEGRA && GPIOLIB
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 2329b72c93e3..09d0b47db5af 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -23,6 +23,7 @@ snd-soc-tegra-rt5640-objs := tegra_rt5640.o
snd-soc-tegra-rt5677-objs := tegra_rt5677.o
snd-soc-tegra-wm8753-objs := tegra_wm8753.o
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
+snd-soc-tegra-wm8994-objs := tegra_wm8994.o
snd-soc-tegra-wm9712-objs := tegra_wm9712.o
snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-alc5632-objs := tegra_alc5632.o
@@ -33,6 +34,7 @@ obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
+obj-$(CONFIG_SND_SOC_TEGRA_WM8994) += snd-soc-tegra-wm8994.o
obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_wm8994.c b/sound/soc/tegra/tegra_wm8994.c
new file mode 100755
index 000000000000..bf928d7f4813
--- /dev/null
+++ b/sound/soc/tegra/tegra_wm8994.c
@@ -0,0 +1,452 @@
+/*
+ * tegra_wm8994.c - Tegra machine ASoC driver for boards using WM8994 codec.
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010-2011 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <asm/mach-types.h>
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_pcm.h"
+#include "tegra_asoc_utils.h"
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+#include "tegra20_das.h"
+#endif
+
+#define DRV_NAME "tegra-snd-wm8994"
+
+struct tegra_wm8994 {
+ struct tegra_asoc_utils_data util_data;
+};
+
+static int tegra_wm8994_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct tegra_wm8994 *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk, i2s_daifmt;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 64000:
+ case 88200:
+ case 96000:
+ mclk = 128 * srate;
+ break;
+ default:
+ mclk = 256 * srate;
+ break;
+ }
+ /* FIXME: Codec only requires >= 3MHz if OSR==0 */
+ while (mclk < 6000000)
+ mclk *= 2;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ /* Use DSP mode for mono on Tegra20 */
+ // if ((params_channels(params) != 2) &&
+ // (machine_is_ventana() || machine_is_harmony() ||
+ // machine_is_kaen() || machine_is_aebl()))
+ // i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ // else
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai fmt not set\n");
+ return err;
+ }
+
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
+ if (err < 0) {
+ dev_err(card->dev, "cpu_dai fmt not set\n");
+ return err;
+ }
+ /* Need to check clk id */
+ err = snd_soc_dai_set_sysclk(codec_dai, 1, mclk,
+ SND_SOC_CLOCK_IN);
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai clock not set\n");
+ return err;
+ }
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
+ TEGRA20_DAS_DAP_ID_1);
+ if (err < 0) {
+ dev_err(card->dev, "failed to set dap-dac path\n");
+ return err;
+ }
+
+ err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
+ TEGRA20_DAS_DAP_SEL_DAC1);
+ if (err < 0) {
+ dev_err(card->dev, "failed to set dac-dap path\n");
+ return err;
+ }
+#endif
+ return 0;
+}
+
+static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *card = rtd->card;
+ struct tegra_wm8994 *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk, min_mclk;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ mclk = 12288000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ min_mclk = 64 * srate;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % min_mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ err = snd_soc_dai_set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (err < 0) {
+ dev_err(card->dev, "cpu_dai fmt not set\n");
+ return err;
+ }
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
+ TEGRA20_DAS_DAP_ID_4);
+ if (err < 0) {
+ dev_err(card->dev, "failed to set dac-dap path\n");
+ return err;
+ }
+
+ err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
+ TEGRA20_DAS_DAP_SEL_DAC2);
+ if (err < 0) {
+ dev_err(card->dev, "failed to set dac-dap path\n");
+ return err;
+ }
+#endif
+ return 0;
+}
+
+static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct tegra_wm8994 *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk, min_mclk;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ mclk = 12288000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ min_mclk = 128 * srate;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % min_mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int tegra_hw_free(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static struct snd_soc_ops tegra_wm8994_ops = {
+ .hw_params = tegra_wm8994_hw_params,
+ .hw_free = tegra_hw_free,
+};
+
+static int tegra_wm8994_init(struct snd_soc_pcm_runtime *rtd)
+{
+ pr_info("%s\n", __func__);
+ return 0;
+}
+
+static int tegra_wm8994_remove(struct snd_soc_card *card)
+{
+ pr_info("%s\n", __func__);
+ return 0;
+}
+
+static struct snd_soc_dai_link tegra_wm8994_dai[] = {
+ {
+ .name = "WM8994",
+ .stream_name = "WM8994 PCM",
+ .codec_dai_name = "wm8994-aif1",
+ .init = tegra_wm8994_init,
+
+ // .codec_name = "WM8994 I2C Codec.8-001b",
+ // .platform_name = "tegra-pcm-audio",
+ // .cpu_dai_name = "tegra20-i2s.0",
+ // .codec_dai_name = "WM8994 PAIFRX",
+ .ops = &tegra_wm8994_ops,
+ },
+/*
+ {
+ .name = "SPDIF",
+ .stream_name = "SPDIF PCM",
+ .codec_name = "spdif-dit.0",
+ .platform_name = "tegra-pcm-audio",
+ .cpu_dai_name = "tegra20-spdif",
+ .codec_dai_name = "dit-hifi",
+ .ops = &tegra_spdif_ops,
+ },
+*/
+/*
+ {
+ .name = "BT-SCO",
+ .stream_name = "BT SCO PCM",
+ .codec_name = "spdif-dit.1",
+ .platform_name = "tegra-pcm-audio",
+ .cpu_dai_name = "tegra20-i2s.1",
+ .codec_dai_name = "dit-hifi",
+ .ops = &tegra_wm8994_bt_sco_ops,
+ },
+*/
+};
+
+static struct snd_soc_card snd_soc_tegra_wm8994 = {
+ .name = "tegra-wm8994",
+ .dai_link = tegra_wm8994_dai,
+ .num_links = ARRAY_SIZE(tegra_wm8994_dai),
+ .remove = tegra_wm8994_remove,
+};
+
+static int tegra_wm8994_driver_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct snd_soc_card *card = &snd_soc_tegra_wm8994;
+ struct tegra_wm8994 *machine;
+ int ret;
+
+ pr_info("%s\n", __func__);
+
+ if (!pdev->dev.platform_data && !pdev->dev.of_node) {
+ dev_err(&pdev->dev, "No platform data supplied\n");
+ return -EINVAL;
+ }
+
+ machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8994),
+ GFP_KERNEL);
+ if (!machine) {
+ dev_err(&pdev->dev, "Can't allocate tegra_wm8994 struct\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, machine);
+
+ // Parse device tree nodes
+
+ // ...
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto err;
+
+
+ tegra_wm8994_dai[0].codec_of_node = of_parse_phandle(np,
+ "nvidia,audio-codec", 0);
+ if (!tegra_wm8994_dai[0].codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8994_dai[0].cpu_of_node = of_parse_phandle(np,
+ "nvidia,i2s-controller", 0);
+ if (!tegra_wm8994_dai[0].cpu_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8994_dai[0].platform_of_node = tegra_wm8994_dai[0].cpu_of_node;
+/*
+ tegra_wm8994_dai[1].codec_of_node = of_parse_phandle(np,
+ "nvidia,spdif-codec", 0);
+ if (!tegra_wm8994_dai[1].codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,spdif-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8994_dai[1].cpu_of_node = of_parse_phandle(np,
+ "nvidia,spdif-controller", 0);
+ if (!tegra_wm8994_dai[1].cpu_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,spdif-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8994_dai[1].platform_of_node = tegra_wm8994_dai[1].cpu_of_node;
+*/
+
+ ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_init failed (%d)\n",
+ ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ pr_info("%s: probed\n", __func__);
+
+
+ return 0;
+
+err_fini_utils:
+ tegra_asoc_utils_fini(&machine->util_data);
+err:
+ return ret;
+}
+
+static int tegra_wm8994_driver_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct tegra_wm8994 *machine = snd_soc_card_get_drvdata(card);
+ snd_soc_unregister_card(card);
+
+ tegra_asoc_utils_fini(&machine->util_data);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_wm8994_of_match[] = {
+ { .compatible = "nvidia,tegra-audio-wm8994", },
+ {},
+};
+
+static struct platform_driver tegra_wm8994_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_wm8994_of_match,
+ },
+ .probe = tegra_wm8994_driver_probe,
+ .remove = tegra_wm8994_driver_remove,
+};
+
+module_platform_driver(tegra_wm8994_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra+WM8994 machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_wm8994_of_match);
--
2.20.1

View file

@ -0,0 +1,27 @@
From aa3924de19ea515a7aa3309da9e779303f73d43e Mon Sep 17 00:00:00 2001
From: ryang <decatf@gmail.com>
Date: Sat, 26 May 2018 13:14:21 -0400
Subject: [PATCH 12/34] HACK: Fix wm8994 Kconfig
(cherry picked from commit 2bca457e1d53d6312afd21c902f55f768ef75a2e)
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
sound/soc/codecs/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 9cc4f1848c9b..7bc76e5ebb82 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1255,7 +1255,7 @@ config SND_SOC_WM8993
tristate
config SND_SOC_WM8994
- tristate
+ tristate "Wolfson Microelectronics WM8994 codec driver"
config SND_SOC_WM8995
tristate
--
2.20.1

View file

@ -0,0 +1,211 @@
From 392be1c5347b89a0c353e861a1222f925fe5b8a5 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Mon, 28 Jan 2019 11:35:06 +0300
Subject: [PATCH 13/34] ASoC: tegra_wm8994: cleanup
Remove unnecessary functions. Also, S/PDIF support
is not needed.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
sound/soc/tegra/Kconfig | 3 -
sound/soc/tegra/tegra_wm8994.c | 155 ---------------------------------
2 files changed, 158 deletions(-)
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index a95c7feee491..99be3ef82d85 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -91,9 +91,6 @@ config SND_SOC_TEGRA_WM8994
depends on SND_SOC_TEGRA && I2C
select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
- select SND_SOC_TEGRA20_SPDIF if ARCH_TEGRA_2x_SOC
- select SND_SOC_TEGRA30_SPDIF if ARCH_TEGRA_3x_SOC
- select SND_SOC_SPDIF
select SND_SOC_TEGRA30_DAM if ARCH_TEGRA_3x_SOC
help
Say Y or M here if you want to add support for SoC audio on Tegra
diff --git a/sound/soc/tegra/tegra_wm8994.c b/sound/soc/tegra/tegra_wm8994.c
index bf928d7f4813..87cb36df3bcf 100755
--- a/sound/soc/tegra/tegra_wm8994.c
+++ b/sound/soc/tegra/tegra_wm8994.c
@@ -138,117 +138,6 @@ static int tegra_wm8994_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_card *card = rtd->card;
- struct tegra_wm8994 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
- int err;
-
- srate = params_rate(params);
- switch (srate) {
- case 11025:
- case 22050:
- case 44100:
- case 88200:
- mclk = 11289600;
- break;
- case 8000:
- case 16000:
- case 32000:
- case 48000:
- case 64000:
- case 96000:
- mclk = 12288000;
- break;
- default:
- return -EINVAL;
- }
- min_mclk = 64 * srate;
-
- err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
- if (err < 0) {
- if (!(machine->util_data.set_mclk % min_mclk))
- mclk = machine->util_data.set_mclk;
- else {
- dev_err(card->dev, "Can't configure clocks\n");
- return err;
- }
- }
-
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err < 0) {
- dev_err(card->dev, "cpu_dai fmt not set\n");
- return err;
- }
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
- TEGRA20_DAS_DAP_ID_4);
- if (err < 0) {
- dev_err(card->dev, "failed to set dac-dap path\n");
- return err;
- }
-
- err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
- TEGRA20_DAS_DAP_SEL_DAC2);
- if (err < 0) {
- dev_err(card->dev, "failed to set dac-dap path\n");
- return err;
- }
-#endif
- return 0;
-}
-
-static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct tegra_wm8994 *machine = snd_soc_card_get_drvdata(card);
- int srate, mclk, min_mclk;
- int err;
-
- srate = params_rate(params);
- switch (srate) {
- case 11025:
- case 22050:
- case 44100:
- case 88200:
- mclk = 11289600;
- break;
- case 8000:
- case 16000:
- case 32000:
- case 48000:
- case 64000:
- case 96000:
- mclk = 12288000;
- break;
- default:
- return -EINVAL;
- }
- min_mclk = 128 * srate;
-
- err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
- if (err < 0) {
- if (!(machine->util_data.set_mclk % min_mclk))
- mclk = machine->util_data.set_mclk;
- else {
- dev_err(card->dev, "Can't configure clocks\n");
- return err;
- }
- }
-
- return 0;
-}
-
static int tegra_hw_free(struct snd_pcm_substream *substream)
{
return 0;
@@ -284,28 +173,6 @@ static struct snd_soc_dai_link tegra_wm8994_dai[] = {
// .codec_dai_name = "WM8994 PAIFRX",
.ops = &tegra_wm8994_ops,
},
-/*
- {
- .name = "SPDIF",
- .stream_name = "SPDIF PCM",
- .codec_name = "spdif-dit.0",
- .platform_name = "tegra-pcm-audio",
- .cpu_dai_name = "tegra20-spdif",
- .codec_dai_name = "dit-hifi",
- .ops = &tegra_spdif_ops,
- },
-*/
-/*
- {
- .name = "BT-SCO",
- .stream_name = "BT SCO PCM",
- .codec_name = "spdif-dit.1",
- .platform_name = "tegra-pcm-audio",
- .cpu_dai_name = "tegra20-i2s.1",
- .codec_dai_name = "dit-hifi",
- .ops = &tegra_wm8994_bt_sco_ops,
- },
-*/
};
static struct snd_soc_card snd_soc_tegra_wm8994 = {
@@ -369,28 +236,6 @@ static int tegra_wm8994_driver_probe(struct platform_device *pdev)
}
tegra_wm8994_dai[0].platform_of_node = tegra_wm8994_dai[0].cpu_of_node;
-/*
- tegra_wm8994_dai[1].codec_of_node = of_parse_phandle(np,
- "nvidia,spdif-codec", 0);
- if (!tegra_wm8994_dai[1].codec_of_node) {
- dev_err(&pdev->dev,
- "Property 'nvidia,spdif-codec' missing or invalid\n");
- ret = -EINVAL;
- goto err;
- }
-
- tegra_wm8994_dai[1].cpu_of_node = of_parse_phandle(np,
- "nvidia,spdif-controller", 0);
- if (!tegra_wm8994_dai[1].cpu_of_node) {
- dev_err(&pdev->dev,
- "Property 'nvidia,spdif-controller' missing or invalid\n");
- ret = -EINVAL;
- goto err;
- }
-
- tegra_wm8994_dai[1].platform_of_node = tegra_wm8994_dai[1].cpu_of_node;
-*/
-
ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "tegra_asoc_utils_init failed (%d)\n",
--
2.20.1

View file

@ -0,0 +1,141 @@
From de104acc782c9bfd4a71f32f91e6a2a059873cdd Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Mon, 28 Jan 2019 11:38:19 +0300
Subject: [PATCH 14/34] ARM: dts: tegra20-glide: Device Tree changes
- added wm8994 tegra binding
- vmmc regulator
- STMPE GPIO for card and jack detection (doesn't work)
- remove pwm backlight node
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 53 +++++++++++++++++------------
1 file changed, 32 insertions(+), 21 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 32f59e7889be..f9dfb7ec3a3e 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -732,11 +732,10 @@
regulator-always-on;
};
- ldo16 {
+ vmmc_reg: ldo16 {
regulator-name = "nvvdd_ldo16,vtf_3v3,vmmc";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- regulator-always-on;
};
ldo17 {
@@ -846,12 +845,15 @@
#address-cells = <1>;
#size-cells = <0>;
- wm8994@1a {
+ wm8994: wm8994@1a {
compatible = "wlf,wm8994";
reg = <0x1a>;
gpio-controller;
#gpio-cells = <2>;
+
+ wlf,ldo1ena = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_HIGH>;
+
};
};
@@ -1029,14 +1031,14 @@
MATRIX_KEY(0, 0, KEY_R)
MATRIX_KEY(0, 1, KEY_G)
MATRIX_KEY(0, 2, KEY_V)
- MATRIX_KEY(0, 3, KEY_LEFTMETA)
+ MATRIX_KEY(0, 3, KEY_LEFTCTRL /* KEY_LEFTMETA */)
MATRIX_KEY(0, 4, KEY_MENU)
MATRIX_KEY(0, 5, KEY_HOME)
MATRIX_KEY(1, 0, KEY_T)
MATRIX_KEY(1, 1, KEY_H)
MATRIX_KEY(1, 2, KEY_B)
- MATRIX_KEY(1, 3, KEY_RIGHTMETA)
+ MATRIX_KEY(1, 3, KEY_TAB /* KEY_RIGHTMETA */)
MATRIX_KEY(1, 4, KEY_Q)
MATRIX_KEY(1, 5, KEY_FN)
@@ -1074,13 +1076,19 @@
MATRIX_KEY(6, 3, KEY_DOWN)
MATRIX_KEY(6, 4, KEY_D)
- MATRIX_KEY(7, 0, KEY_DELETE)
+ MATRIX_KEY(7, 0, KEY_BACKSPACE /* KEY_DELETE */)
MATRIX_KEY(7, 1, KEY_BACK)
MATRIX_KEY(7, 2, KEY_SEARCH)
- MATRIX_KEY(7, 3, KEY_WWW)
+ MATRIX_KEY(7, 3, KEY_SLASH /* KEY_WWW */)
MATRIX_KEY(7, 4, KEY_F)
MATRIX_KEY(7, 5, KEY_FN) >;
};
+
+ stmpegpio: stmpe_gpio {
+ compatible = "st,stmpe-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
};
@@ -1151,7 +1159,10 @@
sdhci@c8000400 {
status = "okay";
bus-width = <4>;
- cd-gpios = <&gpio TEGRA_GPIO(V, 6) GPIO_ACTIVE_LOW>;
+ // cd-gpios = <&stmpegpio 16 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio TEGRA_GPIO(V, 6) GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&vmmc_reg>;
+ broken-cd;
keep-power-in-suspend;
};
@@ -1163,19 +1174,6 @@
keep-power-in-suspend;
};
- // This is supposed to be vibra, but it operates on a controller, which is not supported
- /* backlight: backlight {
- compatible = "pwm-backlight";
-
- enable-gpios = <&gpio TEGRA_GPIO(U, 4) GPIO_ACTIVE_HIGH>;
- pwms = <&pwm 0 5000000>;
-
- brightness-levels = <0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 255>;
- default-brightness-level = <10>;
-
- backlight-boot-off;
- }; */
-
clocks {
compatible = "simple-bus";
#address-cells = <1>;
@@ -1288,4 +1286,17 @@
enable-active-high;
};
};
+
+ sound {
+ compatible = "nvidia,tegra-audio-wm8994";
+ nvidia,model = "wm8994-aif1";
+
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&wm8994>;
+
+ clocks = <&tegra_car TEGRA20_CLK_PLL_A>,
+ <&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
+ <&tegra_car TEGRA20_CLK_CDEV1>;
+ clock-names = "pll_a", "pll_a_out0", "mclk";
+ };
};
--
2.20.1

View file

@ -0,0 +1,29 @@
From 73e3de92fdc2804a98b13de917dc218b065d3619 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Thu, 7 Feb 2019 13:21:15 +0300
Subject: [PATCH 15/34] ARM: dts: tegra20-glide: add memory node address
This fixes dts warning and avoids conflict with 'memory' node in
tegra20.dtsi
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index f9dfb7ec3a3e..ddadfd998493 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -56,7 +56,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@0 {
device_type = "memory";
reg = <0x00000000 0x40000000>;
};
--
2.20.1

View file

@ -0,0 +1,54 @@
From 0e7b869a461dc005c786b97ab9d6a8b3718d8ae5 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Thu, 7 Feb 2019 13:26:02 +0300
Subject: [PATCH 16/34] ARM: dts: tegra20-glide: comment out MHL
HDMI and MHL enabled makes screen size incorrectly set to 1024x800
instead of 480x800
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index ddadfd998493..46e4d30b077a 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -81,7 +81,7 @@
nvidia,panel = <&panel>;
};
};
-
+#if 0
hdmi@54280000 {
status = "okay";
@@ -98,6 +98,7 @@
};
};
};
+#endif
};
pinmux@70000014 {
@@ -905,7 +906,7 @@
i2c-gpio,delay-us = <5>;
#address-cells = <1>;
#size-cells = <0>;
-
+#if 0
sii9234@39 {
compatible = "sil,sii9234";
reg = <0x39>;
@@ -923,6 +924,7 @@
};
};
};
+#endif
};
i2c@15 {
--
2.20.1

View file

@ -0,0 +1,28 @@
From 21dec175043642df78f0cba6322cdf714fafdd9d Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Thu, 7 Feb 2019 13:30:45 +0300
Subject: [PATCH 17/34] ARM: dts: tegra20-glide: fix duplicate i2c bus address
Camera and power i2c buses use separate addresses for operation.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 46e4d30b077a..93a4f50f0710 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -552,7 +552,7 @@
};
};
- i2c@7000d000 {
+ i2c@7000c500 {
status = "okay";
clock-frequency = <400000>;
--
2.20.1

View file

@ -0,0 +1,59 @@
From 1ae43bfcc1b331d1585714d7571539d609507638 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Thu, 7 Feb 2019 13:33:31 +0300
Subject: [PATCH 18/34] ARM: dts: tegra20-glide: fix USB gadget mode
This commit makes USB gadget mode working by changing mode from
OTG to peripherial and specifying vbus regulator.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 93a4f50f0710..c582512936a6 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -655,7 +655,7 @@
regulator-max-microvolt = <1800000>;
};
- ldo4 {
+ vbus1_reg: ldo4 {
regulator-name = "nvvdd_ldo4,vap_usb_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
@@ -1107,18 +1107,18 @@
nvidia,lp0-vec = <0x1819E000 8192>;
};
- // Enabling this makes device to hang at boot
-#if 0
usb@c5000000 {
compatible = "nvidia,tegra20-udc";
status = "okay";
- dr_mode = "otg";
+ dr_mode = "peripheral"; // otg
};
usb-phy@c5000000 {
status = "okay";
+ vbus-supply = <&vbus1_reg>;
};
+#if 0
usb@c5004000 {
status = "okay";
};
@@ -1127,6 +1127,7 @@
status = "okay";
};
#endif
+
wifi_pwrseq: bcm4330_pwrseq {
compatible = "mmc-pwrseq-simple";
clocks = <&tegra_car TEGRA20_CLK_BLINK>;
--
2.20.1

View file

@ -0,0 +1,43 @@
From 17a78313603f9da233307ccaf178c1fa6689de99 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Thu, 7 Feb 2019 13:37:04 +0300
Subject: [PATCH 19/34] ARM: dts: tegra20-glide: change display timings
Fix the image being shifted upwards and make refresh rate a bit faster
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index c582512936a6..76493614f6df 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -1237,18 +1237,18 @@
display-timings {
timing {
- clock-frequency = <24000000>;
+ clock-frequency = <25000000>;
hactive = <480>;
vactive = <800>;
hfront-porch = <16>;
- vfront-porch = <28>;
- hback-porch = <14>;
- vback-porch = <1>;
+ vfront-porch = <27>; // 28
+ hback-porch = <16>;
+ vback-porch = <2>; // 1
hsync-len = <2>;
vsync-len = <2>;
hsync-active = <0>;
vsync-active = <0>;
- nvidia,h-ref-to-sync = <0>;
+ nvidia,h-ref-to-sync = <1>; // 0
nvidia,v-ref-to-sync = <1>;
};
};
--
2.20.1

View file

@ -0,0 +1,29 @@
From faf3aeb5d29682133c26da878f33a340cda6b90d Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 9 Feb 2019 18:30:12 +0300
Subject: [PATCH 20/34] ARM: dts: tegra20-glide: add intrrupt binding for
charger
Add missing interrupt for max17043 charger
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 76493614f6df..cb219d1b1198 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -819,6 +819,8 @@
max17043@36 {
compatible = "maxim,max17040";
reg = <0x36>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(I, 5) IRQ_TYPE_LEVEL_HIGH>;
};
};
--
2.20.1

View file

@ -0,0 +1,29 @@
From dc2429062dd7e527b96cd03e5d2ca310df64e5c5 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 9 Feb 2019 18:35:00 +0300
Subject: [PATCH 21/34] drm/panel: s6e63m0: disable rotation
Low part of GTCON register is responsible for flipping/rotation.
This commit disables default rotation by 180 degrees.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
index 4312aa3e4386..dbd57239359e 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -200,7 +200,7 @@ static void s6e63m0_init(struct s6e63m0 *ctx)
s6e63m0_dcs_write_seq_static(ctx, MCS_DISPLAY_CONDITION,
0x02, 0x03, 0x1c, 0x10, 0x10);
s6e63m0_dcs_write_seq_static(ctx, 0xf7,
- 0x03, 0x00, 0x00);
+ 0x00, 0x00, 0x00);
s6e63m0_dcs_write_seq_static(ctx, MCS_GAMMA_CTRL,
0x00, 0x18, 0x08, 0x24, 0x64, 0x56, 0x33,
--
2.20.1

View file

@ -0,0 +1,29 @@
From aa393adbba669ab25251d241672ef9f418a85e8c Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 9 Feb 2019 18:44:17 +0300
Subject: [PATCH 22/34] ARM: dts: tegra20-glide: set panel reset GPIO pin to
active low
This fixes display not working with new S6E63M0 panel driver.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index cb219d1b1198..87d737c62b0a 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -1230,7 +1230,7 @@
spi-cpha;
vdd3-supply = <&vlcd_1v8>;
vci-supply = <&vlcd_3v0>;
- reset-gpios = <&gpio TEGRA_GPIO(C, 1) GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio TEGRA_GPIO(C, 1) GPIO_ACTIVE_LOW>;
panel-width-mm = <52>;
panel-height-mm = <87>;
/* 25 + 1 for regulator */
--
2.20.1

View file

@ -0,0 +1,30 @@
From bac8eb35a16b6a0bc0969dc7d3fa862159519672 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 9 Feb 2019 18:47:19 +0300
Subject: [PATCH 23/34] power: supply: max17040: Fix voltage reporting
VCELL register on max17040 reports voltage in 1.25mV steps
in top-12 bits. Fix volate reporting by taking this
into account.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/power/supply/max17040_battery.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c
index 91cafc7bed30..de5e791e0055 100644
--- a/drivers/power/supply/max17040_battery.c
+++ b/drivers/power/supply/max17040_battery.c
@@ -105,7 +105,7 @@ static void max17040_get_vcell(struct i2c_client *client)
vcell = max17040_read_reg(client, MAX17040_VCELL);
- chip->vcell = vcell;
+ chip->vcell = (vcell >> 4) * 1250;
}
static void max17040_get_soc(struct i2c_client *client)
--
2.20.1

View file

@ -0,0 +1,27 @@
From eab2e34a6db401c7477f3084fca8152155bebd8c Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 9 Feb 2019 19:00:23 +0300
Subject: [PATCH 24/34] power: supply: max17040: Set initial RCOMP value
This should fix incorrect capacity reporting.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/power/supply/max17040_battery.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c
index de5e791e0055..dd75c8045ff1 100644
--- a/drivers/power/supply/max17040_battery.c
+++ b/drivers/power/supply/max17040_battery.c
@@ -219,6 +219,7 @@ static int max17040_probe(struct i2c_client *client,
max17040_reset(client);
max17040_get_version(client);
+ max17040_write_reg(client, MAX17040_RCOMP, 0xff00);
INIT_DEFERRABLE_WORK(&chip->work, max17040_work);
queue_delayed_work(system_power_efficient_wq, &chip->work,
--
2.20.1

View file

@ -0,0 +1,33 @@
From 191217e9006ab051cd2f18accc02582737fe0a38 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sat, 9 Feb 2019 20:13:26 +0300
Subject: [PATCH 25/34] drm/panel: s6e63m0: Increase back porch
Original timings cause issues on Tegra hardware - image is
shifted and colors are wrong.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
index dbd57239359e..b77e3a774291 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -112,9 +112,9 @@ static const struct drm_display_mode default_mode = {
.hsync_end = 480 + 16 + 2,
.htotal = 480 + 16 + 2 + 16,
.vdisplay = 800,
- .vsync_start = 800 + 28,
- .vsync_end = 800 + 28 + 2,
- .vtotal = 800 + 28 + 2 + 1,
+ .vsync_start = 800 + 27,
+ .vsync_end = 800 + 27 + 2,
+ .vtotal = 800 + 27 + 2 + 2,
.vrefresh = 60,
.width_mm = 53,
.height_mm = 89,
--
2.20.1

View file

@ -0,0 +1,29 @@
From cc78d2d1c0b02ee1a94801c4a99924ed85808c41 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sun, 10 Feb 2019 00:43:16 +0300
Subject: [PATCH 26/34] ARM: dts: tegra20-glide: fix AK8975
Add GPIO definition instead of interrupt.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 87d737c62b0a..f1909f55d8e3 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -835,8 +835,7 @@
ak8975@c {
compatible = "asahi-kasei,ak8975";
reg = <0xc>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(K, 4) IRQ_TYPE_LEVEL_HIGH>;
+ gpios = <&gpio TEGRA_GPIO(K, 4) GPIO_ACTIVE_HIGH>;
};
};
--
2.20.1

View file

@ -0,0 +1,127 @@
From bc7a628192bb519681a3c93bc1e1ed3f79c358da Mon Sep 17 00:00:00 2001
From: Beomho Seo <beomho.seo@samsung.com>
Date: Mon, 12 Aug 2013 22:04:13 +0900
Subject: [PATCH 27/34] Input: mcs_touchkey: Add parse DT function from device
tree
Add parse DT function for support mcs touchkey driver
Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
---
drivers/input/keyboard/mcs_touchkey.c | 75 +++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index be56d4f262a7..2c9d7f63b562 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -19,6 +19,8 @@
#include <linux/slab.h>
#include <linux/platform_data/mcs.h>
#include <linux/pm.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
/* MCS5000 Touchkey */
#define MCS5000_TOUCHKEY_STATUS 0x04
@@ -96,6 +98,61 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
+static struct mcs_platform_data *mcs_touchkey_parse_dt(struct device *dev)
+{
+ struct mcs_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ u32 *keymap;
+ unsigned int len;
+ int i = 0;
+ const __be32 *prop;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "Failed to allocate platform data\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ prop = of_get_property(np, "linux,code", &len);
+ if (!prop) {
+ dev_err(dev, "Failed to get code\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (len % sizeof(u32)) {
+ dev_err(dev, "Malformed keycode property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ pdata->keymap_size = len / sizeof(u32);
+ keymap = devm_kzalloc(dev, sizeof(*keymap) * pdata->keymap_size, GFP_KERNEL);
+
+ if (of_property_read_u32(np, "key_maxval", &pdata->key_maxval)) {
+ dev_err(dev, "Failed to get key max value data\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (pdata->keymap_size > pdata->key_maxval) {
+ dev_err(dev, "Key map size overflow\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (i = 0; i < pdata->keymap_size; i++) {
+ u32 code = be32_to_cpup(prop + i);
+ keymap[i] = MCS_KEY_MAP(i, code);
+ }
+ pdata->keymap = keymap;
+ return pdata;
+}
+#else
+static inline struct mcs_platform_data *mcs_touchkey_parse_dt
+ (struct device *dev)
+{
+ return NULL;
+}
+#endif
+
static int mcs_touchkey_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -107,10 +164,14 @@ static int mcs_touchkey_probe(struct i2c_client *client,
int error;
int i;
- pdata = dev_get_platdata(&client->dev);
- if (!pdata) {
- dev_err(&client->dev, "no platform data defined\n");
- return -EINVAL;
+ if (&client->dev.of_node)
+ pdata = mcs_touchkey_parse_dt(&client->dev);
+ else
+ pdata = dev_get_platdata(&client->dev);
+
+ if (IS_ERR(pdata)) {
+ dev_err(&client->dev, "Failed to get platform data\n");
+ return PTR_ERR(pdata);
}
data = kzalloc(sizeof(struct mcs_touchkey_data) +
@@ -262,10 +323,16 @@ static const struct i2c_device_id mcs_touchkey_id[] = {
};
MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
+static struct of_device_id mcs_touchkey_dt_match[] = {
+ { .compatible = "mcs5000_touchkey", },
+ { .compatible = "mcs5080_touchkey", },
+};
+
static struct i2c_driver mcs_touchkey_driver = {
.driver = {
.name = "mcs_touchkey",
.pm = &mcs_touchkey_pm_ops,
+ .of_match_table = of_match_ptr(mcs_touchkey_dt_match),
},
.probe = mcs_touchkey_probe,
.remove = mcs_touchkey_remove,
--
2.20.1

View file

@ -0,0 +1,83 @@
From c4ff1dc8430861193f894aa5cb7d4a816dc95b0d Mon Sep 17 00:00:00 2001
From: Beomho Seo <beomho.seo@samsung.com>
Date: Mon, 13 Oct 2014 11:46:26 +0900
Subject: [PATCH 28/34] input: keyboard: mcs_touchkey:Convert to devm_* managed
functions
Tis patch use the devm_* managed functions to allocate resources.
Change-Id: I9351869922b481a6791ca98f6dd3328d84424906
Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
---
drivers/input/keyboard/mcs_touchkey.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index 2c9d7f63b562..933429c165b5 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -174,14 +174,14 @@ static int mcs_touchkey_probe(struct i2c_client *client,
return PTR_ERR(pdata);
}
- data = kzalloc(sizeof(struct mcs_touchkey_data) +
+ data = devm_kzalloc(&client->dev, sizeof(struct mcs_touchkey_data) +
sizeof(data->keycodes[0]) * (pdata->key_maxval + 1),
GFP_KERNEL);
- input_dev = input_allocate_device();
+ input_dev = devm_input_allocate_device(&client->dev);
if (!data || !input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n");
error = -ENOMEM;
- goto err_free_mem;
+ return error;
}
data->client = client;
@@ -204,7 +204,7 @@ static int mcs_touchkey_probe(struct i2c_client *client,
if (fw_ver < 0) {
error = fw_ver;
dev_err(&client->dev, "i2c read error[%d]\n", error);
- goto err_free_mem;
+ return error;
}
dev_info(&client->dev, "Firmware version: %d\n", fw_ver);
@@ -237,27 +237,22 @@ static int mcs_touchkey_probe(struct i2c_client *client,
data->poweron(true);
}
- error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- client->dev.driver->name, data);
+ error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ mcs_touchkey_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->dev.driver->name, data);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
- goto err_free_mem;
+ return error;
}
error = input_register_device(input_dev);
if (error)
- goto err_free_irq;
+ return error;
i2c_set_clientdata(client, data);
- return 0;
-err_free_irq:
- free_irq(client->irq, data);
-err_free_mem:
- input_free_device(input_dev);
- kfree(data);
- return error;
+ return 0;
}
static int mcs_touchkey_remove(struct i2c_client *client)
--
2.20.1

View file

@ -0,0 +1,30 @@
From 6497c54d598bd7b62c2a54a76d3246b155a1cc4b Mon Sep 17 00:00:00 2001
From: Seung-Woo Kim <sw0312.kim@samsung.com>
Date: Thu, 4 Dec 2014 20:19:30 +0900
Subject: [PATCH 29/34] input: keyboard: mcs_touchkey: add sentinel into array
of of_device_id
Without sentinel, of_match_node() to array causes out-of-bound
memory access. So this patch adds sentinel into array.
Change-Id: Icfe3d8c2fdb0faa006f413e7c080b6d713eab08c
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
---
drivers/input/keyboard/mcs_touchkey.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index 933429c165b5..21ceea6bbff5 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -321,6 +321,7 @@ MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
static struct of_device_id mcs_touchkey_dt_match[] = {
{ .compatible = "mcs5000_touchkey", },
{ .compatible = "mcs5080_touchkey", },
+ { },
};
static struct i2c_driver mcs_touchkey_driver = {
--
2.20.1

View file

@ -0,0 +1,49 @@
From ecda374fe948e278635b6146320e5a569097b6a6 Mon Sep 17 00:00:00 2001
From: Beomho Seo <beomho.seo@samsung.com>
Date: Mon, 12 Aug 2013 21:51:45 +0900
Subject: [PATCH 30/34] TRATS2: dts: exynos4412-m0.dts: Add mcs-touchkey node
Support melfas 2 touchkey device for TRATS2 board
Adds also the binding documentation file
Signed-off-by: Beomho Seo <beomho.seo@samsung.com>
---
.../bindings/input/mcs-touchkey.txt | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/mcs-touchkey.txt
diff --git a/Documentation/devicetree/bindings/input/mcs-touchkey.txt b/Documentation/devicetree/bindings/input/mcs-touchkey.txt
new file mode 100644
index 000000000000..545454112a43
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/mcs-touchkey.txt
@@ -0,0 +1,26 @@
+* mcs_touchkey MELFAS MCS5000/5080 controller
+
+Required properties:
+- compatible: must be "mcs5000_touchkey" or "mcs5080_touchkey"
+- reg : I2C address of the chip
+- interrupts: interrupt to which the chop is connected
+- key_maxval: size of keycode table
+- interrupts: interrupt to which the chip is connected
+- code: key code for this device
+
+Example:
+
+ i2c_touch_key: i2c-gpio-0 {
+ /* ... */
+
+ touch_key@20 {
+ compatible = "mcs5080_touchkey";
+ reg = <0x20>;
+ interrupt-patrent = <gpj0>;
+ key_maxval = <2>;
+ linux, code = <0x0000009e
+ 0x000000a9>;
+ };
+
+ /* ... */
+ };
--
2.20.1

View file

@ -0,0 +1,46 @@
From 5efe0ea2a8014795c7c5926f257336394ce2177e Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sun, 10 Feb 2019 13:19:50 +0300
Subject: [PATCH 31/34] ARM: dts: tegra20-glide: Add touchkey binding
This commit adds touchkey binding for Melfas MCS5080
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index f1909f55d8e3..89f0002789ea 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -762,6 +762,8 @@
regulator-name = "nvvdd_ldo20,t_key_3v0";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ regulator-boot-on;
};
out5v {
@@ -1001,10 +1003,14 @@
#address-cells = <1>;
#size-cells = <0>;
- /* Not supported - no driver */
- /* melfas-touchkey@20 {
+ melfas-touchkey@20 {
+ compatible = "mcs5080_touchkey";
reg = <0x20>;
- }; */
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(Q, 4) IRQ_TYPE_EDGE_FALLING>;
+ key_maxval = <4>;
+ linux,code = <KEY_MENU KEY_HOME KEY_BACK KEY_SEARCH>;
+ };
};
i2c@20 {
--
2.20.1

View file

@ -0,0 +1,37 @@
From dd1d90e46c9f1a5d0757330ee2d5801962e9ef60 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sun, 10 Feb 2019 13:21:07 +0300
Subject: [PATCH 32/34] ARM: dts: tegra20-glide: Add keyboard backlight LED
Keyboard backlight on I927 is simple GPIO LED
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 89f0002789ea..3d419e094665 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -1101,6 +1101,17 @@
};
};
+ leds {
+ compatible = "gpio-leds";
+
+ kbd {
+ label = "Keyboard backlight";
+ gpios = <&gpio TEGRA_GPIO(L, 5) GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "gpio";
+ default-state = "off";
+ };
+ };
+
pmc@7000e400 {
nvidia,invert-interrupt;
nvidia,suspend-mode = <0>;
--
2.20.1

View file

@ -0,0 +1,157 @@
From e91d56736df792ebe7da24644ea551a14b68db7a Mon Sep 17 00:00:00 2001
From: "Kim, HeungJun" <riverful.kim@samsung.com>
Date: Mon, 15 Nov 2010 13:33:30 +0900
Subject: [PATCH 33/34] input: keyboard: mcs_touchkey: LED support
This commit adds support for LED found on this touchkey controller.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
drivers/input/keyboard/Kconfig | 1 +
drivers/input/keyboard/mcs_touchkey.c | 61 ++++++++++++++++++++++++---
2 files changed, 57 insertions(+), 5 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4713957b0cbb..38578298491b 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -397,6 +397,7 @@ config KEYBOARD_MAX7359
config KEYBOARD_MCS
tristate "MELFAS MCS Touchkey"
depends on I2C
+ depends on LEDS_CLASS
help
Say Y here if you have the MELFAS MCS5000/5080 touchkey controller
chip in your system.
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index 21ceea6bbff5..36acbaea9aa1 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -21,18 +21,26 @@
#include <linux/pm.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
/* MCS5000 Touchkey */
#define MCS5000_TOUCHKEY_STATUS 0x04
#define MCS5000_TOUCHKEY_STATUS_PRESS 7
#define MCS5000_TOUCHKEY_FW 0x0a
#define MCS5000_TOUCHKEY_BASE_VAL 0x61
+#define MCS5000_TOUCHKEY_LED_ON 0x1
+#define MCS5000_TOUCHKEY_LED_OFF 0x2
/* MCS5080 Touchkey */
#define MCS5080_TOUCHKEY_STATUS 0x00
#define MCS5080_TOUCHKEY_STATUS_PRESS 3
#define MCS5080_TOUCHKEY_FW 0x01
#define MCS5080_TOUCHKEY_BASE_VAL 0x1
+#define MCS5080_TOUCHKEY_LED_ON 0x10
+#define MCS5080_TOUCHKEY_LED_OFF 0x20
+
+#define LED_TIME 500
enum mcs_touchkey_type {
MCS5000_TOUCHKEY,
@@ -44,6 +52,8 @@ struct mcs_touchkey_chip {
unsigned int pressbit;
unsigned int press_invert;
unsigned int baseval;
+ u8 led_on;
+ u8 led_off;
};
struct mcs_touchkey_data {
@@ -54,9 +64,25 @@ struct mcs_touchkey_data {
struct mcs_touchkey_chip chip;
unsigned int key_code;
unsigned int key_val;
+ struct led_classdev led_dev;
unsigned short keycodes[];
};
+
+static void mcs_touchkey_led_brightness_set(struct led_classdev *led_dev,
+ enum led_brightness brightness)
+{
+ struct mcs_touchkey_data *touchkey =
+ container_of(led_dev, struct mcs_touchkey_data, led_dev);
+ u8 buf;
+
+ if (brightness == LED_OFF)
+ buf = touchkey->chip.led_off;
+ else
+ buf = touchkey->chip.led_on;
+ i2c_master_send(touchkey->client, &buf, 1);
+}
+
static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
{
struct mcs_touchkey_data *data = dev_id;
@@ -65,12 +91,21 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
struct input_dev *input = data->input_dev;
unsigned int key_val;
unsigned int pressed;
- int val;
+ u8 val;
+ int ret;
- val = i2c_smbus_read_byte_data(client, chip->status_reg);
- if (val < 0) {
- dev_err(&client->dev, "i2c read error [%d]\n", val);
- goto out;
+ if (chip->status_reg != 0) {
+ val = i2c_smbus_read_byte_data(client, chip->status_reg);
+ if (val < 0) {
+ dev_err(&client->dev, "i2c read error [%d]\n", val);
+ goto out;
+ }
+ } else {
+ ret = i2c_master_recv(client, &val, 1);
+ if (ret < 0) {
+ dev_err(&client->dev, "i2c read error [%d]\n", val);
+ goto out;
+ }
}
pressed = (val & (1 << chip->pressbit)) >> chip->pressbit;
@@ -191,12 +226,16 @@ static int mcs_touchkey_probe(struct i2c_client *client,
data->chip.status_reg = MCS5000_TOUCHKEY_STATUS;
data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS;
data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL;
+ data->chip.led_on = MCS5000_TOUCHKEY_LED_ON;
+ data->chip.led_off = MCS5000_TOUCHKEY_LED_OFF;
fw_reg = MCS5000_TOUCHKEY_FW;
} else {
data->chip.status_reg = MCS5080_TOUCHKEY_STATUS;
data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS;
data->chip.press_invert = 1;
data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL;
+ data->chip.led_on = MCS5080_TOUCHKEY_LED_ON;
+ data->chip.led_off = MCS5080_TOUCHKEY_LED_OFF;
fw_reg = MCS5080_TOUCHKEY_FW;
}
@@ -252,6 +291,18 @@ static int mcs_touchkey_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
+ data->led_dev.name = "mcs_touchkey_led";
+ data->led_dev.brightness = LED_FULL;
+ data->led_dev.max_brightness = LED_ON;
+ data->led_dev.brightness_set = mcs_touchkey_led_brightness_set;
+
+ error = devm_led_classdev_register(&client->dev, &data->led_dev);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to register touchkey led: %d\n", error);
+ return error;
+ }
+
return 0;
}
--
2.20.1

View file

@ -0,0 +1,48 @@
From ceeecef75e5faa16a3f435eb25bb66c3d983a345 Mon Sep 17 00:00:00 2001
From: Sergey Larin <cerg2010cerg2010@mail.ru>
Date: Sun, 10 Feb 2019 16:55:18 +0300
Subject: [PATCH 34/34] ARM: dts: tegra20-glide: Add HALL GPIO binding
This is used for keyboard slide detection.
Signed-off-by: Sergey Larin <cerg2010cerg2010@mail.ru>
---
arch/arm/boot/dts/tegra20-glide.dts | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm/boot/dts/tegra20-glide.dts b/arch/arm/boot/dts/tegra20-glide.dts
index 3d419e094665..ab30b1b8cc29 100644
--- a/arch/arm/boot/dts/tegra20-glide.dts
+++ b/arch/arm/boot/dts/tegra20-glide.dts
@@ -1107,6 +1107,14 @@
kbd {
label = "Keyboard backlight";
gpios = <&gpio TEGRA_GPIO(L, 5) GPIO_ACTIVE_HIGH>;
+ /*
+ * Looks like there's no way to specify GPIO for trigger in DT.
+ * So keyboard hall GPIO is PW3, which number is 179.
+ * (See TEGRA_GPIO() macro)
+ * To enable this trigger:
+ * echo gpio > /sys/class/leds/Keyboard\ backlight/trigger
+ * echo 179 > /sys/class/leds/Keyboard\ backlight/gpio
+ */
linux,default-trigger = "gpio";
default-state = "off";
};
@@ -1232,6 +1240,13 @@
linux,code = <KEY_VOLUMEDOWN>;
debounce-interval = <10>;
};
+
+ hall {
+ label = "Keyboard slide";
+ gpios = <&gpio TEGRA_GPIO(W, 3) GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_KEYPAD_SLIDE>;
+ };
};
spi@7000d800 {
--
2.20.1

View file

@ -3,7 +3,7 @@
pkgname="linux-samsung-i927"
pkgver=4.20.4
pkgrel=0
pkgrel=1
pkgdesc="Samsung Captivate Glide kernel fork"
arch="armhf"
_carch="arm"
@ -23,7 +23,40 @@ _config="config-${_flavor}.${arch}"
source="
$pkgname-$pkgver.tar.gz::https://kernel.org/pub/linux/kernel/v4.x/linux-$pkgver.tar.gz
$_config
kernel.patch
0001-dt-bindings-drm-panel-Add-Samsung-s6e63m0-panel-docu.patch
0002-drm-panel-Add-driver-for-Samsung-S6E63M0-panel.patch
0003-drm-tegra-Hacks-for-S6E63M0.patch
0004-iio-gyro-mpu3050-get-chip-ID-correctly.patch
0005-soc-tegra-fix-build-for-Tegra.patch
0006-mmc-core-Add-a-quirk-for-NVIDIA-Tegra-EMMC.patch
0007-leds-Add-led-class-support-isa1200-vibration-motor.patch
0008-iio-accel-kxcjk-Add-device-tree-support.patch
0009-ARM-dts-tegra20-glide-Samsung-SGH-I927-support.patch
0010-Input-stmpe-keypad-add-STMPE1801-support.patch
0011-Add-tegra_wm8994-driver.patch
0012-HACK-Fix-wm8994-Kconfig.patch
0013-ASoC-tegra_wm8994-cleanup.patch
0014-ARM-dts-tegra20-glide-Device-Tree-changes.patch
0015-ARM-dts-tegra20-glide-add-memory-node-address.patch
0016-ARM-dts-tegra20-glide-comment-out-MHL.patch
0017-ARM-dts-tegra20-glide-fix-duplicate-i2c-bus-address.patch
0018-ARM-dts-tegra20-glide-fix-USB-gadget-mode.patch
0019-ARM-dts-tegra20-glide-change-display-timings.patch
0020-ARM-dts-tegra20-glide-add-intrrupt-binding-for-charg.patch
0021-drm-panel-s6e63m0-disable-rotation.patch
0022-ARM-dts-tegra20-glide-set-panel-reset-GPIO-pin-to-ac.patch
0023-power-supply-max17040-Fix-voltage-reporting.patch
0024-power-supply-max17040-Set-initial-RCOMP-value.patch
0025-drm-panel-s6e63m0-Increase-back-porch.patch
0026-ARM-dts-tegra20-glide-fix-AK8975.patch
0027-Input-mcs_touchkey-Add-parse-DT-function-from-device.patch
0028-input-keyboard-mcs_touchkey-Convert-to-devm_-managed.patch
0029-input-keyboard-mcs_touchkey-add-sentinel-into-array-.patch
0030-TRATS2-dts-exynos4412-m0.dts-Add-mcs-touchkey-node.patch
0031-ARM-dts-tegra20-glide-Add-touchkey-binding.patch
0032-ARM-dts-tegra20-glide-Add-keyboard-backlight-LED.patch
0033-input-keyboard-mcs_touchkey-LED-support.patch
0034-ARM-dts-tegra20-glide-Add-HALL-GPIO-binding.patch
"
builddir="$srcdir/${_repository}-${pkgver}"
@ -71,5 +104,38 @@ package() {
}
sha512sums="5f9eb065932e404091dd9e4afd5a92b6382ddbc81488684c42981cdfe227da9a423356c19ec236ca1a9a7f4bf042cf351aa8b3cd4f7488b0d8b1245d69221a5c linux-samsung-i927-4.20.4.tar.gz
fb556670c376c85f6c0ad0105179298e8d7b1564e32c7a50152924112407dcc294b5e322eb207e801f61e81f9511e28c52dcd663152c2e5a1ea1a9e0100d09ba config-samsung-i927.armhf
c65a89a07b20b3720d6187c6049f215823b07fd4ba647984691bf37d2488a71f4e00ce8bc9521c499b7e15f13fb1473289a8eeea42899d5a6c0c3247b0a94549 kernel.patch"
c676893a5062a0cc1e4cfe2ad4f73087ae787e301d2f17a20cecc9cbce76fdd564517068ea063b07c26065107ac6e27e7c2be51b018796a1a982ec47cc852fa5 config-samsung-i927.armhf
8791c158836bd8db5b8b557138dd4b5ca9ffd94d0bc441c1fde649733c18a6ee73dde47aef96582edc844e059acd501ff4f8a6aad5157833b41e6e15bbf12f81 0001-dt-bindings-drm-panel-Add-Samsung-s6e63m0-panel-docu.patch
f8f1bf6944898b06fdec922eb97a674d2edcf58f1dac02aff6761674ec5b615b5432553e98bbb39b2b9110534b5a9a57f8f1a107e39ced48edd61cd194ac4935 0002-drm-panel-Add-driver-for-Samsung-S6E63M0-panel.patch
75bf4aaf46de8d56de9348c7c772a1063637aae9dc77f8da397d7e1220d4b29d5ccde3242b38b31d483f07f1c2a2b4e075cf04bfedcf0cf2ded09114b18b1bdb 0003-drm-tegra-Hacks-for-S6E63M0.patch
498796860ca706cb2d6914f6677942567782434887cdeb5872a7a03fa5f08c45ea3180fa2ab4e9976327b1a8786092a12171143c32182d88a0aee327b43ef2b0 0004-iio-gyro-mpu3050-get-chip-ID-correctly.patch
547215e283c4b6b5c390f4e954ffcfffa89da9037eab7dd59cf339bbda8a0bc2136bc515a5b3518b6161bf81ba59df5675dacf7a48a811a2c1391037ba6a2a36 0005-soc-tegra-fix-build-for-Tegra.patch
c3e771e046f76f516cbefb5aeae4064279dfb6a0b76c2f05d577753ab1150ca2f3c6201e8903b8a174997028f935287fe2a5f6727d1fe07cba56331b18763f21 0006-mmc-core-Add-a-quirk-for-NVIDIA-Tegra-EMMC.patch
ff287c7938489f96e3a2a31f7fcd55bfb3945984dbd89796684c820ca19ceb7275307517925939fa5d9b03a42f9bea649d3baf4c9c26d835c9ff2f98bd898403 0007-leds-Add-led-class-support-isa1200-vibration-motor.patch
f9d1e22735cc8c3e8300f05a63527dcf78ce74da1ec9538155a66eb34d2421a4f449ca8c6bc7b62fa146e762b4ec997aa563da5c6f1586285aec5f79ee3cda2f 0008-iio-accel-kxcjk-Add-device-tree-support.patch
4c829deef770aab5c17314853af10c8acb913be3ed839a6b926680da54bc7e3f3d85c12862dd4b530ef57a569cceb55693fc269e9fd232636070cb6d8676891e 0009-ARM-dts-tegra20-glide-Samsung-SGH-I927-support.patch
4740867e900e05c3db66ec4069ba2b8a371a05ebb11b9e40349fe3f94466a7f80596bdf809d90a9a3389f861db4d272f4913069323c17144411fa831a4ec03ae 0010-Input-stmpe-keypad-add-STMPE1801-support.patch
af1cee099fe35eef22fb77889f9e9784f6bcc2606e16d837824e9fc0e0a6a33e2d58565cad8daa362de5a1fe9dd32e229ec4a7323aa61e823bb7f4a0c06fd9df 0011-Add-tegra_wm8994-driver.patch
cf0b473400968f7b8472a5657855df18a2240b3335cc21c2d1207e634ecfce9565b57407eab6dee432d60ddc6418e1638d67c156881f92acf382afe8542f1e02 0012-HACK-Fix-wm8994-Kconfig.patch
41ea8f9e714b6809d52ab0e3d7da655746f73715ae5ef1e1b108c2f569491056530f128b5acc5ece1800b578f558e014f1fc016a0116a76b039c665a440308a4 0013-ASoC-tegra_wm8994-cleanup.patch
dc36fa11439f24bff01f0f098d396bd7ec53e25bc9528e80227d197607f7def6383bb7780abb01c6bd544dc2718b587472f7367a02eb758ca28ee2de3285974a 0014-ARM-dts-tegra20-glide-Device-Tree-changes.patch
93caaa3cc90c45614aa4f1659933cd7dd81baaf473a9c13aa6ebc2092dd15f02121df4a2af6cb0d0b4d0db4c0e348a3e775834011378b0a693f0cf47cf25b722 0015-ARM-dts-tegra20-glide-add-memory-node-address.patch
392c7d65c94d7fd8d7c745b2cc9f4352683e5026d29e985c49ba8aaf381b0383ba6aaf85222715de0c8ee95f36b6f7609e7dc464bde47a6f919b808504080dc0 0016-ARM-dts-tegra20-glide-comment-out-MHL.patch
a47ff803d2c1df850bf5ad75ae0a8c1fe9275e6252ba679cd62f37abe7a4fe100aa48eb1f494104846facdb74d6fd77aed7658bcbc17501d05375cc2b04c31e8 0017-ARM-dts-tegra20-glide-fix-duplicate-i2c-bus-address.patch
3637e6b7231183cd0953c06c698ec54790615dc9dadaa91b7633adf41bf300c006be35665ff02bb5c1f7324329f859c9dd82876eeeeb8a3203290473904e4bfb 0018-ARM-dts-tegra20-glide-fix-USB-gadget-mode.patch
171563e46a6b1ca9be9cf105ea8f601a1d113ee8d007cee4abe54f4c025dc933497b0070b3e5e2401ce04206b7a477924d26f2615e17f8f2a7c6128e3172c93a 0019-ARM-dts-tegra20-glide-change-display-timings.patch
b3981b1f88b70ec59289171e75b462edfebf918f229cb3c549febdfecb0d0efc1842e4820b8c172a372ba136d5939cdf81f9dd24441168400688626288e29fbd 0020-ARM-dts-tegra20-glide-add-intrrupt-binding-for-charg.patch
222fedee563f19ba5e6fba7393099f061040065ea690f597743dab4f5851dc9d559c949f975025444720f320496195e5cd027f37a1bf4ce591537e9e64c45135 0021-drm-panel-s6e63m0-disable-rotation.patch
2014b13ab9ebb1ade4e3d882916922365fa663adecf4a1b8da4ca2f433bf26352b80eab69e79af72285a6a1bb1d0848e33fe032ff644d94496c98247ef775728 0022-ARM-dts-tegra20-glide-set-panel-reset-GPIO-pin-to-ac.patch
ccaa18e3d4b27d6f8c07e968abafc006067b1150993e167f725e06af3cd6884cfcf502ac4cc758638b170a212a28e66a670ba85429ca2c2143e0f607243bc9ad 0023-power-supply-max17040-Fix-voltage-reporting.patch
de6f1efea36f66d360e5ff542982ff47d696ac81ff4328f50fc96a37eb8c446d13d52035c4e097e19938c3e9e7b9fc423c4d9d4801de0937b5f6be0b125a4d64 0024-power-supply-max17040-Set-initial-RCOMP-value.patch
e48f47d145f6312cbed5fcd9a907c3037704634f027c85fe03e7a3e90402d2172f8734bbfc14858a9238e6ff84fb7f136a7187349a62786171feeb1b54ef87d7 0025-drm-panel-s6e63m0-Increase-back-porch.patch
3dd3fcc3d607b584bab5407346c65f2ba5650ae34e39e913809bd6eaf8b2fe3e6a79973efde0cca4024dab5e9c3f8e9c66293bb3d99a55c5bf81875ca1779f85 0026-ARM-dts-tegra20-glide-fix-AK8975.patch
4a448e378bdfcca1292bbc877581984d64205429ed7f61e80cb22422714b15fe1691e2234475c3ee84e744580f5e4e6ef5e8023d683332f4f2acce0779978469 0027-Input-mcs_touchkey-Add-parse-DT-function-from-device.patch
caf9e44d8b6f8efa414d21a0fa74cdbb0df0902651dc18e26969b91c411ec8826223b2bda5b96e2df669c4f1901e4bcfa7a5e6beb4f15e33f6aa016f15589b4f 0028-input-keyboard-mcs_touchkey-Convert-to-devm_-managed.patch
993192bd8675f942b0fd5f378a7653b94d190f05ee8f883888aa8d58b9a355b8ad3d85ad97b75a553fe415e1a394acd9c248cf734340609b767ded90b7f56343 0029-input-keyboard-mcs_touchkey-add-sentinel-into-array-.patch
43a5695a1fd999acb4f6dc5e0d0af17b8b2c74995db2ce0082a69876a285256c992ab4090cc09571897446a7fe85c706a7131ca951a83e033a6f8cba77013fdb 0030-TRATS2-dts-exynos4412-m0.dts-Add-mcs-touchkey-node.patch
a1ab752a0aab1b53108cc0ec7ead852d97ccab3c43fb682bed77e1e4d62098268214d06aa8e058ab96f8634de6233c5934743f5e7d8345ae158a7409ec4e9d24 0031-ARM-dts-tegra20-glide-Add-touchkey-binding.patch
7eebe202647b5d7308a67892d9fa981b2e87044786665f46133effde406c02f0a4c1f73158850ce4551f57f5fcefccbec51b342ece3c60bb4c7d7193435cd146 0032-ARM-dts-tegra20-glide-Add-keyboard-backlight-LED.patch
92c7416647fe780ef1b2a3dda5468e0c13b10c40937f0a620d666d4785a4354d88e2d4c12fdaa1e2399322caebd625c198c22ac74e646b097642e3d5ae241910 0033-input-keyboard-mcs_touchkey-LED-support.patch
679cbe5d74515fbdeb55c3a4aeb0571d6b0096483cbb93ef3fc645c5aa80ab3f3731f52001c08979f2742ad90c8dedf5231f40fecef55d7b5761004373cfeb58 0034-ARM-dts-tegra20-glide-Add-HALL-GPIO-binding.patch"

View file

@ -795,6 +795,7 @@ CONFIG_NETFILTER_XTABLES=y
# CONFIG_NETFILTER_XT_TARGET_HL is not set
# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
# CONFIG_NETFILTER_XT_TARGET_LED is not set
# CONFIG_NETFILTER_XT_TARGET_LOG is not set
# CONFIG_NETFILTER_XT_TARGET_MARK is not set
# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
@ -968,6 +969,8 @@ CONFIG_BT_HCIUART_BCM=y
# CONFIG_AF_RXRPC is not set
# CONFIG_AF_KCM is not set
CONFIG_WIRELESS=y
CONFIG_WEXT_CORE=y
CONFIG_WEXT_PROC=y
CONFIG_CFG80211=y
# CONFIG_NL80211_TESTMODE is not set
# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
@ -975,11 +978,12 @@ CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
CONFIG_CFG80211_DEFAULT_PS=y
CONFIG_CFG80211_CRDA_SUPPORT=y
# CONFIG_CFG80211_WEXT is not set
CONFIG_CFG80211_WEXT=y
# CONFIG_MAC80211 is not set
CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
CONFIG_RFKILL_LEDS=y
CONFIG_RFKILL_INPUT=y
# CONFIG_RFKILL_GPIO is not set
# CONFIG_NET_9P is not set
@ -1298,7 +1302,7 @@ CONFIG_KEYBOARD_GPIO=y
# CONFIG_KEYBOARD_LM8323 is not set
# CONFIG_KEYBOARD_LM8333 is not set
# CONFIG_KEYBOARD_MAX7359 is not set
# CONFIG_KEYBOARD_MCS is not set
CONFIG_KEYBOARD_MCS=y
# CONFIG_KEYBOARD_MPR121 is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_KEYBOARD_TEGRA=y
@ -2312,12 +2316,26 @@ CONFIG_DRM_PANEL=y
#
# Display Panels
#
# CONFIG_DRM_PANEL_LVDS is not set
# CONFIG_DRM_PANEL_SIMPLE is not set
# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set
# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set
# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set
# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set
# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
# CONFIG_DRM_PANEL_LG_LG4573 is not set
# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set
# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set
# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set
CONFIG_DRM_PANEL_SAMSUNG_S6E63M0=y
# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set
# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set
# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set
# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set
CONFIG_DRM_BRIDGE=y
CONFIG_DRM_PANEL_BRIDGE=y
@ -2380,8 +2398,18 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_SIMPLE is not set
# CONFIG_FB_SSD1307 is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
CONFIG_VIDEOMODE_HELPERS=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_GENERIC is not set
# CONFIG_BACKLIGHT_PM8941_WLED is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
# CONFIG_BACKLIGHT_LM3639 is not set
# CONFIG_BACKLIGHT_GPIO is not set
# CONFIG_BACKLIGHT_LV5207LP is not set
# CONFIG_BACKLIGHT_BD6107 is not set
# CONFIG_BACKLIGHT_ARCXCNN is not set
CONFIG_HDMI=y
#
@ -2717,6 +2745,7 @@ CONFIG_USB_OTG=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_OTG_FSM=y
# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set
# CONFIG_USB_MON is not set
# CONFIG_USB_WUSB_CBAF is not set
@ -2861,6 +2890,7 @@ CONFIG_USB_ETH_EEM=y
# CONFIG_USB_G_WEBCAM is not set
# CONFIG_TYPEC is not set
CONFIG_USB_ROLE_SWITCH=y
# CONFIG_USB_LED_TRIG is not set
CONFIG_USB_ULPI_BUS=y
# CONFIG_UWB is not set
CONFIG_MMC=y
@ -2911,7 +2941,7 @@ CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_LM3642 is not set
# CONFIG_LEDS_LM3692X is not set
# CONFIG_LEDS_PCA9532 is not set
# CONFIG_LEDS_GPIO is not set
CONFIG_LEDS_GPIO=y
# CONFIG_LEDS_LP3944 is not set
# CONFIG_LEDS_LP3952 is not set
# CONFIG_LEDS_LP5521 is not set
@ -2942,7 +2972,24 @@ CONFIG_LEDS_ISA1200=y
#
# LED Triggers
#
# CONFIG_LEDS_TRIGGERS is not set
CONFIG_LEDS_TRIGGERS=y
# CONFIG_LEDS_TRIGGER_TIMER is not set
# CONFIG_LEDS_TRIGGER_ONESHOT is not set
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_CPU is not set
# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
CONFIG_LEDS_TRIGGER_GPIO=y
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
#
# iptables trigger is under Netfilter config (LED target)
#
# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
# CONFIG_LEDS_TRIGGER_CAMERA is not set
# CONFIG_LEDS_TRIGGER_PANIC is not set
# CONFIG_LEDS_TRIGGER_NETDEV is not set
# CONFIG_LEDS_TRIGGER_PATTERN is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
CONFIG_EDAC_ATOMIC_SCRUB=y

File diff suppressed because it is too large Load diff