1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2024 Waveshare International Limited 4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 5 */ 6 7 #include <linux/delay.h> 8 #include <linux/device.h> 9 #include <linux/err.h> 10 #include <linux/errno.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 15 #include <linux/gpio/consumer.h> 16 #include <linux/regulator/consumer.h> 17 18 #include <drm/drm_mipi_dsi.h> 19 #include <drm/drm_modes.h> 20 #include <drm/drm_panel.h> 21 #include <drm/drm_probe_helper.h> 22 23 struct ota7290b { 24 struct drm_panel panel; 25 struct mipi_dsi_device *dsi; 26 27 struct regulator *power; 28 struct gpio_desc *reset; 29 struct regulator *avdd; 30 struct regulator *vdd; 31 struct regulator *vcc; 32 33 enum drm_panel_orientation orientation; 34 }; 35 36 static inline struct ota7290b *panel_to_ota(struct drm_panel *panel) 37 { 38 return container_of(panel, struct ota7290b, panel); 39 } 40 41 static int ota7290b_prepare(struct drm_panel *panel) 42 { 43 struct ota7290b *ctx = panel_to_ota(panel); 44 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 45 int ret; 46 47 if (ctx->vcc) { 48 ret = regulator_enable(ctx->vcc); 49 if (ret) 50 dev_err(panel->dev, "failed to enable VCC regulator: %d\n", ret); 51 } 52 53 if (ctx->reset) { 54 gpiod_set_value_cansleep(ctx->reset, 0); 55 msleep(60); 56 gpiod_set_value_cansleep(ctx->reset, 1); 57 msleep(60); 58 } 59 60 if (ctx->vdd) { 61 ret = regulator_enable(ctx->vdd); 62 if (ret) 63 dev_err(panel->dev, "failed to enable VDD regulator: %d\n", ret); 64 } 65 66 if (ctx->reset) { 67 gpiod_set_value_cansleep(ctx->reset, 0); 68 msleep(60); 69 } 70 71 if (ctx->avdd) { 72 ret = regulator_enable(ctx->avdd); 73 if (ret) 74 dev_err(panel->dev, "failed to enable AVDD regulator: %d\n", ret); 75 } 76 77 mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 78 mipi_dsi_msleep(&dsi_ctx, 120); 79 mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 80 mipi_dsi_msleep(&dsi_ctx, 50); 81 82 if (dsi_ctx.accum_err < 0) 83 dev_err(panel->dev, "failed to init panel: %d\n", dsi_ctx.accum_err); 84 85 return dsi_ctx.accum_err; 86 } 87 88 static int ota7290b_unprepare(struct drm_panel *panel) 89 { 90 struct ota7290b *ctx = panel_to_ota(panel); 91 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 92 93 mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 94 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 95 96 if (ctx->avdd) 97 regulator_disable(ctx->avdd); 98 99 if (ctx->reset) { 100 gpiod_set_value_cansleep(ctx->reset, 1); 101 msleep(5); 102 } 103 104 if (ctx->vdd) 105 regulator_disable(ctx->vdd); 106 107 if (ctx->vcc) 108 regulator_disable(ctx->vcc); 109 110 return 0; 111 } 112 113 static const struct drm_display_mode waveshare_dsi_touch_8_8_a_mode = { 114 .clock = 75000, 115 116 .hdisplay = 480, 117 .hsync_start = 480 + 50, 118 .hsync_end = 480 + 50 + 50, 119 .htotal = 480 + 50 + 50 + 50, 120 121 .vdisplay = 1920, 122 .vsync_start = 1920 + 20, 123 .vsync_end = 1920 + 20 + 20, 124 .vtotal = 1920 + 20 + 20 + 20, 125 126 .width_mm = 68, 127 .height_mm = 219, 128 .type = DRM_MODE_TYPE_DRIVER, 129 }; 130 131 static int ota7290b_get_modes(struct drm_panel *panel, 132 struct drm_connector *connector) 133 { 134 return drm_connector_helper_get_modes_fixed(connector, &waveshare_dsi_touch_8_8_a_mode); 135 } 136 137 static enum drm_panel_orientation ota7290b_get_orientation(struct drm_panel *panel) 138 { 139 struct ota7290b *ctx = panel_to_ota(panel); 140 141 return ctx->orientation; 142 } 143 144 static const struct drm_panel_funcs ota7290b_funcs = { 145 .prepare = ota7290b_prepare, 146 .unprepare = ota7290b_unprepare, 147 .get_modes = ota7290b_get_modes, 148 .get_orientation = ota7290b_get_orientation, 149 }; 150 151 static int ota7290b_probe(struct mipi_dsi_device *dsi) 152 { 153 struct ota7290b *ctx; 154 int ret; 155 156 ctx = devm_drm_panel_alloc(&dsi->dev, struct ota7290b, panel, 157 &ota7290b_funcs, 158 DRM_MODE_CONNECTOR_DSI); 159 if (IS_ERR(ctx)) 160 return PTR_ERR(ctx); 161 mipi_dsi_set_drvdata(dsi, ctx); 162 ctx->dsi = dsi; 163 164 ctx->reset = devm_gpiod_get_optional(&dsi->dev, "reset", GPIOD_OUT_HIGH); 165 if (IS_ERR(ctx->reset)) 166 return dev_err_probe(&dsi->dev, PTR_ERR(ctx->reset), 167 "Couldn't get our reset GPIO\n"); 168 169 ctx->vcc = devm_regulator_get_optional(&dsi->dev, "vcc"); 170 if (IS_ERR(ctx->vcc)) 171 return dev_err_probe(&dsi->dev, PTR_ERR(ctx->vcc), 172 "Couldn't get our VCC supply\n"); 173 174 ctx->avdd = devm_regulator_get_optional(&dsi->dev, "avdd"); 175 if (IS_ERR(ctx->avdd)) 176 return dev_err_probe(&dsi->dev, PTR_ERR(ctx->avdd), 177 "Couldn't get our AVDD supply\n"); 178 179 ctx->vdd = devm_regulator_get_optional(&dsi->dev, "vdd"); 180 if (IS_ERR(ctx->vdd)) 181 return dev_err_probe(&dsi->dev, PTR_ERR(ctx->vdd), 182 "Couldn't get our VDD supply\n"); 183 184 ret = of_drm_get_panel_orientation(dsi->dev.of_node, &ctx->orientation); 185 if (ret) { 186 dev_err(&dsi->dev, "%pOF: failed to get orientation: %d\n", 187 dsi->dev.of_node, ret); 188 return ret; 189 } 190 191 ret = drm_panel_of_backlight(&ctx->panel); 192 if (ret) 193 return ret; 194 195 ctx->panel.prepare_prev_first = true; 196 197 ret = devm_drm_panel_add(&dsi->dev, &ctx->panel); 198 if (ret) 199 return ret; 200 201 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_HSE | 202 MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS, 203 dsi->format = MIPI_DSI_FMT_RGB888, 204 dsi->lanes = 2; 205 206 return devm_mipi_dsi_attach(&dsi->dev, dsi); 207 } 208 209 static const struct of_device_id ota7290b_of_match[] = { 210 { .compatible = "waveshare,8.8-dsi-touch-a", }, 211 {} 212 }; 213 MODULE_DEVICE_TABLE(of, ota7290b_of_match); 214 215 static struct mipi_dsi_driver ota7290b_driver = { 216 .probe = ota7290b_probe, 217 .driver = { 218 .name = "focaltech-ota7290b", 219 .of_match_table = ota7290b_of_match, 220 }, 221 }; 222 module_mipi_dsi_driver(ota7290b_driver); 223 224 MODULE_DESCRIPTION("Panel driver for Focaltech OTA7290B panels"); 225 MODULE_LICENSE("GPL"); 226