[PATCH 2/3] Input: himax_hx83112b - Add HX83112A support

From: Luca Weiss

Date: Fri Aug 21 2026 - 03:12:41 EST


The HX83112A touch controller works nearly identical to other supported
chips, we just need a small dance before we can start using the
touchscreen.

For that a new 'init' callback is introduced to facilitate that.

Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Luca Weiss <luca.weiss@xxxxxxxxxxxxx>
---
drivers/input/touchscreen/himax_hx83112b.c | 46 ++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)

diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c
index 0aa67dfacbad..cc8b904d88e6 100644
--- a/drivers/input/touchscreen/himax_hx83112b.c
+++ b/drivers/input/touchscreen/himax_hx83112b.c
@@ -62,6 +62,7 @@ struct himax_ts_data;
struct himax_chip {
u32 id;
int (*check_id)(struct himax_ts_data *ts);
+ int (*init)(struct himax_ts_data *ts);
int (*read_events)(struct himax_ts_data *ts, struct himax_event *event,
size_t length);
};
@@ -364,6 +365,12 @@ static int himax_probe(struct i2c_client *client)
return error;
}

+ if (ts->chip->init) {
+ error = ts->chip->init(ts);
+ if (error)
+ return error;
+ }
+
error = himax_input_register(ts);
if (error)
return error;
@@ -395,10 +402,47 @@ static int himax_resume(struct device *dev)

static DEFINE_SIMPLE_DEV_PM_OPS(himax_pm_ops, himax_suspend, himax_resume);

+static int hx83112a_init(struct himax_ts_data *ts)
+{
+ int error;
+ u32 buf[2];
+
+ /*
+ * By default, the chip boots into safe mode. We clear the FW ISR
+ * register and perform a second hardware reset to boot normally.
+ */
+ buf[0] = 0x9000005c;
+ buf[1] = 0x00000000;
+ error = regmap_bulk_write(ts->regmap, HIMAX_AHB_ADDR_BYTE_0, buf, 2);
+ if (error)
+ return error;
+
+ himax_reset(ts);
+
+ /* Give the MCU time to reload firmware */
+ msleep(100);
+
+ /* Enable the touch algorithm */
+ buf[0] = 0x1000748c;
+ buf[1] = 0xa55aa55a;
+ error = regmap_bulk_write(ts->regmap, HIMAX_AHB_ADDR_BYTE_0, buf, 2);
+ if (error)
+ return error;
+
+ return 0;
+}
+
static const struct himax_chip hx83100a_chip = {
.read_events = hx83100a_read_events,
};

+static const struct himax_chip hx83112a_chip = {
+ .id = 0x83112a,
+ .check_id = himax_check_product_id,
+ .init = hx83112a_init,
+ .read_events = himax_read_events,
+};
+
static const struct himax_chip hx83112b_chip = {
.id = 0x83112b,
.check_id = himax_check_product_id,
@@ -407,6 +451,7 @@ static const struct himax_chip hx83112b_chip = {

static const struct i2c_device_id himax_ts_id[] = {
{ .name = "hx83100a", .driver_data = (kernel_ulong_t)&hx83100a_chip },
+ { .name = "hx83112a", .driver_data = (kernel_ulong_t)&hx83112a_chip },
{ .name = "hx83112b", .driver_data = (kernel_ulong_t)&hx83112b_chip },
{ /* sentinel */ }
};
@@ -415,6 +460,7 @@ MODULE_DEVICE_TABLE(i2c, himax_ts_id);
#ifdef CONFIG_OF
static const struct of_device_id himax_of_match[] = {
{ .compatible = "himax,hx83100a", .data = &hx83100a_chip },
+ { .compatible = "himax,hx83112a", .data = &hx83112a_chip },
{ .compatible = "himax,hx83112b", .data = &hx83112b_chip },
{ /* sentinel */ }
};

--
2.55.0