1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Ilitek ILI9806E core driver. 4 * 5 * Copyright (c) 2026 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com> 6 */ 7 8 #include <drm/drm_panel.h> 9 10 #include <linux/delay.h> 11 #include <linux/export.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/property.h> 16 #include <linux/regulator/consumer.h> 17 18 #include "panel-ilitek-ili9806e-core.h" 19 20 struct ili9806e { 21 void *transport; 22 struct drm_panel panel; 23 24 unsigned int num_supplies; 25 struct regulator_bulk_data supplies[2]; 26 struct gpio_desc *reset_gpio; 27 }; 28 29 void *ili9806e_get_transport(struct drm_panel *panel) 30 { 31 struct ili9806e *ctx = container_of(panel, struct ili9806e, panel); 32 33 return ctx->transport; 34 } 35 EXPORT_SYMBOL_GPL(ili9806e_get_transport); 36 37 int ili9806e_power_on(struct device *dev) 38 { 39 struct ili9806e *ctx = dev_get_drvdata(dev); 40 int ret; 41 42 gpiod_set_value(ctx->reset_gpio, 1); 43 44 ret = regulator_bulk_enable(ctx->num_supplies, ctx->supplies); 45 if (ret) { 46 dev_err(dev, "regulator bulk enable failed: %d\n", ret); 47 return ret; 48 } 49 50 usleep_range(10000, 20000); 51 gpiod_set_value(ctx->reset_gpio, 0); 52 usleep_range(10000, 20000); 53 54 return 0; 55 } 56 EXPORT_SYMBOL_GPL(ili9806e_power_on); 57 58 int ili9806e_power_off(struct device *dev) 59 { 60 struct ili9806e *ctx = dev_get_drvdata(dev); 61 int ret; 62 63 gpiod_set_value(ctx->reset_gpio, 1); 64 65 ret = regulator_bulk_disable(ctx->num_supplies, ctx->supplies); 66 if (ret) 67 dev_err(dev, "regulator bulk disable failed: %d\n", ret); 68 69 return ret; 70 } 71 EXPORT_SYMBOL_GPL(ili9806e_power_off); 72 73 int ili9806e_probe(struct device *dev, void *transport, 74 const struct drm_panel_funcs *funcs, 75 int connector_type) 76 { 77 struct ili9806e *ctx; 78 bool set_prepare_prev_first = false; 79 int ret; 80 81 ctx = devm_drm_panel_alloc(dev, __typeof(*ctx), panel, 82 funcs, connector_type); 83 84 if (IS_ERR(ctx)) 85 return PTR_ERR(ctx); 86 87 dev_set_drvdata(dev, ctx); 88 ctx->transport = transport; 89 90 ctx->supplies[ctx->num_supplies++].supply = "vdd"; 91 if (of_device_is_compatible(dev->of_node, 92 "densitron,dmt028vghmcmi-1d") || 93 of_device_is_compatible(dev->of_node, 94 "ortustech,com35h3p70ulc")) { 95 ctx->supplies[ctx->num_supplies++].supply = "vccio"; 96 set_prepare_prev_first = true; 97 } 98 99 ret = devm_regulator_bulk_get(dev, ctx->num_supplies, ctx->supplies); 100 if (ret) 101 return dev_err_probe(dev, ret, "failed to get regulators\n"); 102 103 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 104 if (IS_ERR(ctx->reset_gpio)) 105 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 106 "Failed to get reset-gpios\n"); 107 108 ret = drm_panel_of_backlight(&ctx->panel); 109 if (ret) 110 return dev_err_probe(dev, ret, "Failed to get backlight\n"); 111 112 if (set_prepare_prev_first) 113 ctx->panel.prepare_prev_first = true; 114 115 drm_panel_add(&ctx->panel); 116 117 return 0; 118 119 } 120 EXPORT_SYMBOL_GPL(ili9806e_probe); 121 122 void ili9806e_remove(struct device *dev) 123 { 124 struct ili9806e *ctx = dev_get_drvdata(dev); 125 126 drm_panel_remove(&ctx->panel); 127 } 128 EXPORT_SYMBOL_GPL(ili9806e_remove); 129 130 MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>"); 131 MODULE_AUTHOR("Gunnar Dibbern <gunnar.dibbern@lht.dlh.de>"); 132 MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>"); 133 MODULE_DESCRIPTION("Ilitek ILI9806E Controller Driver"); 134 MODULE_LICENSE("GPL"); 135