Lines Matching +full:panel +full:- +full:dsi +full:- +full:cm
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Generic DSI Command Mode panel driver
5 * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
44 struct mipi_dsi_device *dsi;
45 struct drm_panel panel;
72 static inline struct panel_drv_data *panel_to_ddata(struct drm_panel *panel)
74 return container_of(panel, struct panel_drv_data, panel);
81 if (ddata->bldev)
82 backlight = ddata->bldev;
83 else if (ddata->extbldev)
84 backlight = ddata->extbldev;
96 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
97 ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
102 unsigned long wait = ddata->hw_guard_end - jiffies;
104 if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
112 return mipi_dsi_dcs_read(ddata->dsi, dcs_cmd, data, 1);
117 return mipi_dsi_dcs_write(ddata->dsi, dcs_cmd, ¶m, 1);
127 r = mipi_dsi_dcs_enter_sleep_mode(ddata->dsi);
144 r = mipi_dsi_dcs_exit_sleep_mode(ddata->dsi);
174 struct mipi_dsi_device *dsi = ddata->dsi;
177 r = mipi_dsi_dcs_set_column_address(dsi, 0, ddata->mode.hdisplay - 1);
181 r = mipi_dsi_dcs_set_page_address(dsi, 0, ddata->mode.vdisplay - 1);
190 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
194 dev_dbg(&ddata->dsi->dev, "update brightness to %d\n", level);
196 mutex_lock(&ddata->lock);
198 if (ddata->enabled)
202 mutex_unlock(&ddata->lock);
222 int r = -ENODEV;
224 mutex_lock(&ddata->lock);
226 if (ddata->enabled)
229 mutex_unlock(&ddata->lock);
242 int r = -ENODEV;
244 mutex_lock(&ddata->lock);
246 if (ddata->enabled)
249 mutex_unlock(&ddata->lock);
272 gpiod_set_value(ddata->reset_gpio, 1);
274 /* reset the panel */
275 gpiod_set_value(ddata->reset_gpio, 0);
278 gpiod_set_value(ddata->reset_gpio, 1);
290 ddata->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
309 r = mipi_dsi_dcs_set_pixel_format(ddata->dsi, MIPI_DCS_PIXEL_FMT_24BIT);
317 r = mipi_dsi_dcs_set_display_on(ddata->dsi);
321 if (ddata->panel_data->te_support) {
322 r = mipi_dsi_dcs_set_tear_on(ddata->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
327 /* possible panel bug */
330 ddata->enabled = true;
332 if (!ddata->intro_printed) {
333 dev_info(&ddata->dsi->dev, "panel revision %02x.%02x.%02x\n",
335 ddata->intro_printed = true;
338 ddata->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
342 dev_err(&ddata->dsi->dev, "error while enabling panel, issuing HW reset\n");
353 ddata->enabled = false;
355 r = mipi_dsi_dcs_set_display_off(ddata->dsi);
360 dev_err(&ddata->dsi->dev,
361 "error disabling panel, issuing HW reset\n");
368 static int dsicm_prepare(struct drm_panel *panel)
370 struct panel_drv_data *ddata = panel_to_ddata(panel);
373 r = regulator_bulk_enable(ARRAY_SIZE(ddata->supplies), ddata->supplies);
375 dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
380 static int dsicm_enable(struct drm_panel *panel)
382 struct panel_drv_data *ddata = panel_to_ddata(panel);
385 mutex_lock(&ddata->lock);
391 mutex_unlock(&ddata->lock);
397 dev_err(&ddata->dsi->dev, "enable failed (%d)\n", r);
398 mutex_unlock(&ddata->lock);
402 static int dsicm_unprepare(struct drm_panel *panel)
404 struct panel_drv_data *ddata = panel_to_ddata(panel);
407 r = regulator_bulk_disable(ARRAY_SIZE(ddata->supplies), ddata->supplies);
409 dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
414 static int dsicm_disable(struct drm_panel *panel)
416 struct panel_drv_data *ddata = panel_to_ddata(panel);
421 mutex_lock(&ddata->lock);
425 mutex_unlock(&ddata->lock);
430 static int dsicm_get_modes(struct drm_panel *panel,
433 struct panel_drv_data *ddata = panel_to_ddata(panel);
436 mode = drm_mode_duplicate(connector->dev, &ddata->mode);
438 dev_err(&ddata->dsi->dev, "failed to add mode %ux%ux@%u kHz\n",
439 ddata->mode.hdisplay, ddata->mode.vdisplay,
440 ddata->mode.clock);
441 return -ENOMEM;
444 connector->display_info.width_mm = ddata->panel_data->width_mm;
445 connector->display_info.height_mm = ddata->panel_data->height_mm;
460 static int dsicm_probe_of(struct mipi_dsi_device *dsi)
463 struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
465 struct drm_display_mode *mode = &ddata->mode;
467 ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
468 if (IS_ERR(ddata->reset_gpio)) {
469 err = PTR_ERR(ddata->reset_gpio);
470 dev_err(&dsi->dev, "reset gpio request failed: %d", err);
474 mode->hdisplay = mode->hsync_start = mode->hsync_end = mode->htotal =
475 ddata->panel_data->xres;
476 mode->vdisplay = mode->vsync_start = mode->vsync_end = mode->vtotal =
477 ddata->panel_data->yres;
478 mode->clock = ddata->panel_data->xres * ddata->panel_data->yres *
479 ddata->panel_data->refresh / 1000;
480 mode->width_mm = ddata->panel_data->width_mm;
481 mode->height_mm = ddata->panel_data->height_mm;
482 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
485 ddata->supplies[0].supply = "vpnl";
486 ddata->supplies[1].supply = "vddi";
487 err = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(ddata->supplies),
488 ddata->supplies);
492 backlight = devm_of_find_backlight(&dsi->dev);
498 ddata->extbldev = backlight;
500 ddata->use_dsi_backlight = true;
505 static int dsicm_probe(struct mipi_dsi_device *dsi)
509 struct device *dev = &dsi->dev;
514 ddata = devm_drm_panel_alloc(dev, struct panel_drv_data, panel,
519 mipi_dsi_set_drvdata(dsi, ddata);
520 ddata->dsi = dsi;
522 ddata->panel_data = of_device_get_match_data(dev);
523 if (!ddata->panel_data)
524 return -ENODEV;
526 r = dsicm_probe_of(dsi);
530 mutex_init(&ddata->lock);
534 if (ddata->use_dsi_backlight) {
546 ddata->bldev = bldev;
549 r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
555 dsi->lanes = 2;
556 dsi->format = MIPI_DSI_FMT_RGB888;
557 dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
559 dsi->hs_rate = ddata->panel_data->max_hs_rate;
560 dsi->lp_rate = ddata->panel_data->max_lp_rate;
562 drm_panel_add(&ddata->panel);
564 r = mipi_dsi_attach(dsi);
571 drm_panel_remove(&ddata->panel);
572 sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
574 if (ddata->extbldev)
575 put_device(&ddata->extbldev->dev);
580 static void dsicm_remove(struct mipi_dsi_device *dsi)
582 struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
584 dev_dbg(&dsi->dev, "remove\n");
586 mipi_dsi_detach(dsi);
588 drm_panel_remove(&ddata->panel);
590 sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
592 if (ddata->extbldev)
593 put_device(&ddata->extbldev->dev);
632 { .compatible = "motorola,droid4-panel", &droid4_data },
642 .name = "panel-dsi-cm",
649 MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");