1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/delay.h> 7 #include <linux/module.h> 8 #include <linux/of_device.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/regulator/consumer.h> 11 12 #include <video/mipi_display.h> 13 14 #include <drm/drm_mipi_dsi.h> 15 #include <drm/drm_modes.h> 16 #include <drm/drm_panel.h> 17 #include <drm/drm_print.h> 18 19 struct visionox_rm69299 { 20 struct drm_panel panel; 21 struct regulator_bulk_data supplies[2]; 22 struct gpio_desc *reset_gpio; 23 struct mipi_dsi_device *dsi; 24 bool prepared; 25 bool enabled; 26 }; 27 28 static inline struct visionox_rm69299 *panel_to_ctx(struct drm_panel *panel) 29 { 30 return container_of(panel, struct visionox_rm69299, panel); 31 } 32 33 static int visionox_rm69299_power_on(struct visionox_rm69299 *ctx) 34 { 35 int ret; 36 37 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 38 if (ret < 0) 39 return ret; 40 41 /* 42 * Reset sequence of visionox panel requires the panel to be 43 * out of reset for 10ms, followed by being held in reset 44 * for 10ms and then out again 45 */ 46 gpiod_set_value(ctx->reset_gpio, 1); 47 usleep_range(10000, 20000); 48 gpiod_set_value(ctx->reset_gpio, 0); 49 usleep_range(10000, 20000); 50 gpiod_set_value(ctx->reset_gpio, 1); 51 usleep_range(10000, 20000); 52 53 return 0; 54 } 55 56 static int visionox_rm69299_power_off(struct visionox_rm69299 *ctx) 57 { 58 gpiod_set_value(ctx->reset_gpio, 0); 59 60 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 61 } 62 63 static int visionox_rm69299_unprepare(struct drm_panel *panel) 64 { 65 struct visionox_rm69299 *ctx = panel_to_ctx(panel); 66 int ret; 67 68 ctx->dsi->mode_flags = 0; 69 70 ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0); 71 if (ret < 0) 72 DRM_DEV_ERROR(ctx->panel.dev, 73 "set_display_off cmd failed ret = %d\n", ret); 74 75 /* 120ms delay required here as per DCS spec */ 76 msleep(120); 77 78 ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0); 79 if (ret < 0) { 80 DRM_DEV_ERROR(ctx->panel.dev, 81 "enter_sleep cmd failed ret = %d\n", ret); 82 } 83 84 ret = visionox_rm69299_power_off(ctx); 85 86 ctx->prepared = false; 87 return ret; 88 } 89 90 static int visionox_rm69299_prepare(struct drm_panel *panel) 91 { 92 struct visionox_rm69299 *ctx = panel_to_ctx(panel); 93 int ret; 94 95 if (ctx->prepared) 96 return 0; 97 98 ret = visionox_rm69299_power_on(ctx); 99 if (ret < 0) 100 return ret; 101 102 ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; 103 104 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0xfe, 0x00 }, 2); 105 if (ret < 0) { 106 DRM_DEV_ERROR(ctx->panel.dev, 107 "cmd set tx 0 failed, ret = %d\n", ret); 108 goto power_off; 109 } 110 111 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0xc2, 0x08 }, 2); 112 if (ret < 0) { 113 DRM_DEV_ERROR(ctx->panel.dev, 114 "cmd set tx 1 failed, ret = %d\n", ret); 115 goto power_off; 116 } 117 118 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0x35, 0x00 }, 2); 119 if (ret < 0) { 120 DRM_DEV_ERROR(ctx->panel.dev, 121 "cmd set tx 2 failed, ret = %d\n", ret); 122 goto power_off; 123 } 124 125 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0x51, 0xff }, 2); 126 if (ret < 0) { 127 DRM_DEV_ERROR(ctx->panel.dev, 128 "cmd set tx 3 failed, ret = %d\n", ret); 129 goto power_off; 130 } 131 132 ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); 133 if (ret < 0) { 134 DRM_DEV_ERROR(ctx->panel.dev, 135 "exit_sleep_mode cmd failed ret = %d\n", ret); 136 goto power_off; 137 } 138 139 /* Per DSI spec wait 120ms after sending exit sleep DCS command */ 140 msleep(120); 141 142 ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0); 143 if (ret < 0) { 144 DRM_DEV_ERROR(ctx->panel.dev, 145 "set_display_on cmd failed ret = %d\n", ret); 146 goto power_off; 147 } 148 149 /* Per DSI spec wait 120ms after sending set_display_on DCS command */ 150 msleep(120); 151 152 ctx->prepared = true; 153 154 return 0; 155 156 power_off: 157 return ret; 158 } 159 160 static const struct drm_display_mode visionox_rm69299_1080x2248_60hz = { 161 .name = "1080x2248", 162 .clock = 158695, 163 .hdisplay = 1080, 164 .hsync_start = 1080 + 26, 165 .hsync_end = 1080 + 26 + 2, 166 .htotal = 1080 + 26 + 2 + 36, 167 .vdisplay = 2248, 168 .vsync_start = 2248 + 56, 169 .vsync_end = 2248 + 56 + 4, 170 .vtotal = 2248 + 56 + 4 + 4, 171 .vrefresh = 60, 172 .flags = 0, 173 }; 174 175 static int visionox_rm69299_get_modes(struct drm_panel *panel, 176 struct drm_connector *connector) 177 { 178 struct visionox_rm69299 *ctx = panel_to_ctx(panel); 179 struct drm_display_mode *mode; 180 181 mode = drm_mode_create(connector->dev); 182 if (!mode) { 183 DRM_DEV_ERROR(ctx->panel.dev, 184 "failed to create a new display mode\n"); 185 return 0; 186 } 187 188 connector->display_info.width_mm = 74; 189 connector->display_info.height_mm = 131; 190 drm_mode_copy(mode, &visionox_rm69299_1080x2248_60hz); 191 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 192 drm_mode_probed_add(connector, mode); 193 194 return 1; 195 } 196 197 static const struct drm_panel_funcs visionox_rm69299_drm_funcs = { 198 .unprepare = visionox_rm69299_unprepare, 199 .prepare = visionox_rm69299_prepare, 200 .get_modes = visionox_rm69299_get_modes, 201 }; 202 203 static int visionox_rm69299_probe(struct mipi_dsi_device *dsi) 204 { 205 struct device *dev = &dsi->dev; 206 struct visionox_rm69299 *ctx; 207 int ret; 208 209 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 210 if (!ctx) 211 return -ENOMEM; 212 213 mipi_dsi_set_drvdata(dsi, ctx); 214 215 ctx->panel.dev = dev; 216 ctx->dsi = dsi; 217 218 ctx->supplies[0].supply = "vdda"; 219 ctx->supplies[1].supply = "vdd3p3"; 220 221 ret = devm_regulator_bulk_get(ctx->panel.dev, ARRAY_SIZE(ctx->supplies), 222 ctx->supplies); 223 if (ret < 0) 224 return ret; 225 226 ctx->reset_gpio = devm_gpiod_get(ctx->panel.dev, 227 "reset", GPIOD_OUT_LOW); 228 if (IS_ERR(ctx->reset_gpio)) { 229 DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n", 230 PTR_ERR(ctx->reset_gpio)); 231 return PTR_ERR(ctx->reset_gpio); 232 } 233 234 drm_panel_init(&ctx->panel, dev, &visionox_rm69299_drm_funcs, 235 DRM_MODE_CONNECTOR_DSI); 236 ctx->panel.dev = dev; 237 ctx->panel.funcs = &visionox_rm69299_drm_funcs; 238 drm_panel_add(&ctx->panel); 239 240 dsi->lanes = 4; 241 dsi->format = MIPI_DSI_FMT_RGB888; 242 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | 243 MIPI_DSI_CLOCK_NON_CONTINUOUS; 244 ret = mipi_dsi_attach(dsi); 245 if (ret < 0) { 246 DRM_DEV_ERROR(dev, "dsi attach failed ret = %d\n", ret); 247 goto err_dsi_attach; 248 } 249 250 ret = regulator_set_load(ctx->supplies[0].consumer, 32000); 251 if (ret) { 252 DRM_DEV_ERROR(dev, 253 "regulator set load failed for vdda supply ret = %d\n", 254 ret); 255 goto err_set_load; 256 } 257 258 ret = regulator_set_load(ctx->supplies[1].consumer, 13200); 259 if (ret) { 260 DRM_DEV_ERROR(dev, 261 "regulator set load failed for vdd3p3 supply ret = %d\n", 262 ret); 263 goto err_set_load; 264 } 265 266 return 0; 267 268 err_set_load: 269 mipi_dsi_detach(dsi); 270 err_dsi_attach: 271 drm_panel_remove(&ctx->panel); 272 return ret; 273 } 274 275 static int visionox_rm69299_remove(struct mipi_dsi_device *dsi) 276 { 277 struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi); 278 279 mipi_dsi_detach(ctx->dsi); 280 mipi_dsi_device_unregister(ctx->dsi); 281 282 drm_panel_remove(&ctx->panel); 283 return 0; 284 } 285 286 static const struct of_device_id visionox_rm69299_of_match[] = { 287 { .compatible = "visionox,rm69299-1080p-display", }, 288 { /* sentinel */ } 289 }; 290 MODULE_DEVICE_TABLE(of, visionox_rm69299_of_match); 291 292 static struct mipi_dsi_driver visionox_rm69299_driver = { 293 .driver = { 294 .name = "panel-visionox-rm69299", 295 .of_match_table = visionox_rm69299_of_match, 296 }, 297 .probe = visionox_rm69299_probe, 298 .remove = visionox_rm69299_remove, 299 }; 300 module_mipi_dsi_driver(visionox_rm69299_driver); 301 302 MODULE_DESCRIPTION("Visionox RM69299 DSI Panel Driver"); 303 MODULE_LICENSE("GPL v2"); 304