panel-sony-tulip-truly-nt35521.c (18098B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2021, Linaro Limited 4 * 5 * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: 6 * Copyright (c) 2013, The Linux Foundation. All rights reserved. 7 */ 8 9#include <linux/backlight.h> 10#include <linux/delay.h> 11#include <linux/gpio/consumer.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <linux/regulator/consumer.h> 15 16#include <drm/drm_mipi_dsi.h> 17#include <drm/drm_modes.h> 18#include <drm/drm_panel.h> 19 20struct truly_nt35521 { 21 struct drm_panel panel; 22 struct mipi_dsi_device *dsi; 23 struct regulator_bulk_data supplies[2]; 24 struct gpio_desc *reset_gpio; 25 struct gpio_desc *blen_gpio; 26 bool prepared; 27 bool enabled; 28}; 29 30static inline 31struct truly_nt35521 *to_truly_nt35521(struct drm_panel *panel) 32{ 33 return container_of(panel, struct truly_nt35521, panel); 34} 35 36#define dsi_generic_write_seq(dsi, seq...) do { \ 37 static const u8 d[] = { seq }; \ 38 int ret; \ 39 ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ 40 if (ret < 0) \ 41 return ret; \ 42 } while (0) 43 44static void truly_nt35521_reset(struct truly_nt35521 *ctx) 45{ 46 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 47 usleep_range(1000, 2000); 48 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 49 usleep_range(10000, 11000); 50 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 51 msleep(150); 52} 53 54static int truly_nt35521_on(struct truly_nt35521 *ctx) 55{ 56 struct mipi_dsi_device *dsi = ctx->dsi; 57 struct device *dev = &dsi->dev; 58 int ret; 59 60 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 61 62 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 63 dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80); 64 dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00); 65 dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00); 66 dsi_generic_write_seq(dsi, 0x6f, 0x01); 67 dsi_generic_write_seq(dsi, 0xb1, 0x21); 68 dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01); 69 dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02); 70 dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11); 71 dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00); 72 dsi_generic_write_seq(dsi, 0xb6, 0x02); 73 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01); 74 dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09); 75 dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09); 76 dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00); 77 dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00); 78 dsi_generic_write_seq(dsi, 0xca, 0x00); 79 dsi_generic_write_seq(dsi, 0xc0, 0x04); 80 dsi_generic_write_seq(dsi, 0xbe, 0xb5); 81 dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35); 82 dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25); 83 dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43); 84 dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24); 85 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02); 86 dsi_generic_write_seq(dsi, 0xee, 0x03); 87 dsi_generic_write_seq(dsi, 0xb0, 88 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3, 89 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11); 90 dsi_generic_write_seq(dsi, 0xb1, 91 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3, 92 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77); 93 dsi_generic_write_seq(dsi, 0xb2, 94 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c, 95 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90); 96 dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98); 97 dsi_generic_write_seq(dsi, 0xb4, 98 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9, 99 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02); 100 dsi_generic_write_seq(dsi, 0xb5, 101 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf, 102 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76); 103 dsi_generic_write_seq(dsi, 0xb6, 104 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c, 105 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2); 106 dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba); 107 dsi_generic_write_seq(dsi, 0xb8, 108 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a, 109 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9); 110 dsi_generic_write_seq(dsi, 0xb9, 111 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3, 112 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67); 113 dsi_generic_write_seq(dsi, 0xba, 114 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31, 115 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4); 116 dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7); 117 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03); 118 dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00); 119 dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00); 120 dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00); 121 dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00); 122 dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00); 123 dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00); 124 dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00); 125 dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00); 126 dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00); 127 dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00); 128 dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00); 129 dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00); 130 dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00); 131 dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00); 132 dsi_generic_write_seq(dsi, 0xc4, 0x60); 133 dsi_generic_write_seq(dsi, 0xc5, 0xc0); 134 dsi_generic_write_seq(dsi, 0xc6, 0x00); 135 dsi_generic_write_seq(dsi, 0xc7, 0x00); 136 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05); 137 dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06); 138 dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06); 139 dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06); 140 dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06); 141 dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06); 142 dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06); 143 dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06); 144 dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06); 145 dsi_generic_write_seq(dsi, 0xb8, 0x00); 146 dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03); 147 dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00); 148 dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03); 149 dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03); 150 dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03); 151 dsi_generic_write_seq(dsi, 0xc0, 0x0b); 152 dsi_generic_write_seq(dsi, 0xc1, 0x09); 153 dsi_generic_write_seq(dsi, 0xc2, 0xa6); 154 dsi_generic_write_seq(dsi, 0xc3, 0x05); 155 dsi_generic_write_seq(dsi, 0xc4, 0x00); 156 dsi_generic_write_seq(dsi, 0xc5, 0x02); 157 dsi_generic_write_seq(dsi, 0xc6, 0x22); 158 dsi_generic_write_seq(dsi, 0xc7, 0x03); 159 dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20); 160 dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20); 161 dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60); 162 dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60); 163 dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02); 164 dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02); 165 dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02); 166 dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02); 167 dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10); 168 dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10); 169 dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10); 170 dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10); 171 dsi_generic_write_seq(dsi, 0xd0, 172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 173 dsi_generic_write_seq(dsi, 0xd5, 174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 175 0x00, 0x00, 0x00); 176 dsi_generic_write_seq(dsi, 0xd6, 177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 178 0x00, 0x00, 0x00); 179 dsi_generic_write_seq(dsi, 0xd7, 180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 181 0x00, 0x00, 0x00); 182 dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00); 183 dsi_generic_write_seq(dsi, 0xe5, 0x06); 184 dsi_generic_write_seq(dsi, 0xe6, 0x06); 185 dsi_generic_write_seq(dsi, 0xe7, 0x00); 186 dsi_generic_write_seq(dsi, 0xe8, 0x06); 187 dsi_generic_write_seq(dsi, 0xe9, 0x06); 188 dsi_generic_write_seq(dsi, 0xea, 0x06); 189 dsi_generic_write_seq(dsi, 0xeb, 0x00); 190 dsi_generic_write_seq(dsi, 0xec, 0x00); 191 dsi_generic_write_seq(dsi, 0xed, 0x30); 192 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06); 193 dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31); 194 dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31); 195 dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e); 196 dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34); 197 dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a); 198 dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10); 199 dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16); 200 dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02); 201 dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31); 202 dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31); 203 dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31); 204 dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08); 205 dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01); 206 dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19); 207 dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13); 208 dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29); 209 dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31); 210 dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d); 211 dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31); 212 dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31); 213 dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31); 214 dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31); 215 dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d); 216 dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34); 217 dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a); 218 dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19); 219 dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13); 220 dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01); 221 dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31); 222 dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31); 223 dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31); 224 dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08); 225 dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02); 226 dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10); 227 dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16); 228 dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29); 229 dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31); 230 dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e); 231 dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31); 232 dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31); 233 dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31); 234 dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31); 235 dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00); 236 dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00); 237 dsi_generic_write_seq(dsi, 0xe7, 0x00); 238 dsi_generic_write_seq(dsi, 0x6f, 0x02); 239 dsi_generic_write_seq(dsi, 0xf7, 0x47); 240 dsi_generic_write_seq(dsi, 0x6f, 0x0a); 241 dsi_generic_write_seq(dsi, 0xf7, 0x02); 242 dsi_generic_write_seq(dsi, 0x6f, 0x17); 243 dsi_generic_write_seq(dsi, 0xf4, 0x60); 244 dsi_generic_write_seq(dsi, 0x6f, 0x01); 245 dsi_generic_write_seq(dsi, 0xf9, 0x46); 246 dsi_generic_write_seq(dsi, 0x6f, 0x11); 247 dsi_generic_write_seq(dsi, 0xf3, 0x01); 248 dsi_generic_write_seq(dsi, 0x35, 0x00); 249 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 250 dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00); 251 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00); 252 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00); 253 dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21); 254 dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00); 255 dsi_generic_write_seq(dsi, 0x35, 0x00); 256 257 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 258 if (ret < 0) { 259 dev_err(dev, "Failed to exit sleep mode: %d\n", ret); 260 return ret; 261 } 262 msleep(120); 263 264 ret = mipi_dsi_dcs_set_display_on(dsi); 265 if (ret < 0) { 266 dev_err(dev, "Failed to set display on: %d\n", ret); 267 return ret; 268 } 269 usleep_range(1000, 2000); 270 271 dsi_generic_write_seq(dsi, 0x53, 0x24); 272 273 return 0; 274} 275 276static int truly_nt35521_off(struct truly_nt35521 *ctx) 277{ 278 struct mipi_dsi_device *dsi = ctx->dsi; 279 struct device *dev = &dsi->dev; 280 int ret; 281 282 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 283 284 ret = mipi_dsi_dcs_set_display_off(dsi); 285 if (ret < 0) { 286 dev_err(dev, "Failed to set display off: %d\n", ret); 287 return ret; 288 } 289 msleep(50); 290 291 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 292 if (ret < 0) { 293 dev_err(dev, "Failed to enter sleep mode: %d\n", ret); 294 return ret; 295 } 296 msleep(150); 297 298 return 0; 299} 300 301static int truly_nt35521_prepare(struct drm_panel *panel) 302{ 303 struct truly_nt35521 *ctx = to_truly_nt35521(panel); 304 struct device *dev = &ctx->dsi->dev; 305 int ret; 306 307 if (ctx->prepared) 308 return 0; 309 310 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 311 if (ret < 0) { 312 dev_err(dev, "Failed to enable regulators: %d\n", ret); 313 return ret; 314 } 315 316 truly_nt35521_reset(ctx); 317 318 ret = truly_nt35521_on(ctx); 319 if (ret < 0) { 320 dev_err(dev, "Failed to initialize panel: %d\n", ret); 321 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 322 return ret; 323 } 324 325 ctx->prepared = true; 326 return 0; 327} 328 329static int truly_nt35521_unprepare(struct drm_panel *panel) 330{ 331 struct truly_nt35521 *ctx = to_truly_nt35521(panel); 332 struct device *dev = &ctx->dsi->dev; 333 int ret; 334 335 if (!ctx->prepared) 336 return 0; 337 338 ret = truly_nt35521_off(ctx); 339 if (ret < 0) 340 dev_err(dev, "Failed to un-initialize panel: %d\n", ret); 341 342 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 343 regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), 344 ctx->supplies); 345 346 ctx->prepared = false; 347 return 0; 348} 349 350static int truly_nt35521_enable(struct drm_panel *panel) 351{ 352 struct truly_nt35521 *ctx = to_truly_nt35521(panel); 353 354 if (ctx->enabled) 355 return 0; 356 357 gpiod_set_value_cansleep(ctx->blen_gpio, 1); 358 359 ctx->enabled = true; 360 return 0; 361} 362 363static int truly_nt35521_disable(struct drm_panel *panel) 364{ 365 struct truly_nt35521 *ctx = to_truly_nt35521(panel); 366 367 if (!ctx->enabled) 368 return 0; 369 370 gpiod_set_value_cansleep(ctx->blen_gpio, 0); 371 372 ctx->enabled = false; 373 return 0; 374} 375 376static const struct drm_display_mode truly_nt35521_mode = { 377 .clock = (720 + 232 + 20 + 112) * (1280 + 18 + 1 + 18) * 60 / 1000, 378 .hdisplay = 720, 379 .hsync_start = 720 + 232, 380 .hsync_end = 720 + 232 + 20, 381 .htotal = 720 + 232 + 20 + 112, 382 .vdisplay = 1280, 383 .vsync_start = 1280 + 18, 384 .vsync_end = 1280 + 18 + 1, 385 .vtotal = 1280 + 18 + 1 + 18, 386 .width_mm = 65, 387 .height_mm = 116, 388}; 389 390static int truly_nt35521_get_modes(struct drm_panel *panel, 391 struct drm_connector *connector) 392{ 393 struct drm_display_mode *mode; 394 395 mode = drm_mode_duplicate(connector->dev, &truly_nt35521_mode); 396 if (!mode) 397 return -ENOMEM; 398 399 drm_mode_set_name(mode); 400 401 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 402 connector->display_info.width_mm = mode->width_mm; 403 connector->display_info.height_mm = mode->height_mm; 404 drm_mode_probed_add(connector, mode); 405 406 return 1; 407} 408 409static const struct drm_panel_funcs truly_nt35521_panel_funcs = { 410 .prepare = truly_nt35521_prepare, 411 .unprepare = truly_nt35521_unprepare, 412 .enable = truly_nt35521_enable, 413 .disable = truly_nt35521_disable, 414 .get_modes = truly_nt35521_get_modes, 415}; 416 417static int truly_nt35521_bl_update_status(struct backlight_device *bl) 418{ 419 struct mipi_dsi_device *dsi = bl_get_data(bl); 420 u16 brightness = backlight_get_brightness(bl); 421 int ret; 422 423 ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness); 424 if (ret < 0) 425 return ret; 426 427 return 0; 428} 429 430static int truly_nt35521_bl_get_brightness(struct backlight_device *bl) 431{ 432 struct mipi_dsi_device *dsi = bl_get_data(bl); 433 u16 brightness; 434 int ret; 435 436 ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); 437 if (ret < 0) 438 return ret; 439 440 return brightness & 0xff; 441} 442 443static const struct backlight_ops truly_nt35521_bl_ops = { 444 .update_status = truly_nt35521_bl_update_status, 445 .get_brightness = truly_nt35521_bl_get_brightness, 446}; 447 448static struct backlight_device * 449truly_nt35521_create_backlight(struct mipi_dsi_device *dsi) 450{ 451 struct device *dev = &dsi->dev; 452 const struct backlight_properties props = { 453 .type = BACKLIGHT_RAW, 454 .brightness = 255, 455 .max_brightness = 255, 456 }; 457 458 return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 459 &truly_nt35521_bl_ops, &props); 460} 461 462static int truly_nt35521_probe(struct mipi_dsi_device *dsi) 463{ 464 struct device *dev = &dsi->dev; 465 struct truly_nt35521 *ctx; 466 int ret; 467 468 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 469 if (!ctx) 470 return -ENOMEM; 471 472 ctx->supplies[0].supply = "positive5"; 473 ctx->supplies[1].supply = "negative5"; 474 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 475 ctx->supplies); 476 if (ret < 0) { 477 dev_err(dev, "Failed to get regulators: %d\n", ret); 478 return ret; 479 } 480 481 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 482 if (IS_ERR(ctx->reset_gpio)) 483 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 484 "Failed to get reset-gpios\n"); 485 486 ctx->blen_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW); 487 if (IS_ERR(ctx->blen_gpio)) 488 return dev_err_probe(dev, PTR_ERR(ctx->blen_gpio), 489 "Failed to get backlight-gpios\n"); 490 491 ctx->dsi = dsi; 492 mipi_dsi_set_drvdata(dsi, ctx); 493 494 dsi->lanes = 4; 495 dsi->format = MIPI_DSI_FMT_RGB888; 496 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 497 MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET | 498 MIPI_DSI_CLOCK_NON_CONTINUOUS; 499 500 drm_panel_init(&ctx->panel, dev, &truly_nt35521_panel_funcs, 501 DRM_MODE_CONNECTOR_DSI); 502 503 ctx->panel.backlight = truly_nt35521_create_backlight(dsi); 504 if (IS_ERR(ctx->panel.backlight)) 505 return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), 506 "Failed to create backlight\n"); 507 508 drm_panel_add(&ctx->panel); 509 510 ret = mipi_dsi_attach(dsi); 511 if (ret < 0) { 512 dev_err(dev, "Failed to attach to DSI host: %d\n", ret); 513 drm_panel_remove(&ctx->panel); 514 return ret; 515 } 516 517 return 0; 518} 519 520static int truly_nt35521_remove(struct mipi_dsi_device *dsi) 521{ 522 struct truly_nt35521 *ctx = mipi_dsi_get_drvdata(dsi); 523 int ret; 524 525 ret = mipi_dsi_detach(dsi); 526 if (ret < 0) 527 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 528 529 drm_panel_remove(&ctx->panel); 530 531 return 0; 532} 533 534static const struct of_device_id truly_nt35521_of_match[] = { 535 { .compatible = "sony,tulip-truly-nt35521" }, 536 { /* sentinel */ } 537}; 538MODULE_DEVICE_TABLE(of, truly_nt35521_of_match); 539 540static struct mipi_dsi_driver truly_nt35521_driver = { 541 .probe = truly_nt35521_probe, 542 .remove = truly_nt35521_remove, 543 .driver = { 544 .name = "panel-truly-nt35521", 545 .of_match_table = truly_nt35521_of_match, 546 }, 547}; 548module_mipi_dsi_driver(truly_nt35521_driver); 549 550MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>"); 551MODULE_DESCRIPTION("DRM driver for Sony Tulip Truly NT35521 panel"); 552MODULE_LICENSE("GPL v2");