0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/backlight.h>
0010 #include <linux/delay.h>
0011 #include <linux/gpio/consumer.h>
0012 #include <linux/module.h>
0013 #include <linux/regulator/consumer.h>
0014
0015 #include <video/mipi_display.h>
0016
0017 #include <drm/drm_mipi_dsi.h>
0018 #include <drm/drm_modes.h>
0019 #include <drm/drm_panel.h>
0020
0021 #define OTM8009A_BACKLIGHT_DEFAULT 240
0022 #define OTM8009A_BACKLIGHT_MAX 255
0023
0024
0025 #define MCS_ADRSFT 0x0000
0026 #define MCS_PANSET 0xB3A6
0027 #define MCS_SD_CTRL 0xC0A2
0028 #define MCS_P_DRV_M 0xC0B4
0029 #define MCS_OSC_ADJ 0xC181
0030 #define MCS_RGB_VID_SET 0xC1A1
0031 #define MCS_SD_PCH_CTRL 0xC480
0032 #define MCS_NO_DOC1 0xC48A
0033 #define MCS_PWR_CTRL1 0xC580
0034 #define MCS_PWR_CTRL2 0xC590
0035 #define MCS_PWR_CTRL4 0xC5B0
0036 #define MCS_PANCTRLSET1 0xCB80
0037 #define MCS_PANCTRLSET2 0xCB90
0038 #define MCS_PANCTRLSET3 0xCBA0
0039 #define MCS_PANCTRLSET4 0xCBB0
0040 #define MCS_PANCTRLSET5 0xCBC0
0041 #define MCS_PANCTRLSET6 0xCBD0
0042 #define MCS_PANCTRLSET7 0xCBE0
0043 #define MCS_PANCTRLSET8 0xCBF0
0044 #define MCS_PANU2D1 0xCC80
0045 #define MCS_PANU2D2 0xCC90
0046 #define MCS_PANU2D3 0xCCA0
0047 #define MCS_PAND2U1 0xCCB0
0048 #define MCS_PAND2U2 0xCCC0
0049 #define MCS_PAND2U3 0xCCD0
0050 #define MCS_GOAVST 0xCE80
0051 #define MCS_GOACLKA1 0xCEA0
0052 #define MCS_GOACLKA3 0xCEB0
0053 #define MCS_GOAECLK 0xCFC0
0054 #define MCS_NO_DOC2 0xCFD0
0055 #define MCS_GVDDSET 0xD800
0056 #define MCS_VCOMDC 0xD900
0057 #define MCS_GMCT2_2P 0xE100
0058 #define MCS_GMCT2_2N 0xE200
0059 #define MCS_NO_DOC3 0xF5B6
0060 #define MCS_CMD2_ENA1 0xFF00
0061 #define MCS_CMD2_ENA2 0xFF80
0062
0063 #define OTM8009A_HDISPLAY 480
0064 #define OTM8009A_VDISPLAY 800
0065
0066 struct otm8009a {
0067 struct device *dev;
0068 struct drm_panel panel;
0069 struct backlight_device *bl_dev;
0070 struct gpio_desc *reset_gpio;
0071 struct regulator *supply;
0072 bool prepared;
0073 bool enabled;
0074 };
0075
0076 static const struct drm_display_mode modes[] = {
0077 {
0078 .clock = 29700,
0079 .hdisplay = 480,
0080 .hsync_start = 480 + 98,
0081 .hsync_end = 480 + 98 + 32,
0082 .htotal = 480 + 98 + 32 + 98,
0083 .vdisplay = 800,
0084 .vsync_start = 800 + 15,
0085 .vsync_end = 800 + 15 + 10,
0086 .vtotal = 800 + 15 + 10 + 14,
0087 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
0088 .width_mm = 52,
0089 .height_mm = 86,
0090 },
0091 {
0092 .clock = 33000,
0093 .hdisplay = 480,
0094 .hsync_start = 480 + 70,
0095 .hsync_end = 480 + 70 + 32,
0096 .htotal = 480 + 70 + 32 + 72,
0097 .vdisplay = 800,
0098 .vsync_start = 800 + 15,
0099 .vsync_end = 800 + 15 + 10,
0100 .vtotal = 800 + 15 + 10 + 16,
0101 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
0102 .width_mm = 52,
0103 .height_mm = 86,
0104 },
0105 };
0106
0107 static inline struct otm8009a *panel_to_otm8009a(struct drm_panel *panel)
0108 {
0109 return container_of(panel, struct otm8009a, panel);
0110 }
0111
0112 static void otm8009a_dcs_write_buf(struct otm8009a *ctx, const void *data,
0113 size_t len)
0114 {
0115 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0116
0117 if (mipi_dsi_dcs_write_buffer(dsi, data, len) < 0)
0118 dev_warn(ctx->dev, "mipi dsi dcs write buffer failed\n");
0119 }
0120
0121 #define dcs_write_seq(ctx, seq...) \
0122 ({ \
0123 static const u8 d[] = { seq }; \
0124 otm8009a_dcs_write_buf(ctx, d, ARRAY_SIZE(d)); \
0125 })
0126
0127 #define dcs_write_cmd_at(ctx, cmd, seq...) \
0128 ({ \
0129 dcs_write_seq(ctx, MCS_ADRSFT, (cmd) & 0xFF); \
0130 dcs_write_seq(ctx, (cmd) >> 8, seq); \
0131 })
0132
0133 static int otm8009a_init_sequence(struct otm8009a *ctx)
0134 {
0135 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0136 int ret;
0137
0138
0139 dcs_write_cmd_at(ctx, MCS_CMD2_ENA1, 0x80, 0x09, 0x01);
0140
0141
0142 dcs_write_cmd_at(ctx, MCS_CMD2_ENA2, 0x80, 0x09);
0143
0144 dcs_write_cmd_at(ctx, MCS_SD_PCH_CTRL, 0x30);
0145 mdelay(10);
0146
0147 dcs_write_cmd_at(ctx, MCS_NO_DOC1, 0x40);
0148 mdelay(10);
0149
0150 dcs_write_cmd_at(ctx, MCS_PWR_CTRL4 + 1, 0xA9);
0151 dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 1, 0x34);
0152 dcs_write_cmd_at(ctx, MCS_P_DRV_M, 0x50);
0153 dcs_write_cmd_at(ctx, MCS_VCOMDC, 0x4E);
0154 dcs_write_cmd_at(ctx, MCS_OSC_ADJ, 0x66);
0155 dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 2, 0x01);
0156 dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 5, 0x34);
0157 dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 4, 0x33);
0158 dcs_write_cmd_at(ctx, MCS_GVDDSET, 0x79, 0x79);
0159 dcs_write_cmd_at(ctx, MCS_SD_CTRL + 1, 0x1B);
0160 dcs_write_cmd_at(ctx, MCS_PWR_CTRL1 + 2, 0x83);
0161 dcs_write_cmd_at(ctx, MCS_SD_PCH_CTRL + 1, 0x83);
0162 dcs_write_cmd_at(ctx, MCS_RGB_VID_SET, 0x0E);
0163 dcs_write_cmd_at(ctx, MCS_PANSET, 0x00, 0x01);
0164
0165 dcs_write_cmd_at(ctx, MCS_GOAVST, 0x85, 0x01, 0x00, 0x84, 0x01, 0x00);
0166 dcs_write_cmd_at(ctx, MCS_GOACLKA1, 0x18, 0x04, 0x03, 0x39, 0x00, 0x00,
0167 0x00, 0x18, 0x03, 0x03, 0x3A, 0x00, 0x00, 0x00);
0168 dcs_write_cmd_at(ctx, MCS_GOACLKA3, 0x18, 0x02, 0x03, 0x3B, 0x00, 0x00,
0169 0x00, 0x18, 0x01, 0x03, 0x3C, 0x00, 0x00, 0x00);
0170 dcs_write_cmd_at(ctx, MCS_GOAECLK, 0x01, 0x01, 0x20, 0x20, 0x00, 0x00,
0171 0x01, 0x02, 0x00, 0x00);
0172
0173 dcs_write_cmd_at(ctx, MCS_NO_DOC2, 0x00);
0174
0175 dcs_write_cmd_at(ctx, MCS_PANCTRLSET1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
0176 dcs_write_cmd_at(ctx, MCS_PANCTRLSET2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0177 0, 0, 0, 0, 0);
0178 dcs_write_cmd_at(ctx, MCS_PANCTRLSET3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0179 0, 0, 0, 0, 0);
0180 dcs_write_cmd_at(ctx, MCS_PANCTRLSET4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
0181 dcs_write_cmd_at(ctx, MCS_PANCTRLSET5, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0,
0182 0, 0, 0, 0, 0);
0183 dcs_write_cmd_at(ctx, MCS_PANCTRLSET6, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4,
0184 4, 0, 0, 0, 0);
0185 dcs_write_cmd_at(ctx, MCS_PANCTRLSET7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
0186 dcs_write_cmd_at(ctx, MCS_PANCTRLSET8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0187 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
0188
0189 dcs_write_cmd_at(ctx, MCS_PANU2D1, 0x00, 0x26, 0x09, 0x0B, 0x01, 0x25,
0190 0x00, 0x00, 0x00, 0x00);
0191 dcs_write_cmd_at(ctx, MCS_PANU2D2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0192 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0A, 0x0C, 0x02);
0193 dcs_write_cmd_at(ctx, MCS_PANU2D3, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
0194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
0195 dcs_write_cmd_at(ctx, MCS_PAND2U1, 0x00, 0x25, 0x0C, 0x0A, 0x02, 0x26,
0196 0x00, 0x00, 0x00, 0x00);
0197 dcs_write_cmd_at(ctx, MCS_PAND2U2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0198 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0B, 0x09, 0x01);
0199 dcs_write_cmd_at(ctx, MCS_PAND2U3, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
0200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
0201
0202 dcs_write_cmd_at(ctx, MCS_PWR_CTRL1 + 1, 0x66);
0203
0204 dcs_write_cmd_at(ctx, MCS_NO_DOC3, 0x06);
0205
0206 dcs_write_cmd_at(ctx, MCS_GMCT2_2P, 0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10,
0207 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A,
0208 0x01);
0209 dcs_write_cmd_at(ctx, MCS_GMCT2_2N, 0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10,
0210 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A,
0211 0x01);
0212
0213
0214 dcs_write_cmd_at(ctx, MCS_CMD2_ENA1, 0xFF, 0xFF, 0xFF);
0215
0216 ret = mipi_dsi_dcs_nop(dsi);
0217 if (ret)
0218 return ret;
0219
0220 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0221 if (ret)
0222 return ret;
0223
0224
0225 mdelay(120);
0226
0227
0228 dcs_write_seq(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
0229
0230 ret = mipi_dsi_dcs_set_column_address(dsi, 0, OTM8009A_HDISPLAY - 1);
0231 if (ret)
0232 return ret;
0233
0234 ret = mipi_dsi_dcs_set_page_address(dsi, 0, OTM8009A_VDISPLAY - 1);
0235 if (ret)
0236 return ret;
0237
0238
0239 ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT |
0240 MIPI_DCS_PIXEL_FMT_24BIT << 4);
0241 if (ret)
0242 return ret;
0243
0244
0245 dcs_write_seq(ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
0246
0247 ret = mipi_dsi_dcs_set_display_on(dsi);
0248 if (ret)
0249 return ret;
0250
0251 ret = mipi_dsi_dcs_nop(dsi);
0252 if (ret)
0253 return ret;
0254
0255
0256 dcs_write_seq(ctx, MIPI_DCS_WRITE_MEMORY_START);
0257
0258
0259 mdelay(10);
0260
0261 return 0;
0262 }
0263
0264 static int otm8009a_disable(struct drm_panel *panel)
0265 {
0266 struct otm8009a *ctx = panel_to_otm8009a(panel);
0267 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0268 int ret;
0269
0270 if (!ctx->enabled)
0271 return 0;
0272
0273 backlight_disable(ctx->bl_dev);
0274
0275 ret = mipi_dsi_dcs_set_display_off(dsi);
0276 if (ret)
0277 return ret;
0278
0279 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0280 if (ret)
0281 return ret;
0282
0283 msleep(120);
0284
0285 ctx->enabled = false;
0286
0287 return 0;
0288 }
0289
0290 static int otm8009a_unprepare(struct drm_panel *panel)
0291 {
0292 struct otm8009a *ctx = panel_to_otm8009a(panel);
0293
0294 if (!ctx->prepared)
0295 return 0;
0296
0297 if (ctx->reset_gpio) {
0298 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0299 msleep(20);
0300 }
0301
0302 regulator_disable(ctx->supply);
0303
0304 ctx->prepared = false;
0305
0306 return 0;
0307 }
0308
0309 static int otm8009a_prepare(struct drm_panel *panel)
0310 {
0311 struct otm8009a *ctx = panel_to_otm8009a(panel);
0312 int ret;
0313
0314 if (ctx->prepared)
0315 return 0;
0316
0317 ret = regulator_enable(ctx->supply);
0318 if (ret < 0) {
0319 dev_err(panel->dev, "failed to enable supply: %d\n", ret);
0320 return ret;
0321 }
0322
0323 if (ctx->reset_gpio) {
0324 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
0325 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0326 msleep(20);
0327 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
0328 msleep(100);
0329 }
0330
0331 ret = otm8009a_init_sequence(ctx);
0332 if (ret)
0333 return ret;
0334
0335 ctx->prepared = true;
0336
0337 return 0;
0338 }
0339
0340 static int otm8009a_enable(struct drm_panel *panel)
0341 {
0342 struct otm8009a *ctx = panel_to_otm8009a(panel);
0343
0344 if (ctx->enabled)
0345 return 0;
0346
0347 backlight_enable(ctx->bl_dev);
0348
0349 ctx->enabled = true;
0350
0351 return 0;
0352 }
0353
0354 static int otm8009a_get_modes(struct drm_panel *panel,
0355 struct drm_connector *connector)
0356 {
0357 struct drm_display_mode *mode;
0358 unsigned int num_modes = ARRAY_SIZE(modes);
0359 unsigned int i;
0360
0361 for (i = 0; i < num_modes; i++) {
0362 mode = drm_mode_duplicate(connector->dev, &modes[i]);
0363 if (!mode) {
0364 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
0365 modes[i].hdisplay,
0366 modes[i].vdisplay,
0367 drm_mode_vrefresh(&modes[i]));
0368 return -ENOMEM;
0369 }
0370
0371 mode->type = DRM_MODE_TYPE_DRIVER;
0372
0373
0374 if (!i)
0375 mode->type |= DRM_MODE_TYPE_PREFERRED;
0376
0377 drm_mode_set_name(mode);
0378 drm_mode_probed_add(connector, mode);
0379 }
0380
0381 connector->display_info.width_mm = mode->width_mm;
0382 connector->display_info.height_mm = mode->height_mm;
0383
0384 return num_modes;
0385 }
0386
0387 static const struct drm_panel_funcs otm8009a_drm_funcs = {
0388 .disable = otm8009a_disable,
0389 .unprepare = otm8009a_unprepare,
0390 .prepare = otm8009a_prepare,
0391 .enable = otm8009a_enable,
0392 .get_modes = otm8009a_get_modes,
0393 };
0394
0395
0396
0397
0398
0399 static int otm8009a_backlight_update_status(struct backlight_device *bd)
0400 {
0401 struct otm8009a *ctx = bl_get_data(bd);
0402 u8 data[2];
0403
0404 if (!ctx->prepared) {
0405 dev_dbg(&bd->dev, "lcd not ready yet for setting its backlight!\n");
0406 return -ENXIO;
0407 }
0408
0409 if (bd->props.power <= FB_BLANK_NORMAL) {
0410
0411
0412
0413
0414 data[0] = MIPI_DCS_SET_DISPLAY_BRIGHTNESS;
0415 data[1] = bd->props.brightness;
0416 otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data));
0417
0418
0419 data[1] = 0x24;
0420
0421 } else {
0422
0423 data[1] = 0;
0424 }
0425
0426
0427 data[0] = MIPI_DCS_WRITE_CONTROL_DISPLAY;
0428 otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data));
0429
0430 return 0;
0431 }
0432
0433 static const struct backlight_ops otm8009a_backlight_ops = {
0434 .update_status = otm8009a_backlight_update_status,
0435 };
0436
0437 static int otm8009a_probe(struct mipi_dsi_device *dsi)
0438 {
0439 struct device *dev = &dsi->dev;
0440 struct otm8009a *ctx;
0441 int ret;
0442
0443 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0444 if (!ctx)
0445 return -ENOMEM;
0446
0447 ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
0448 if (IS_ERR(ctx->reset_gpio)) {
0449 dev_err(dev, "cannot get reset-gpio\n");
0450 return PTR_ERR(ctx->reset_gpio);
0451 }
0452
0453 ctx->supply = devm_regulator_get(dev, "power");
0454 if (IS_ERR(ctx->supply)) {
0455 ret = PTR_ERR(ctx->supply);
0456 if (ret != -EPROBE_DEFER)
0457 dev_err(dev, "failed to request regulator: %d\n", ret);
0458 return ret;
0459 }
0460
0461 mipi_dsi_set_drvdata(dsi, ctx);
0462
0463 ctx->dev = dev;
0464
0465 dsi->lanes = 2;
0466 dsi->format = MIPI_DSI_FMT_RGB888;
0467 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
0468 MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS;
0469
0470 drm_panel_init(&ctx->panel, dev, &otm8009a_drm_funcs,
0471 DRM_MODE_CONNECTOR_DSI);
0472
0473 ctx->bl_dev = devm_backlight_device_register(dev, dev_name(dev),
0474 dsi->host->dev, ctx,
0475 &otm8009a_backlight_ops,
0476 NULL);
0477 if (IS_ERR(ctx->bl_dev)) {
0478 ret = PTR_ERR(ctx->bl_dev);
0479 dev_err(dev, "failed to register backlight: %d\n", ret);
0480 return ret;
0481 }
0482
0483 ctx->bl_dev->props.max_brightness = OTM8009A_BACKLIGHT_MAX;
0484 ctx->bl_dev->props.brightness = OTM8009A_BACKLIGHT_DEFAULT;
0485 ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
0486 ctx->bl_dev->props.type = BACKLIGHT_RAW;
0487
0488 drm_panel_add(&ctx->panel);
0489
0490 ret = mipi_dsi_attach(dsi);
0491 if (ret < 0) {
0492 dev_err(dev, "mipi_dsi_attach failed. Is host ready?\n");
0493 drm_panel_remove(&ctx->panel);
0494 return ret;
0495 }
0496
0497 return 0;
0498 }
0499
0500 static int otm8009a_remove(struct mipi_dsi_device *dsi)
0501 {
0502 struct otm8009a *ctx = mipi_dsi_get_drvdata(dsi);
0503
0504 mipi_dsi_detach(dsi);
0505 drm_panel_remove(&ctx->panel);
0506
0507 return 0;
0508 }
0509
0510 static const struct of_device_id orisetech_otm8009a_of_match[] = {
0511 { .compatible = "orisetech,otm8009a" },
0512 { }
0513 };
0514 MODULE_DEVICE_TABLE(of, orisetech_otm8009a_of_match);
0515
0516 static struct mipi_dsi_driver orisetech_otm8009a_driver = {
0517 .probe = otm8009a_probe,
0518 .remove = otm8009a_remove,
0519 .driver = {
0520 .name = "panel-orisetech-otm8009a",
0521 .of_match_table = orisetech_otm8009a_of_match,
0522 },
0523 };
0524 module_mipi_dsi_driver(orisetech_otm8009a_driver);
0525
0526 MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
0527 MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
0528 MODULE_DESCRIPTION("DRM driver for Orise Tech OTM8009A MIPI DSI panel");
0529 MODULE_LICENSE("GPL v2");