0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <drm/drm_mipi_dbi.h>
0010 #include <drm/drm_modes.h>
0011 #include <drm/drm_panel.h>
0012
0013 #include <linux/backlight.h>
0014 #include <linux/delay.h>
0015 #include <linux/gpio/consumer.h>
0016 #include <linux/init.h>
0017 #include <linux/kernel.h>
0018 #include <linux/media-bus-format.h>
0019 #include <linux/module.h>
0020 #include <linux/regulator/consumer.h>
0021 #include <linux/spi/spi.h>
0022
0023 #include <video/mipi_display.h>
0024
0025 #define WS2401_RESCTL 0xb8
0026 #define WS2401_PSMPS 0xbd
0027 #define WS2401_NSMPS 0xbe
0028 #define WS2401_SMPS 0xbf
0029 #define WS2401_BCMODE 0xc1
0030 #define WS2401_WRBLCTL 0xc3
0031 #define WS2401_WRDISBV 0xc4
0032 #define WS2401_WRCTRLD 0xc6
0033 #define WS2401_WRMIE 0xc7
0034 #define WS2401_READ_ID1 0xda
0035 #define WS2401_READ_ID2 0xdb
0036 #define WS2401_READ_ID3 0xdc
0037 #define WS2401_GAMMA_R1 0xe7
0038 #define WS2401_GAMMA_G1 0xe8
0039 #define WS2401_GAMMA_B1 0xe9
0040 #define WS2401_GAMMA_R2 0xea
0041 #define WS2401_GAMMA_G2 0xeb
0042 #define WS2401_GAMMA_B2 0xec
0043 #define WS2401_PASSWD1 0xf0
0044 #define WS2401_DISCTL 0xf2
0045 #define WS2401_PWRCTL 0xf3
0046 #define WS2401_VCOMCTL 0xf4
0047 #define WS2401_SRCCTL 0xf5
0048 #define WS2401_PANELCTL 0xf6
0049
0050 static const u8 ws2401_dbi_read_commands[] = {
0051 WS2401_READ_ID1,
0052 WS2401_READ_ID2,
0053 WS2401_READ_ID3,
0054 0,
0055 };
0056
0057
0058
0059
0060
0061 struct ws2401 {
0062
0063 struct device *dev;
0064
0065 struct mipi_dbi dbi;
0066
0067 struct drm_panel panel;
0068
0069 u32 width;
0070
0071 u32 height;
0072
0073 struct gpio_desc *reset;
0074
0075 struct regulator_bulk_data regulators[2];
0076
0077 bool internal_bl;
0078 };
0079
0080 static const struct drm_display_mode lms380kf01_480_800_mode = {
0081
0082
0083
0084
0085 .clock = 24960,
0086 .hdisplay = 480,
0087 .hsync_start = 480 + 8,
0088 .hsync_end = 480 + 8 + 10,
0089 .htotal = 480 + 8 + 10 + 8,
0090 .vdisplay = 800,
0091 .vsync_start = 800 + 8,
0092 .vsync_end = 800 + 8 + 2,
0093 .vtotal = 800 + 8 + 2 + 18,
0094 .width_mm = 50,
0095 .height_mm = 84,
0096 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
0097 };
0098
0099 static inline struct ws2401 *to_ws2401(struct drm_panel *panel)
0100 {
0101 return container_of(panel, struct ws2401, panel);
0102 }
0103
0104 static void ws2401_read_mtp_id(struct ws2401 *ws)
0105 {
0106 struct mipi_dbi *dbi = &ws->dbi;
0107 u8 id1, id2, id3;
0108 int ret;
0109
0110 ret = mipi_dbi_command_read(dbi, WS2401_READ_ID1, &id1);
0111 if (ret) {
0112 dev_err(ws->dev, "unable to read MTP ID 1\n");
0113 return;
0114 }
0115 ret = mipi_dbi_command_read(dbi, WS2401_READ_ID2, &id2);
0116 if (ret) {
0117 dev_err(ws->dev, "unable to read MTP ID 2\n");
0118 return;
0119 }
0120 ret = mipi_dbi_command_read(dbi, WS2401_READ_ID3, &id3);
0121 if (ret) {
0122 dev_err(ws->dev, "unable to read MTP ID 3\n");
0123 return;
0124 }
0125 dev_info(ws->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3);
0126 }
0127
0128 static int ws2401_power_on(struct ws2401 *ws)
0129 {
0130 struct mipi_dbi *dbi = &ws->dbi;
0131 int ret;
0132
0133
0134 ret = regulator_bulk_enable(ARRAY_SIZE(ws->regulators),
0135 ws->regulators);
0136 if (ret) {
0137 dev_err(ws->dev, "failed to enable regulators: %d\n", ret);
0138 return ret;
0139 }
0140 msleep(10);
0141
0142
0143 gpiod_set_value_cansleep(ws->reset, 1);
0144 usleep_range(1000, 5000);
0145
0146 gpiod_set_value_cansleep(ws->reset, 0);
0147
0148 msleep(10);
0149 dev_dbg(ws->dev, "de-asserted RESET\n");
0150
0151
0152
0153
0154
0155 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
0156 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
0157 msleep(50);
0158
0159
0160 mipi_dbi_command(dbi, WS2401_PASSWD1, 0x5a, 0x5a);
0161
0162 mipi_dbi_command(dbi, WS2401_RESCTL, 0x12);
0163
0164 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, 0x01);
0165
0166 mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, 0x70);
0167 mipi_dbi_command(dbi, WS2401_SMPS, 0x00, 0x0f);
0168 mipi_dbi_command(dbi, WS2401_PSMPS, 0x06, 0x03,
0169 0x7e, 0x03, 0x12, 0x37);
0170 mipi_dbi_command(dbi, WS2401_NSMPS, 0x06, 0x03,
0171 0x7e, 0x02, 0x15, 0x37);
0172 mipi_dbi_command(dbi, WS2401_SMPS, 0x02, 0x0f);
0173 mipi_dbi_command(dbi, WS2401_PWRCTL, 0x10, 0xA9, 0x00, 0x01, 0x44,
0174 0xb4,
0175 0x50,
0176 0x50,
0177 0x00,
0178 0x44);
0179 mipi_dbi_command(dbi, WS2401_DISCTL, 0x01, 0x00, 0x00, 0x00, 0x14,
0180 0x16);
0181 mipi_dbi_command(dbi, WS2401_VCOMCTL, 0x30, 0x53, 0x53);
0182 mipi_dbi_command(dbi, WS2401_SRCCTL, 0x03, 0x0C, 0x00, 0x00, 0x00,
0183 0x01,
0184 0x01, 0x06, 0x03);
0185 mipi_dbi_command(dbi, WS2401_PANELCTL, 0x14, 0x00, 0x80, 0x00);
0186 mipi_dbi_command(dbi, WS2401_WRMIE, 0x01);
0187
0188
0189 mipi_dbi_command(dbi, WS2401_GAMMA_R1, 0x00,
0190 0x5b, 0x42, 0x41, 0x3f, 0x42, 0x3d, 0x38, 0x2e,
0191 0x2b, 0x2a, 0x27, 0x22, 0x27, 0x0f, 0x00, 0x00);
0192 mipi_dbi_command(dbi, WS2401_GAMMA_R2, 0x00,
0193 0x5b, 0x42, 0x41, 0x3f, 0x42, 0x3d, 0x38, 0x2e,
0194 0x2b, 0x2a, 0x27, 0x22, 0x27, 0x0f, 0x00, 0x00);
0195 mipi_dbi_command(dbi, WS2401_GAMMA_G1, 0x00,
0196 0x59, 0x40, 0x3f, 0x3e, 0x41, 0x3d, 0x39, 0x2f,
0197 0x2c, 0x2b, 0x29, 0x25, 0x29, 0x19, 0x08, 0x00);
0198 mipi_dbi_command(dbi, WS2401_GAMMA_G2, 0x00,
0199 0x59, 0x40, 0x3f, 0x3e, 0x41, 0x3d, 0x39, 0x2f,
0200 0x2c, 0x2b, 0x29, 0x25, 0x29, 0x19, 0x08, 0x00);
0201 mipi_dbi_command(dbi, WS2401_GAMMA_B1, 0x00,
0202 0x57, 0x3b, 0x3a, 0x3b, 0x3f, 0x3b, 0x38, 0x27,
0203 0x38, 0x2a, 0x26, 0x22, 0x34, 0x0c, 0x09, 0x00);
0204 mipi_dbi_command(dbi, WS2401_GAMMA_B2, 0x00,
0205 0x57, 0x3b, 0x3a, 0x3b, 0x3f, 0x3b, 0x38, 0x27,
0206 0x38, 0x2a, 0x26, 0x22, 0x34, 0x0c, 0x09, 0x00);
0207
0208 if (ws->internal_bl) {
0209 mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x2c);
0210 } else {
0211 mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x00);
0212
0213
0214
0215
0216
0217 mipi_dbi_command(dbi, WS2401_PASSWD1, 0xa5, 0xa5);
0218 }
0219
0220 return 0;
0221 }
0222
0223 static int ws2401_power_off(struct ws2401 *ws)
0224 {
0225
0226 gpiod_set_value_cansleep(ws->reset, 1);
0227 return regulator_bulk_disable(ARRAY_SIZE(ws->regulators),
0228 ws->regulators);
0229 }
0230
0231 static int ws2401_unprepare(struct drm_panel *panel)
0232 {
0233 struct ws2401 *ws = to_ws2401(panel);
0234 struct mipi_dbi *dbi = &ws->dbi;
0235
0236
0237 if (ws->internal_bl)
0238 mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x00);
0239 mipi_dbi_command(dbi, MIPI_DCS_ENTER_SLEEP_MODE);
0240 msleep(120);
0241 return ws2401_power_off(to_ws2401(panel));
0242 }
0243
0244 static int ws2401_disable(struct drm_panel *panel)
0245 {
0246 struct ws2401 *ws = to_ws2401(panel);
0247 struct mipi_dbi *dbi = &ws->dbi;
0248
0249 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
0250 msleep(25);
0251
0252 return 0;
0253 }
0254
0255 static int ws2401_prepare(struct drm_panel *panel)
0256 {
0257 return ws2401_power_on(to_ws2401(panel));
0258 }
0259
0260 static int ws2401_enable(struct drm_panel *panel)
0261 {
0262 struct ws2401 *ws = to_ws2401(panel);
0263 struct mipi_dbi *dbi = &ws->dbi;
0264
0265 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
0266
0267 return 0;
0268 }
0269
0270
0271
0272
0273
0274
0275 static int ws2401_get_modes(struct drm_panel *panel,
0276 struct drm_connector *connector)
0277 {
0278 struct ws2401 *ws = to_ws2401(panel);
0279 struct drm_display_mode *mode;
0280 static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
0281
0282
0283
0284
0285
0286
0287
0288 mode = drm_mode_duplicate(connector->dev, &lms380kf01_480_800_mode);
0289 if (!mode) {
0290 dev_err(ws->dev, "failed to add mode\n");
0291 return -ENOMEM;
0292 }
0293
0294 connector->display_info.bpc = 8;
0295 connector->display_info.width_mm = mode->width_mm;
0296 connector->display_info.height_mm = mode->height_mm;
0297 connector->display_info.bus_flags =
0298 DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
0299 drm_display_info_set_bus_formats(&connector->display_info,
0300 &bus_format, 1);
0301
0302 drm_mode_set_name(mode);
0303 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0304
0305 drm_mode_probed_add(connector, mode);
0306
0307 return 1;
0308 }
0309
0310 static const struct drm_panel_funcs ws2401_drm_funcs = {
0311 .disable = ws2401_disable,
0312 .unprepare = ws2401_unprepare,
0313 .prepare = ws2401_prepare,
0314 .enable = ws2401_enable,
0315 .get_modes = ws2401_get_modes,
0316 };
0317
0318 static int ws2401_set_brightness(struct backlight_device *bl)
0319 {
0320 struct ws2401 *ws = bl_get_data(bl);
0321 struct mipi_dbi *dbi = &ws->dbi;
0322 u8 brightness = backlight_get_brightness(bl);
0323
0324 if (backlight_is_blank(bl)) {
0325 mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x00);
0326 } else {
0327 mipi_dbi_command(dbi, WS2401_WRCTRLD, 0x2c);
0328 mipi_dbi_command(dbi, WS2401_WRDISBV, brightness);
0329 }
0330
0331 return 0;
0332 }
0333
0334 static const struct backlight_ops ws2401_bl_ops = {
0335 .update_status = ws2401_set_brightness,
0336 };
0337
0338 static const struct backlight_properties ws2401_bl_props = {
0339 .type = BACKLIGHT_PLATFORM,
0340 .brightness = 120,
0341 .max_brightness = U8_MAX,
0342 };
0343
0344 static int ws2401_probe(struct spi_device *spi)
0345 {
0346 struct device *dev = &spi->dev;
0347 struct ws2401 *ws;
0348 int ret;
0349
0350 ws = devm_kzalloc(dev, sizeof(*ws), GFP_KERNEL);
0351 if (!ws)
0352 return -ENOMEM;
0353 ws->dev = dev;
0354
0355
0356
0357
0358
0359 ws->regulators[0].supply = "vci";
0360 ws->regulators[1].supply = "vccio";
0361 ret = devm_regulator_bulk_get(dev,
0362 ARRAY_SIZE(ws->regulators),
0363 ws->regulators);
0364 if (ret)
0365 return dev_err_probe(dev, ret, "failed to get regulators\n");
0366
0367 ws->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0368 if (IS_ERR(ws->reset)) {
0369 ret = PTR_ERR(ws->reset);
0370 return dev_err_probe(dev, ret, "no RESET GPIO\n");
0371 }
0372
0373 ret = mipi_dbi_spi_init(spi, &ws->dbi, NULL);
0374 if (ret)
0375 return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
0376 ws->dbi.read_commands = ws2401_dbi_read_commands;
0377
0378 ws2401_power_on(ws);
0379 ws2401_read_mtp_id(ws);
0380 ws2401_power_off(ws);
0381
0382 drm_panel_init(&ws->panel, dev, &ws2401_drm_funcs,
0383 DRM_MODE_CONNECTOR_DPI);
0384
0385 ret = drm_panel_of_backlight(&ws->panel);
0386 if (ret)
0387 return dev_err_probe(dev, ret,
0388 "failed to get external backlight device\n");
0389
0390 if (!ws->panel.backlight) {
0391 dev_dbg(dev, "no external backlight, using internal backlight\n");
0392 ws->panel.backlight =
0393 devm_backlight_device_register(dev, "ws2401", dev, ws,
0394 &ws2401_bl_ops, &ws2401_bl_props);
0395 if (IS_ERR(ws->panel.backlight))
0396 return dev_err_probe(dev, PTR_ERR(ws->panel.backlight),
0397 "failed to register backlight device\n");
0398 } else {
0399 dev_dbg(dev, "using external backlight\n");
0400 }
0401
0402 spi_set_drvdata(spi, ws);
0403
0404 drm_panel_add(&ws->panel);
0405 dev_dbg(dev, "added panel\n");
0406
0407 return 0;
0408 }
0409
0410 static void ws2401_remove(struct spi_device *spi)
0411 {
0412 struct ws2401 *ws = spi_get_drvdata(spi);
0413
0414 drm_panel_remove(&ws->panel);
0415 }
0416
0417
0418
0419
0420
0421
0422 static const struct of_device_id ws2401_match[] = {
0423 { .compatible = "samsung,lms380kf01", },
0424 {},
0425 };
0426 MODULE_DEVICE_TABLE(of, ws2401_match);
0427
0428 static struct spi_driver ws2401_driver = {
0429 .probe = ws2401_probe,
0430 .remove = ws2401_remove,
0431 .driver = {
0432 .name = "ws2401-panel",
0433 .of_match_table = ws2401_match,
0434 },
0435 };
0436 module_spi_driver(ws2401_driver);
0437
0438 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
0439 MODULE_DESCRIPTION("Samsung WS2401 panel driver");
0440 MODULE_LICENSE("GPL v2");