Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/panel/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  panel-synaptics-r63353.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Synaptics R63353 Controller driver
 *
 * Copyright (C) 2020 BSH Hausgerate GmbH
 */


#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/media-bus-format.h>

#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>

#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>

#include <video/mipi_display.h>

#define R63353_INSTR(...) { \
  .len = sizeof((u8[]) {__VA_ARGS__}), \
  .data = (u8[]){__VA_ARGS__} \
 }

struct r63353_instr {
 size_t len;
 const u8 *data;
};

static const struct r63353_instr sharp_ls068b3sx02_init[] = {
 R63353_INSTR(0x51, 0xff),
 R63353_INSTR(0x53, 0x0c),
 R63353_INSTR(0x55, 0x00),
 R63353_INSTR(0x84, 0x00),
 R63353_INSTR(0x29),
};

struct r63353_desc {
 const char *name;
 const struct r63353_instr *init;
 const size_t init_length;
 const struct drm_display_mode *mode;
 u32 width_mm;
 u32 height_mm;
};

struct r63353_panel {
 struct drm_panel base;
 struct mipi_dsi_device *dsi;

 struct gpio_desc *reset_gpio;
 struct regulator *dvdd;
 struct regulator *avdd;

 struct r63353_desc *pdata;
};

static inline struct r63353_panel *to_r63353_panel(struct drm_panel *panel)
{
 return container_of(panel, struct r63353_panel, base);
}

static int r63353_panel_power_on(struct r63353_panel *rpanel)
{
 struct mipi_dsi_device *dsi = rpanel->dsi;
 struct device *dev = &dsi->dev;
 int ret;

 ret = regulator_enable(rpanel->avdd);
 if (ret) {
  dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret);
  return ret;
 }

 usleep_range(15000, 25000);

 ret = regulator_enable(rpanel->dvdd);
 if (ret) {
  dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret);
  regulator_disable(rpanel->avdd);
  return ret;
 }

 usleep_range(300000, 350000);
 gpiod_set_value(rpanel->reset_gpio, 1);
 usleep_range(15000, 25000);

 return 0;
}

static int r63353_panel_power_off(struct r63353_panel *rpanel)
{
 gpiod_set_value(rpanel->reset_gpio, 0);
 regulator_disable(rpanel->dvdd);
 regulator_disable(rpanel->avdd);

 return 0;
}

static int r63353_panel_activate(struct r63353_panel *rpanel)
{
 struct mipi_dsi_device *dsi = rpanel->dsi;
 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
 int i;

 mipi_dsi_dcs_soft_reset_multi(&dsi_ctx);

 mipi_dsi_usleep_range(&dsi_ctx, 15000, 17000);

 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);

 for (i = 0; i < rpanel->pdata->init_length; i++) {
  const struct r63353_instr *instr = &rpanel->pdata->init[i];

  mipi_dsi_dcs_write_buffer_multi(&dsi_ctx, instr->data,
      instr->len);
 }

 mipi_dsi_msleep(&dsi_ctx, 120);

 mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);

 mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000);

 mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);

 if (dsi_ctx.accum_err)
  gpiod_set_value(rpanel->reset_gpio, 0);

 return dsi_ctx.accum_err;
}

static int r63353_panel_prepare(struct drm_panel *panel)
{
 struct r63353_panel *rpanel = to_r63353_panel(panel);
 struct mipi_dsi_device *dsi = rpanel->dsi;
 struct device *dev = &dsi->dev;
 int ret;

 dev_dbg(dev, "Preparing\n");

 ret = r63353_panel_power_on(rpanel);
 if (ret)
  return ret;

 ret = r63353_panel_activate(rpanel);
 if (ret) {
  r63353_panel_power_off(rpanel);
  return ret;
 }

 dev_dbg(dev, "Prepared\n");
 return 0;
}

static void r63353_panel_deactivate(struct r63353_panel *rpanel)
{
 struct mipi_dsi_device *dsi = rpanel->dsi;
 struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };

 mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);

 mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000);

 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
}

static int r63353_panel_unprepare(struct drm_panel *panel)
{
 struct r63353_panel *rpanel = to_r63353_panel(panel);

 r63353_panel_deactivate(rpanel);
 r63353_panel_power_off(rpanel);

 return 0;
}

static const struct drm_display_mode sharp_ls068b3sx02_timing = {
 .clock = 70000,
 .hdisplay = 640,
 .hsync_start = 640 + 35,
 .hsync_end = 640 + 35 + 2,
 .htotal = 640 + 35 + 2 + 150,
 .vdisplay = 1280,
 .vsync_start = 1280 + 2,
 .vsync_end = 1280 + 2 + 4,
 .vtotal = 1280 + 2 + 4 + 0,
};

static int r63353_panel_get_modes(struct drm_panel *panel,
      struct drm_connector *connector)
{
 struct r63353_panel *rpanel = to_r63353_panel(panel);
 struct drm_display_mode *mode;
 static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;

 mode = drm_mode_duplicate(connector->dev, rpanel->pdata->mode);
 if (!mode)
  return -ENOMEM;

 drm_mode_set_name(mode);
 drm_mode_probed_add(connector, mode);

 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 connector->display_info.width_mm = rpanel->pdata->width_mm;
 connector->display_info.height_mm = rpanel->pdata->height_mm;

 drm_display_info_set_bus_formats(&connector->display_info,
      &bus_format, 1);

 return 1;
}

static const struct drm_panel_funcs r63353_panel_funcs = {
 .prepare = r63353_panel_prepare,
 .unprepare = r63353_panel_unprepare,
 .get_modes = r63353_panel_get_modes,
};

static int r63353_panel_probe(struct mipi_dsi_device *dsi)
{
 int ret = 0;
 struct device *dev = &dsi->dev;
 struct r63353_panel *panel;

 panel = devm_drm_panel_alloc(dev, struct r63353_panel, base,
         &r63353_panel_funcs,
         DRM_MODE_CONNECTOR_DSI);
 if (IS_ERR(panel))
  return PTR_ERR(panel);

 mipi_dsi_set_drvdata(dsi, panel);
 panel->dsi = dsi;
 panel->pdata = (struct r63353_desc *)of_device_get_match_data(dev);

 dev_info(dev, "Panel %s\n", panel->pdata->name);

 dsi->lanes = 2;
 dsi->format = MIPI_DSI_FMT_RGB888;
 dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
     MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM |
     MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET;

 panel->dvdd = devm_regulator_get(dev, "dvdd");
 if (IS_ERR(panel->dvdd))
  return PTR_ERR(panel->dvdd);
 panel->avdd = devm_regulator_get(dev, "avdd");
 if (IS_ERR(panel->avdd))
  return PTR_ERR(panel->avdd);

 panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
 if (IS_ERR(panel->reset_gpio)) {
  dev_err(dev, "failed to get RESET GPIO\n");
  return PTR_ERR(panel->reset_gpio);
 }

 panel->base.prepare_prev_first = true;
 ret = drm_panel_of_backlight(&panel->base);
 if (ret)
  return ret;

 drm_panel_add(&panel->base);

 ret = mipi_dsi_attach(dsi);
 if (ret < 0) {
  dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
  drm_panel_remove(&panel->base);
  return ret;
 }

 return ret;
}

static void r63353_panel_remove(struct mipi_dsi_device *dsi)
{
 struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
 struct device *dev = &dsi->dev;
 int ret;

 ret = mipi_dsi_detach(dsi);
 if (ret < 0)
  dev_err(dev, "Failed to detach from host (%d)\n", ret);

 drm_panel_remove(&rpanel->base);
}

static void r63353_panel_shutdown(struct mipi_dsi_device *dsi)
{
 struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);

 drm_panel_unprepare(&rpanel->base);
}

static const struct r63353_desc sharp_ls068b3sx02_data = {
 .name = "Sharp LS068B3SX02",
 .mode = &sharp_ls068b3sx02_timing,
 .init = sharp_ls068b3sx02_init,
 .init_length = ARRAY_SIZE(sharp_ls068b3sx02_init),
 .width_mm = 68,
 .height_mm = 159,
};

static const struct of_device_id r63353_of_match[] = {
 { .compatible = "sharp,ls068b3sx02", .data = &sharp_ls068b3sx02_data },
 { }
};

MODULE_DEVICE_TABLE(of, r63353_of_match);

static struct mipi_dsi_driver r63353_panel_driver = {
 .driver = {
     .name = "r63353-dsi",
     .of_match_table = r63353_of_match,
 },
 .probe = r63353_panel_probe,
 .remove = r63353_panel_remove,
 .shutdown = r63353_panel_shutdown,
};

module_mipi_dsi_driver(r63353_panel_driver);

MODULE_AUTHOR("Matthias Proske ");
MODULE_AUTHOR("Michael Trimarchi ");
MODULE_DESCRIPTION("Synaptics R63353 Controller Driver");
MODULE_LICENSE("GPL");

Messung V0.5
C=95 H=92 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.