1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for Sitronix ST7571 connected via I2C bus. 4 * 5 * Copyright (C) 2025 Marcus Folkesson <marcus.folkesson@gmail.com> 6 */ 7 8 #include <linux/i2c.h> 9 #include <linux/module.h> 10 #include <linux/regmap.h> 11 12 #include "st7571.h" 13 14 struct st7571_i2c_transport { 15 struct i2c_client *client; 16 17 /* 18 * Depending on the hardware design, the acknowledge signal may be hard to 19 * recognize as a valid logic "0" level. 20 * Therefor, ignore NAK if possible to stay compatible with most hardware designs 21 * and off-the-shelf panels out there. 22 * 23 * From section 6.4 MICROPOCESSOR INTERFACE section in the datasheet: 24 * 25 * "By connecting SDA_OUT to SDA_IN externally, the SDA line becomes fully 26 * I2C interface compatible. 27 * Separating acknowledge-output from serial data 28 * input is advantageous for chip-on-glass (COG) applications. In COG 29 * applications, the ITO resistance and the pull-up resistor will form a 30 * voltage divider, which affects acknowledge-signal level. Larger ITO 31 * resistance will raise the acknowledged-signal level and system cannot 32 * recognize this level as a valid logic “0” level. By separating SDA_IN from 33 * SDA_OUT, the IC can be used in a mode that ignores the acknowledge-bit. 34 * For applications which check acknowledge-bit, it is necessary to minimize 35 * the ITO resistance of the SDA_OUT trace to guarantee a valid low level." 36 * 37 */ 38 bool ignore_nak; 39 }; 40 41 static int st7571_i2c_regmap_write(void *context, const void *data, size_t count) 42 { 43 struct st7571_i2c_transport *t = context; 44 int ret; 45 46 struct i2c_msg msg = { 47 .addr = t->client->addr, 48 .flags = t->ignore_nak ? I2C_M_IGNORE_NAK : 0, 49 .len = count, 50 .buf = (u8 *)data 51 }; 52 53 ret = i2c_transfer(t->client->adapter, &msg, 1); 54 55 /* 56 * Unfortunately, there is no way to check if the transfer failed because of 57 * a NAK or something else as I2C bus drivers use different return values for NAK. 58 * 59 * However, if the transfer fails and ignore_nak is set, we know it is an error. 60 */ 61 if (ret < 0 && t->ignore_nak) 62 return ret; 63 64 return 0; 65 } 66 67 /* The st7571 driver does not read registers but regmap expects a .read */ 68 static int st7571_i2c_regmap_read(void *context, const void *reg_buf, 69 size_t reg_size, void *val_buf, size_t val_size) 70 { 71 return -EOPNOTSUPP; 72 } 73 74 static const struct regmap_bus st7571_i2c_regmap_bus = { 75 .read = st7571_i2c_regmap_read, 76 .write = st7571_i2c_regmap_write, 77 }; 78 79 static const struct regmap_config st7571_i2c_regmap_config = { 80 .reg_bits = 8, 81 .val_bits = 8, 82 .use_single_write = true, 83 }; 84 85 static int st7571_i2c_probe(struct i2c_client *client) 86 { 87 struct st7571_device *st7571; 88 struct st7571_i2c_transport *t; 89 struct regmap *regmap; 90 91 t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); 92 if (!t) 93 return -ENOMEM; 94 95 t->client = client; 96 97 /* 98 * The hardware design could make it hard to detect a NAK on the I2C bus. 99 * If the adapter does not support protocol mangling do 100 * not set the I2C_M_IGNORE_NAK flag at the expense * of possible 101 * cruft in the logs. 102 */ 103 if (i2c_check_functionality(client->adapter, I2C_FUNC_PROTOCOL_MANGLING)) 104 t->ignore_nak = true; 105 106 regmap = devm_regmap_init(&client->dev, &st7571_i2c_regmap_bus, 107 t, &st7571_i2c_regmap_config); 108 if (IS_ERR(regmap)) { 109 return dev_err_probe(&client->dev, PTR_ERR(regmap), 110 "Failed to initialize regmap\n"); 111 } 112 113 st7571 = st7571_probe(&client->dev, regmap); 114 if (IS_ERR(st7571)) 115 return dev_err_probe(&client->dev, PTR_ERR(st7571), 116 "Failed to initialize regmap\n"); 117 118 i2c_set_clientdata(client, st7571); 119 return 0; 120 } 121 122 static void st7571_i2c_remove(struct i2c_client *client) 123 { 124 struct st7571_device *st7571 = i2c_get_clientdata(client); 125 126 st7571_remove(st7571); 127 } 128 129 static const struct of_device_id st7571_of_match[] = { 130 { .compatible = "sitronix,st7567", .data = &st7567_config }, 131 { .compatible = "sitronix,st7571", .data = &st7571_config }, 132 {}, 133 }; 134 MODULE_DEVICE_TABLE(of, st7571_of_match); 135 136 static const struct i2c_device_id st7571_id[] = { 137 { "st7567", 0 }, 138 { "st7571", 0 }, 139 { } 140 }; 141 MODULE_DEVICE_TABLE(i2c, st7571_id); 142 143 static struct i2c_driver st7571_i2c_driver = { 144 .driver = { 145 .name = "st7571-i2c", 146 .of_match_table = st7571_of_match, 147 }, 148 .probe = st7571_i2c_probe, 149 .remove = st7571_i2c_remove, 150 .id_table = st7571_id, 151 }; 152 153 module_i2c_driver(st7571_i2c_driver); 154 155 MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>"); 156 MODULE_DESCRIPTION("DRM Driver for Sitronix ST7571 LCD controller (I2C)"); 157 MODULE_LICENSE("GPL"); 158 MODULE_IMPORT_NS("DRM_ST7571"); 159