1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AU Optronics A030JTN01.0 TFT LCD panel driver 4 * 5 * Copyright (C) 2023, Paul Cercueil <paul@crapouillou.net> 6 * Copyright (C) 2023, Christophe Branchereau <cbranchereau@gmail.com> 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/delay.h> 11 #include <linux/device.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/media-bus-format.h> 14 #include <linux/module.h> 15 #include <linux/regmap.h> 16 #include <linux/regulator/consumer.h> 17 #include <linux/spi/spi.h> 18 19 #include <drm/drm_modes.h> 20 #include <drm/drm_panel.h> 21 22 #define REG05 0x05 23 #define REG06 0x06 24 #define REG07 0x07 25 26 #define REG05_STDBY BIT(0) 27 #define REG06_VBLK GENMASK(4, 0) 28 #define REG07_HBLK GENMASK(7, 0) 29 30 31 struct a030jtn01_info { 32 const struct drm_display_mode *display_modes; 33 unsigned int num_modes; 34 u16 width_mm, height_mm; 35 u32 bus_format, bus_flags; 36 }; 37 38 struct a030jtn01 { 39 struct drm_panel panel; 40 struct spi_device *spi; 41 struct regmap *map; 42 43 const struct a030jtn01_info *panel_info; 44 45 struct regulator *supply; 46 struct gpio_desc *reset_gpio; 47 }; 48 49 static inline struct a030jtn01 *to_a030jtn01(struct drm_panel *panel) 50 { 51 return container_of(panel, struct a030jtn01, panel); 52 } 53 54 static int a030jtn01_prepare(struct drm_panel *panel) 55 { 56 struct a030jtn01 *priv = to_a030jtn01(panel); 57 struct device *dev = &priv->spi->dev; 58 unsigned int dummy; 59 int err; 60 61 err = regulator_enable(priv->supply); 62 if (err) { 63 dev_err(dev, "Failed to enable power supply: %d\n", err); 64 return err; 65 } 66 67 usleep_range(1000, 8000); 68 69 /* Reset the chip */ 70 gpiod_set_value_cansleep(priv->reset_gpio, 1); 71 usleep_range(100, 8000); 72 gpiod_set_value_cansleep(priv->reset_gpio, 0); 73 usleep_range(2000, 8000); 74 75 /* 76 * No idea why, but a register read (doesn't matter which) is needed to 77 * properly initialize the chip after a reset; otherwise, the colors 78 * will be wrong. It doesn't seem to be timing-related as a msleep(200) 79 * doesn't fix it. 80 */ 81 err = regmap_read(priv->map, REG05, &dummy); 82 if (err) 83 goto err_disable_regulator; 84 85 /* Use (24 + 6) == 0x1e as the vertical back porch */ 86 err = regmap_write(priv->map, REG06, FIELD_PREP(REG06_VBLK, 0x1e)); 87 if (err) 88 goto err_disable_regulator; 89 90 /* Use (42 + 30) * 3 == 0xd8 as the horizontal back porch */ 91 err = regmap_write(priv->map, REG07, FIELD_PREP(REG07_HBLK, 0xd8)); 92 if (err) 93 goto err_disable_regulator; 94 95 return 0; 96 97 err_disable_regulator: 98 gpiod_set_value_cansleep(priv->reset_gpio, 1); 99 regulator_disable(priv->supply); 100 return err; 101 } 102 103 static int a030jtn01_unprepare(struct drm_panel *panel) 104 { 105 struct a030jtn01 *priv = to_a030jtn01(panel); 106 107 gpiod_set_value_cansleep(priv->reset_gpio, 1); 108 regulator_disable(priv->supply); 109 110 return 0; 111 } 112 113 static int a030jtn01_enable(struct drm_panel *panel) 114 { 115 struct a030jtn01 *priv = to_a030jtn01(panel); 116 int ret; 117 118 ret = regmap_set_bits(priv->map, REG05, REG05_STDBY); 119 if (ret) 120 return ret; 121 122 /* Wait for the picture to be stable */ 123 if (panel->backlight) 124 msleep(100); 125 126 return 0; 127 } 128 129 static int a030jtn01_disable(struct drm_panel *panel) 130 { 131 struct a030jtn01 *priv = to_a030jtn01(panel); 132 133 return regmap_clear_bits(priv->map, REG05, REG05_STDBY); 134 } 135 136 static int a030jtn01_get_modes(struct drm_panel *panel, 137 struct drm_connector *connector) 138 { 139 struct a030jtn01 *priv = to_a030jtn01(panel); 140 const struct a030jtn01_info *panel_info = priv->panel_info; 141 struct drm_display_mode *mode; 142 unsigned int i; 143 144 for (i = 0; i < panel_info->num_modes; i++) { 145 mode = drm_mode_duplicate(connector->dev, 146 &panel_info->display_modes[i]); 147 if (!mode) 148 return -ENOMEM; 149 150 drm_mode_set_name(mode); 151 152 mode->type = DRM_MODE_TYPE_DRIVER; 153 if (panel_info->num_modes == 1) 154 mode->type |= DRM_MODE_TYPE_PREFERRED; 155 156 drm_mode_probed_add(connector, mode); 157 } 158 159 connector->display_info.bpc = 8; 160 connector->display_info.width_mm = panel_info->width_mm; 161 connector->display_info.height_mm = panel_info->height_mm; 162 163 drm_display_info_set_bus_formats(&connector->display_info, 164 &panel_info->bus_format, 1); 165 connector->display_info.bus_flags = panel_info->bus_flags; 166 167 return panel_info->num_modes; 168 } 169 170 static const struct drm_panel_funcs a030jtn01_funcs = { 171 .prepare = a030jtn01_prepare, 172 .unprepare = a030jtn01_unprepare, 173 .enable = a030jtn01_enable, 174 .disable = a030jtn01_disable, 175 .get_modes = a030jtn01_get_modes, 176 }; 177 178 static bool a030jtn01_has_reg(struct device *dev, unsigned int reg) 179 { 180 static const u32 a030jtn01_regs_mask = 0x001823f1fb; 181 182 return a030jtn01_regs_mask & BIT(reg); 183 }; 184 185 static const struct regmap_config a030jtn01_regmap_config = { 186 .reg_bits = 8, 187 .val_bits = 8, 188 .read_flag_mask = 0x40, 189 .max_register = 0x1c, 190 .readable_reg = a030jtn01_has_reg, 191 .writeable_reg = a030jtn01_has_reg, 192 }; 193 194 static int a030jtn01_probe(struct spi_device *spi) 195 { 196 struct device *dev = &spi->dev; 197 struct a030jtn01 *priv; 198 int err; 199 200 spi->mode |= SPI_MODE_3 | SPI_3WIRE; 201 202 priv = devm_drm_panel_alloc(dev, struct a030jtn01, panel, 203 &a030jtn01_funcs, DRM_MODE_CONNECTOR_DPI); 204 if (IS_ERR(priv)) 205 return PTR_ERR(priv); 206 207 priv->spi = spi; 208 spi_set_drvdata(spi, priv); 209 210 priv->map = devm_regmap_init_spi(spi, &a030jtn01_regmap_config); 211 if (IS_ERR(priv->map)) 212 return dev_err_probe(dev, PTR_ERR(priv->map), "Unable to init regmap"); 213 214 priv->panel_info = spi_get_device_match_data(spi); 215 if (!priv->panel_info) 216 return -EINVAL; 217 218 priv->supply = devm_regulator_get(dev, "power"); 219 if (IS_ERR(priv->supply)) 220 return dev_err_probe(dev, PTR_ERR(priv->supply), "Failed to get power supply"); 221 222 priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 223 if (IS_ERR(priv->reset_gpio)) 224 return dev_err_probe(dev, PTR_ERR(priv->reset_gpio), "Failed to get reset GPIO"); 225 226 err = drm_panel_of_backlight(&priv->panel); 227 if (err) 228 return err; 229 230 drm_panel_add(&priv->panel); 231 232 return 0; 233 } 234 235 static void a030jtn01_remove(struct spi_device *spi) 236 { 237 struct a030jtn01 *priv = spi_get_drvdata(spi); 238 239 drm_panel_remove(&priv->panel); 240 drm_panel_disable(&priv->panel); 241 drm_panel_unprepare(&priv->panel); 242 } 243 244 static const struct drm_display_mode a030jtn01_modes[] = { 245 { /* 60 Hz */ 246 .clock = 14400, 247 .hdisplay = 320, 248 .hsync_start = 320 + 8, 249 .hsync_end = 320 + 8 + 42, 250 .htotal = 320 + 8 + 42 + 30, 251 .vdisplay = 480, 252 .vsync_start = 480 + 90, 253 .vsync_end = 480 + 90 + 24, 254 .vtotal = 480 + 90 + 24 + 6, 255 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 256 }, 257 { /* 50 Hz */ 258 .clock = 12000, 259 .hdisplay = 320, 260 .hsync_start = 320 + 8, 261 .hsync_end = 320 + 8 + 42, 262 .htotal = 320 + 8 + 42 + 30, 263 .vdisplay = 480, 264 .vsync_start = 480 + 90, 265 .vsync_end = 480 + 90 + 24, 266 .vtotal = 480 + 90 + 24 + 6, 267 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 268 }, 269 }; 270 271 static const struct a030jtn01_info a030jtn01_info = { 272 .display_modes = a030jtn01_modes, 273 .num_modes = ARRAY_SIZE(a030jtn01_modes), 274 .width_mm = 70, 275 .height_mm = 51, 276 .bus_format = MEDIA_BUS_FMT_RGB888_3X8_DELTA, 277 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, 278 }; 279 280 static const struct spi_device_id a030jtn01_id[] = { 281 { "a030jtn01", (kernel_ulong_t) &a030jtn01_info }, 282 { /* sentinel */ } 283 }; 284 MODULE_DEVICE_TABLE(spi, a030jtn01_id); 285 286 static const struct of_device_id a030jtn01_of_match[] = { 287 { .compatible = "auo,a030jtn01" }, 288 { /* sentinel */ } 289 }; 290 MODULE_DEVICE_TABLE(of, a030jtn01_of_match); 291 292 static struct spi_driver a030jtn01_driver = { 293 .driver = { 294 .name = "auo-a030jtn01", 295 .of_match_table = a030jtn01_of_match, 296 }, 297 .id_table = a030jtn01_id, 298 .probe = a030jtn01_probe, 299 .remove = a030jtn01_remove, 300 }; 301 module_spi_driver(a030jtn01_driver); 302 303 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); 304 MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); 305 MODULE_DESCRIPTION("AU Optronics A030JTN01.0 TFT LCD panel driver"); 306 MODULE_LICENSE("GPL"); 307