From nobody Thu Oct 2 18:17:14 2025 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64E981EA7DD for ; Sun, 14 Sep 2025 13:45:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757857528; cv=none; b=sYOI4TXMjXupcL3PRF+rCi05SRJzG3OaO56ys3Apmbb8+A9yBqA/49c+t6pAnSAm5ufONqTaN7Wr5JnfKATvO6np3DMua/2jLqb+LnvkNT4Ofv2Eivq6JiT6lDF4PN90EM/V+aykEUO8Jbj67YsfLYnQ0goki7DVVuGQyHqHP/A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757857528; c=relaxed/simple; bh=mhlqPe+rYAdqQ2489lVPW8Nz3WhM6I/OuGV4Y0trFXw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S4lD2NGx4vf5xjOcQFFJdbk3FGpwshoxFo/psHyxcBg+rwUYwRRoa6MpGTnIA/cyDImhscE3tgDHNmH0dYmMqZSUCW1BPWC/56Id9NZhR8KH8VeOXQD4s6fVUVXDf/lEEBiUM1rcV05tFKcWcOXj99vzKLX8+v0FUfjcAHdWJhE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ERUlvflY; arc=none smtp.client-ip=209.85.221.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ERUlvflY" Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-3e4b5aee522so1997313f8f.1 for ; Sun, 14 Sep 2025 06:45:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1757857525; x=1758462325; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z1C66At/iPHB+YbOfF0ahn3G5fgbhry39+iH3jn1wwY=; b=ERUlvflYYGBSummwCm8InAPQRET0dtwD/5uN0cuclq8KZ3CLDl4+sTxsmUbflhnPMV 9/4vYIWQqDSPg1rxk8v+o5x/pZqIhdKJrM/WePAIg5SlbiuwRLM4P+sgB0QQ5c5T5nAs J8ftvydhVckkrs3/0wGldr0jJc31gEJc/frwyA3F0ypmPVPPSWp+2BN58tu2gT4WzQtq /AcAl9m+IcduahL+q3/Im+atrB/9/YJO2r8PLK/3trK0YxHK8Ff29ctZWpgEpcGTPbJu EtNVqpIk/m6HuScJ8Wchfa9CxW2RqFiyAfTMtVlY9lqsukdsp8Goj8kNtGhaH8Q4BjzS I5ew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757857525; x=1758462325; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z1C66At/iPHB+YbOfF0ahn3G5fgbhry39+iH3jn1wwY=; b=LxS7wgID19OuZxT8NIvq2NsIN6TPcDEiOh2iy0da7nVypfHXYB+q9ztbAWHWg0D1Op uJ0VuBrp+WKUmDvyKPAXNsjqTbRu2jixDQDFz9vj5E3VqcnIdQpWR8M8zjjOXzgiCxCI VSd7lnDGcCeOwzpKGc+FaqrEuha8t+GlH5gOkCuNODZ3kAdxPY1PYQuGU0xB+/So4mY+ +w/GT1FNWlRxg8TwiZOeNqpcyeEPYM6j7Rx5mfXRVZiIOXuDQsghofHDR3wlzmCW4k52 Pik60ArbP71KP470n6I7XmklraWoz1fjbslEWpUX46BZhEcQwfHLuvkFcLJSL+2nfqOb H/YA== X-Forwarded-Encrypted: i=1; AJvYcCUN+mVK+mRT/kBcifaPRz1E6Kscp0QQkA9laRhHVAEv2uSs6GwPVisDfDiJBmmvvWUVWrx+mBZbRkhup6A=@vger.kernel.org X-Gm-Message-State: AOJu0YyB4yw3ENv8+PvIoqV8dDst6VvEKV2d68VpehA8j3Mru9k8OABV GBKPlP6Cij+5adohOCJqRVST0tUSM8fF7Gs21B+LRKhqlEdcrunpTVQ2 X-Gm-Gg: ASbGncv3VVGn/5brHjxbs3mes8vCfLJRqdY37kf1lLwbf0CUmgYSCWQr3iJPzZHZ9lB NkAIsf0gR3LaiJkRgfaosbDL1bSdEkLT4YG8M+7siXLHFGliRMcMLy3TX6lpLGFQV9/Bs8S85Ud iO7XI7gj134IDTNvYZUCnqVjmoM5cfE4KRyS4b5NcH1+SStahwFQ7YXKGjXRMaT9g4dtFVvQpU5 MPVgRQfbWN8/hkokao9vDWWf+TwL95GvMf8BwA691HcoTPlhqcoKwdo4+wI66dgNQouCDvQcq+v 4q+NJQJ/F8prSrobiZgv9wqPTt0JeKw/kit3luKUMOOYfrtK/naSuWlNH8eKOMykW02GoNCWZru X1d7s0yx6IZwZsddphfI8Wl+d+EfRvoWp9oiCClAHodfa516RKeNDKDMYhO52dYSyGmC4BV4yiN 3NJcXmzioP X-Google-Smtp-Source: AGHT+IGY5Y2KTdaZaAd3HnAGXpedRNw4b12KEMkqN57ZikiQBKfKGS5CdY+ghvCof9iN933uImvqEQ== X-Received: by 2002:a05:6000:22ca:b0:3e9:2fea:6795 with SMTP id ffacd0b85a97d-3e92fea6b35mr2699385f8f.53.1757857524471; Sun, 14 Sep 2025 06:45:24 -0700 (PDT) Received: from ivaylo-T580.. (91-139-201-119.stz.ddns.bulsat.com. [91.139.201.119]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3ea4b52b7fcsm1467591f8f.33.2025.09.14.06.45.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 14 Sep 2025 06:45:24 -0700 (PDT) From: Ivaylo Ivanov To: Krzysztof Kozlowski , Rob Herring , Dmitry Torokhov , Conor Dooley , Henrik Rydberg Cc: linux-samsung-soc@vger.kernel.org, linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v1 2/2] Input: s6sa552 - add a driver for the Samsung A552 touchscreen controller Date: Sun, 14 Sep 2025 16:44:57 +0300 Message-ID: <20250914134458.2624176-3-ivo.ivanov.ivanov1@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250914134458.2624176-1-ivo.ivanov.ivanov1@gmail.com> References: <20250914134458.2624176-1-ivo.ivanov.ivanov1@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The S6SA552 touchscreen is a capacitive multi-touch controller for mobile use. It connects via i2c at the address 0x48. Introduce a basic driver, which can handle initialization, touch events and power states. At least the firmware for this IC on Galaxy S7 differs from S6SY761 in register layout and bits, as well as some missing registers/functions, for example for retrieving the max X/Y coordinates and the amount of TX/RX channels. Signed-off-by: Ivaylo Ivanov --- Samsung almost completely didn't mention the IC name in the vendor drivers.. I retrieved it from a fw-update function that checks a firmware bit and matches it with an IC model string. Otherwise everywhere else it's called sec_ts. I believe the main difference between samsung touchscreen controllers is the firmware they're running on, but this one is a bit different from s6sy761, featuring different registers and bits, as well as some missing features. I went with calling it s6sa552 to follow the "s6s" convention, because as far as I know, s6sy661 also exists, and the important part is after "s6s". --- drivers/input/touchscreen/Kconfig | 11 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/s6sa552.c | 439 ++++++++++++++++++++++++++++ 3 files changed, 451 insertions(+) create mode 100644 drivers/input/touchscreen/s6sa552.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/= Kconfig index 196905162..2d65dd13e 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -505,6 +505,17 @@ config TOUCHSCREEN_IPROC To compile this driver as a module, choose M here: the module will be called bcm_iproc_tsc. =20 +config TOUCHSCREEN_S6SA552 + tristate "Samsung S6SA552 Touchscreen driver" + depends on I2C + help + Say Y if you have the Samsung S6SA552 driver + + If unsure, say N + + To compile this driver as module, choose M here: the + module will be called s6sa552. + config TOUCHSCREEN_S6SY761 tristate "Samsung S6SY761 Touchscreen driver" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen= /Makefile index 97a025c6a..d3be3e21a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP) +=3D pcap_ts.o obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) +=3D penmount.o obj-$(CONFIG_TOUCHSCREEN_PIXCIR) +=3D pixcir_i2c_ts.o obj-$(CONFIG_TOUCHSCREEN_RM_TS) +=3D raydium_i2c_ts.o +obj-$(CONFIG_TOUCHSCREEN_S6SA552) +=3D s6sa552.o obj-$(CONFIG_TOUCHSCREEN_S6SY761) +=3D s6sy761.o obj-$(CONFIG_TOUCHSCREEN_SILEAD) +=3D silead.o obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) +=3D sis_i2c.o diff --git a/drivers/input/touchscreen/s6sa552.c b/drivers/input/touchscree= n/s6sa552.c new file mode 100644 index 000000000..32ef338de --- /dev/null +++ b/drivers/input/touchscreen/s6sa552.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: GPL-2.0 +// Samsung S6SA552 Touchscreen device driver +// +// Copyright (c) 2025 Ivaylo Ivanov +// +// Based on the s6sy761 driver: +// Copyright (c) 2017 Samsung Electronics Co., Ltd. +// Copyright (c) 2017 Andi Shyti + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* commands */ +#define S6SA552_SENSE_ON 0x40 +#define S6SA552_SENSE_OFF 0x41 +#define S6SA552_TOUCH_FUNCTION 0x63 +#define S6SA552_DEVICE_ID 0x52 +#define S6SA552_BOOT_STATUS 0x55 +#define S6SA552_READ_ONE_EVENT 0x71 +#define S6SA552_CLEAR_EVENT_STACK 0x60 +#define S6SA552_PANEL_INFO 0x23 + +/* acknowledge events */ +#define S6SA552_EVENT_ACK_BOOT 0x0c + +/* status event types */ +#define S6SA552_EVENT_TYPE_ACK 0x01 +#define S6SA552_EVENT_TYPE_ERR 0x02 +#define S6SA552_EVENT_TYPE_INFO 0x03 +#define S6SA552_EVENT_TYPE_GEST 0x06 +#define S6SA552_EVENT_TYPE_SPONGE 0x5a + +/* boot status (BS) */ +#define S6SA552_BS_APPLICATION 0x20 + +/* event id */ +#define S6SA552_EVENT_ID_COORDINATE 0x01 +#define S6SA552_EVENT_ID_STATUS 0x00 + +/* event register masks */ +#define S6SA552_MASK_TID 0x0f /* byte 1, lower 4 bits */ +#define S6SA552_MASK_NT 0xf0 /* byte 1, upper 4 bits */ +#define S6SA552_MASK_EID 0xc0 /* byte 0, bits 6-7 */ +#define S6SA552_MASK_TOUCH_STATE 0x07 /* byte 0, bits 0-2 */ +#define S6SA552_MASK_TOUCH_TYPE 0x38 /* byte 0, bits 3-5 */ + +/* touch states */ +#define S6SA552_TS_NONE 0x00 +#define S6SA552_TS_PRESS 0x01 +#define S6SA552_TS_MOVE 0x02 +#define S6SA552_TS_RELEASE 0x03 + +#define S6SA552_EVENT_SIZE 8 +#define S6SA552_DEVID_SIZE 3 +#define S6SA552_PANEL_ID_SIZE 11 +#define S6SA552_MAX_FINGERS 10 + +/* + * Hardcoded values, since at least on herolte, the subid register doesn't + * read/exist. + */ +#define S6SA552_MAX_X 4095 +#define S6SA552_MAX_Y 4095 +#define S6SA552_TX_CHANNELS 16 + +#define S6SA552_DEV_NAME "s6sa552" + +enum s6sa552_regulators { + S6SA552_REGULATOR_VDD, + S6SA552_REGULATOR_AVDD, +}; + +struct s6sa552_data { + struct i2c_client *client; + struct regulator_bulk_data regulators[2]; + struct input_dev *input; + struct touchscreen_properties prop; + + u8 data[S6SA552_EVENT_SIZE]; + + u16 devid; + u8 tx_channel; +}; + +static void s6sa552_report_coordinates(struct s6sa552_data *sdata, + u8 *event, u8 tid) +{ + u8 major =3D event[6]; + u8 minor =3D event[7]; + u8 z =3D event[5]; + u16 x =3D (event[2] << 4) | ((event[4] >> 4) & 0x0F); + u16 y =3D (event[3] << 4) | (event[4] & 0x0F); + + input_mt_slot(sdata->input, tid); + + input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true); + input_report_abs(sdata->input, ABS_MT_POSITION_X, x); + input_report_abs(sdata->input, ABS_MT_POSITION_Y, y); + input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, major); + input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, minor); + input_report_abs(sdata->input, ABS_MT_PRESSURE, z); + + input_sync(sdata->input); +} + +static void s6sa552_report_release(struct s6sa552_data *sdata, u8 tid) +{ + input_mt_slot(sdata->input, tid); + input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, false); + + input_sync(sdata->input); +} + +static void s6sa552_handle_coordinates(struct s6sa552_data *sdata, u8 *eve= nt) +{ + u8 tid; + u8 touch_state; + + if (unlikely(!(event[1] & S6SA552_MASK_TID))) + return; + + tid =3D (event[1] & S6SA552_MASK_TID) - 1; + touch_state =3D event[0] & S6SA552_MASK_TOUCH_STATE; + + switch (touch_state) { + case S6SA552_TS_PRESS: + case S6SA552_TS_MOVE: + s6sa552_report_coordinates(sdata, event, tid); + break; + case S6SA552_TS_RELEASE: + s6sa552_report_release(sdata, tid); + break; + case S6SA552_TS_NONE: + default: + break; + } +} + +static irqreturn_t s6sa552_irq_handler(int irq, void *dev) +{ + struct s6sa552_data *sdata =3D dev; + int ret; + u8 event_id; + + ret =3D i2c_smbus_read_i2c_block_data(sdata->client, + S6SA552_READ_ONE_EVENT, + S6SA552_EVENT_SIZE, + sdata->data); + if (ret < 0) { + dev_err(&sdata->client->dev, "failed to read event\n"); + return IRQ_HANDLED; + } + + if (!sdata->data[0]) + return IRQ_HANDLED; + + event_id =3D sdata->data[0] >> 6; + + switch (event_id) { + case S6SA552_EVENT_ID_COORDINATE: + s6sa552_handle_coordinates(sdata, sdata->data); + break; + case S6SA552_EVENT_ID_STATUS: + break; + default: + break; + } + + return IRQ_HANDLED; +} + +static int s6sa552_input_open(struct input_dev *dev) +{ + struct s6sa552_data *sdata =3D input_get_drvdata(dev); + + return i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_ON); +} + +static void s6sa552_input_close(struct input_dev *dev) +{ + struct s6sa552_data *sdata =3D input_get_drvdata(dev); + int ret; + + ret =3D i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_OFF); + if (ret) + dev_err(&sdata->client->dev, "failed to turn off sensing\n"); +} + +static ssize_t s6sa552_sysfs_devid(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct s6sa552_data *sdata =3D dev_get_drvdata(dev); + + return sprintf(buf, "%#x\n", sdata->devid); +} + +static DEVICE_ATTR(devid, 0444, s6sa552_sysfs_devid, NULL); + +static struct attribute *s6sa552_sysfs_attrs[] =3D { + &dev_attr_devid.attr, + NULL +}; +ATTRIBUTE_GROUPS(s6sa552_sysfs); + +static int s6sa552_power_on(struct s6sa552_data *sdata) +{ + u8 buffer[S6SA552_EVENT_SIZE]; + int ret; + + ret =3D regulator_bulk_enable(ARRAY_SIZE(sdata->regulators), + sdata->regulators); + if (ret) + return ret; + + msleep(140); + + /* double check whether the touch is functional */ + ret =3D i2c_smbus_read_i2c_block_data(sdata->client, + S6SA552_READ_ONE_EVENT, + S6SA552_EVENT_SIZE, + buffer); + if (ret < 0) + return ret; + + if (buffer[0] !=3D S6SA552_EVENT_TYPE_ACK || + buffer[1] !=3D S6SA552_EVENT_ACK_BOOT) { + return -ENODEV; + } + + ret =3D i2c_smbus_read_byte_data(sdata->client, S6SA552_BOOT_STATUS); + if (ret < 0) + return ret; + + /* for some reasons the device might be stuck in the bootloader */ + if (ret !=3D S6SA552_BS_APPLICATION) + return -ENODEV; + + /* enable touch functionality */ + ret =3D i2c_smbus_write_byte_data(sdata->client, + S6SA552_TOUCH_FUNCTION, 0x01); + if (ret) + return ret; + + mdelay(20); /* make sure everything is up */ + + return 0; +} + +static int s6sa552_hw_init(struct s6sa552_data *sdata) +{ + u8 buffer[S6SA552_DEVID_SIZE]; + int ret; + + ret =3D s6sa552_power_on(sdata); + if (ret) + return ret; + + ret =3D i2c_smbus_read_i2c_block_data(sdata->client, + S6SA552_DEVICE_ID, + S6SA552_DEVID_SIZE, + buffer); + if (ret < 0) + return ret; + + sdata->devid =3D get_unaligned_be16(buffer + 1); + + return 0; +} + +static void s6sa552_power_off(void *data) +{ + struct s6sa552_data *sdata =3D data; + + disable_irq(sdata->client->irq); + regulator_bulk_disable(ARRAY_SIZE(sdata->regulators), + sdata->regulators); +} + +static int s6sa552_probe(struct i2c_client *client) +{ + struct s6sa552_data *sdata; + int err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENODEV; + + sdata =3D devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL); + if (!sdata) + return -ENOMEM; + + i2c_set_clientdata(client, sdata); + sdata->client =3D client; + + sdata->regulators[S6SA552_REGULATOR_VDD].supply =3D "vdd"; + sdata->regulators[S6SA552_REGULATOR_AVDD].supply =3D "avdd"; + err =3D devm_regulator_bulk_get(&client->dev, + ARRAY_SIZE(sdata->regulators), + sdata->regulators); + if (err) + return err; + + err =3D devm_add_action_or_reset(&client->dev, s6sa552_power_off, sdata); + if (err) + return err; + + err =3D s6sa552_hw_init(sdata); + if (err) + return err; + + sdata->input =3D devm_input_allocate_device(&client->dev); + if (!sdata->input) + return -ENOMEM; + + sdata->input->name =3D S6SA552_DEV_NAME; + sdata->input->id.bustype =3D BUS_I2C; + sdata->input->open =3D s6sa552_input_open; + sdata->input->close =3D s6sa552_input_close; + + input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0, S6SA552_MAX_X, + 0, 0); + input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0, S6SA552_MAX_Y, + 0, 0); + input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0); + input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0); + + touchscreen_parse_properties(sdata->input, true, &sdata->prop); + + if (!input_abs_get_max(sdata->input, ABS_X) || + !input_abs_get_max(sdata->input, ABS_Y)) { + dev_warn(&client->dev, "the axis have not been set\n"); + } + + err =3D input_mt_init_slots(sdata->input, S6SA552_TX_CHANNELS, + INPUT_MT_DIRECT); + if (err) + return err; + + input_set_drvdata(sdata->input, sdata); + + err =3D input_register_device(sdata->input); + if (err) + return err; + + err =3D devm_request_threaded_irq(&client->dev, client->irq, NULL, + s6sa552_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "s6sa552_irq", sdata); + if (err) + return err; + + pm_runtime_enable(&client->dev); + + return 0; +} + +static void s6sa552_remove(struct i2c_client *client) +{ + pm_runtime_disable(&client->dev); +} + +static int s6sa552_runtime_suspend(struct device *dev) +{ + struct s6sa552_data *sdata =3D dev_get_drvdata(dev); + + return i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_OFF); +} + +static int s6sa552_runtime_resume(struct device *dev) +{ + struct s6sa552_data *sdata =3D dev_get_drvdata(dev); + + return i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_ON); +} + +static int s6sa552_suspend(struct device *dev) +{ + struct s6sa552_data *sdata =3D dev_get_drvdata(dev); + + s6sa552_power_off(sdata); + + return 0; +} + +static int s6sa552_resume(struct device *dev) +{ + struct s6sa552_data *sdata =3D dev_get_drvdata(dev); + + enable_irq(sdata->client->irq); + + return s6sa552_power_on(sdata); +} + +static const struct dev_pm_ops s6sa552_pm_ops =3D { + SYSTEM_SLEEP_PM_OPS(s6sa552_suspend, s6sa552_resume) + RUNTIME_PM_OPS(s6sa552_runtime_suspend, s6sa552_runtime_resume, NULL) +}; + +#ifdef CONFIG_OF +static const struct of_device_id s6sa552_of_match[] =3D { + { .compatible =3D "samsung,s6sa552", }, + { }, +}; +MODULE_DEVICE_TABLE(of, s6sa552_of_match); +#endif + +static const struct i2c_device_id s6sa552_id[] =3D { + { "s6sa552" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, s6sa552_id); + +static struct i2c_driver s6sa552_driver =3D { + .driver =3D { + .name =3D S6SA552_DEV_NAME, + .dev_groups =3D s6sa552_sysfs_groups, + .of_match_table =3D of_match_ptr(s6sa552_of_match), + .pm =3D pm_ptr(&s6sa552_pm_ops), + }, + .probe =3D s6sa552_probe, + .remove =3D s6sa552_remove, + .id_table =3D s6sa552_id, +}; + +module_i2c_driver(s6sa552_driver); + +MODULE_AUTHOR("Ivaylo Ivanov "); +MODULE_DESCRIPTION("Samsung S6SA552 Touch Screen"); +MODULE_LICENSE("GPL"); --=20 2.43.0