Guest User

Huawei BOE Panel

a guest
Nov 27th, 2024
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.66 KB | None | 0 0
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright (c) 2024 FIXME
  3. // Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
  4. //   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
  5.  
  6. #include <linux/backlight.h>
  7. #include <linux/delay.h>
  8. #include <linux/gpio/consumer.h>
  9. #include <linux/module.h>
  10. #include <linux/of.h>
  11. #include <linux/regulator/consumer.h>
  12.  
  13. #include <video/mipi_display.h>
  14.  
  15. #include <drm/drm_mipi_dsi.h>
  16. #include <drm/drm_modes.h>
  17. #include <drm/drm_panel.h>
  18. #include <drm/drm_probe_helper.h>
  19.  
  20. struct boe_nt51017_10_800p {
  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 *vcc_gpio;
  26.     struct gpio_desc *vled_gpio;
  27.    
  28. };
  29.  
  30. static inline
  31. struct boe_nt51017_10_800p *to_boe_nt51017_10_800p(struct drm_panel *panel)
  32. {
  33.     return container_of(panel, struct boe_nt51017_10_800p, panel);
  34. }
  35.  
  36. static void boe_nt51017_10_800p_reset(struct boe_nt51017_10_800p *ctx)
  37. {
  38.     gpiod_set_value_cansleep(ctx->reset_gpio, 0);
  39.     usleep_range(1000, 2000);
  40.     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  41.     msleep(20);
  42.     gpiod_set_value_cansleep(ctx->reset_gpio, 0);
  43.     msleep(120);
  44. }
  45.  
  46. static int boe_nt51017_10_800p_on(struct boe_nt51017_10_800p *ctx)
  47. {
  48.     struct mipi_dsi_device *dsi = ctx->dsi;
  49.  
  50.     mipi_dsi_dcs_write_seq(dsi, 0x83, 0x96);
  51.     mipi_dsi_dcs_write_seq(dsi, 0x84, 0x69);
  52.     mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
  53.     mipi_dsi_dcs_write_seq(dsi, 0x91, 0xc0);
  54.     mipi_dsi_dcs_write_seq(dsi, 0x92, 0x57);
  55.     mipi_dsi_dcs_write_seq(dsi, 0x93, 0x20);
  56.     mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_READ_PPS_CONTINUE, 0xff);
  57.     mipi_dsi_dcs_write_seq(dsi, 0xaa, 0xfa);
  58.     mipi_dsi_dcs_write_seq(dsi, 0xab, 0xf3);
  59.     mipi_dsi_dcs_write_seq(dsi, 0xac, 0xed);
  60.     mipi_dsi_dcs_write_seq(dsi, 0xad, 0xe7);
  61.     mipi_dsi_dcs_write_seq(dsi, 0xae, 0xe2);
  62.     mipi_dsi_dcs_write_seq(dsi, 0xaf, 0xdc);
  63.     mipi_dsi_dcs_write_seq(dsi, 0xb0, 0xd7);
  64.     mipi_dsi_dcs_write_seq(dsi, 0xb1, 0xd1);
  65.     mipi_dsi_dcs_write_seq(dsi, 0xb2, 0xcc);
  66.     mipi_dsi_dcs_write_seq(dsi, 0x99, 0x00);
  67.     mipi_dsi_dcs_write_seq(dsi, 0x83, 0x00);
  68.     mipi_dsi_dcs_write_seq(dsi, 0x84, 0x00);
  69.     mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x00);
  70.     mipi_dsi_dcs_write_seq(dsi, 0x96, 0x40);
  71.  
  72.     return 0;
  73. }
  74.  
  75. static int boe_nt51017_10_800p_off(struct boe_nt51017_10_800p *ctx)
  76. {
  77.     struct mipi_dsi_device *dsi = ctx->dsi;
  78.  
  79.     return 0;
  80. }
  81.  
  82. static int boe_nt51017_10_800p_prepare(struct drm_panel *panel)
  83. {
  84.     struct boe_nt51017_10_800p *ctx = to_boe_nt51017_10_800p(panel);
  85.     struct device *dev = &ctx->dsi->dev;
  86.     int ret;
  87.     gpiod_set_value_cansleep(ctx->vcc_gpio, 1);
  88.     gpiod_set_value_cansleep(ctx->vled_gpio, 1);
  89.     ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
  90.     if (ret < 0) {
  91.         dev_err(dev, "Failed to enable regulators: %d\n", ret);
  92.         return ret;
  93.     }
  94.  
  95.     boe_nt51017_10_800p_reset(ctx);
  96.  
  97.     ret = boe_nt51017_10_800p_on(ctx);
  98.     if (ret < 0) {
  99.         dev_err(dev, "Failed to initialize panel: %d\n", ret);
  100.         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  101.         regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
  102.         return ret;
  103.     }
  104.  
  105.     return 0;
  106. }
  107.  
  108. static int boe_nt51017_10_800p_unprepare(struct drm_panel *panel)
  109. {
  110.     struct boe_nt51017_10_800p *ctx = to_boe_nt51017_10_800p(panel);
  111.     struct device *dev = &ctx->dsi->dev;
  112.     int ret;
  113.    
  114.     ret = boe_nt51017_10_800p_off(ctx);
  115.     if (ret < 0)
  116.         dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
  117.  
  118.     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
  119.     gpiod_set_value_cansleep(ctx->vcc_gpio, 0);
  120.     gpiod_set_value_cansleep(ctx->vled_gpio, 0);
  121.     regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
  122.  
  123.     return 0;
  124. }
  125.  
  126. static const struct drm_display_mode boe_nt51017_10_800p_mode = {
  127.     .clock = (800 + 164 + 8 + 136) * (1280 + 56 + 4 + 42) * 60 / 1000,
  128.     .hdisplay = 800,
  129.     .hsync_start = 800 + 164,
  130.     .hsync_end = 800 + 164 + 8,
  131.     .htotal = 800 + 164 + 8 + 136,
  132.     .vdisplay = 1280,
  133.     .vsync_start = 1280 + 56,
  134.     .vsync_end = 1280 + 56 + 4,
  135.     .vtotal = 1280 + 56 + 4 + 42,
  136.     .width_mm = 0,
  137.     .height_mm = 0,
  138.     .type = DRM_MODE_TYPE_DRIVER,
  139. };
  140.  
  141. static int boe_nt51017_10_800p_get_modes(struct drm_panel *panel,
  142.                      struct drm_connector *connector)
  143. {
  144.     return drm_connector_helper_get_modes_fixed(connector, &boe_nt51017_10_800p_mode);
  145. }
  146.  
  147. static const struct drm_panel_funcs boe_nt51017_10_800p_panel_funcs = {
  148.     .prepare = boe_nt51017_10_800p_prepare,
  149.     .unprepare = boe_nt51017_10_800p_unprepare,
  150.     .get_modes = boe_nt51017_10_800p_get_modes,
  151. };
  152.  
  153. static int boe_nt51017_10_800p_bl_update_status(struct backlight_device *bl)
  154. {
  155.     struct mipi_dsi_device *dsi = bl_get_data(bl);
  156.     u16 brightness = backlight_get_brightness(bl);
  157.     int ret;
  158.  
  159.     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  160.  
  161.     ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
  162.     if (ret < 0)
  163.         return ret;
  164.  
  165.     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  166.  
  167.     return 0;
  168. }
  169.  
  170. // TODO: Check if /sys/class/backlight/.../actual_brightness actually returns
  171. // correct values. If not, remove this function.
  172. static int boe_nt51017_10_800p_bl_get_brightness(struct backlight_device *bl)
  173. {
  174.     struct mipi_dsi_device *dsi = bl_get_data(bl);
  175.     u16 brightness;
  176.     int ret;
  177.  
  178.     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
  179.  
  180.     ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
  181.     if (ret < 0)
  182.         return ret;
  183.  
  184.     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  185.  
  186.     return brightness & 0xff;
  187. }
  188.  
  189. static const struct backlight_ops boe_nt51017_10_800p_bl_ops = {
  190.     .update_status = boe_nt51017_10_800p_bl_update_status,
  191.     .get_brightness = boe_nt51017_10_800p_bl_get_brightness,
  192. };
  193.  
  194. static struct backlight_device *
  195. boe_nt51017_10_800p_create_backlight(struct mipi_dsi_device *dsi)
  196. {
  197.     struct device *dev = &dsi->dev;
  198.     const struct backlight_properties props = {
  199.         .type = BACKLIGHT_RAW,
  200.         .brightness = 255,
  201.         .max_brightness = 255,
  202.     };
  203.  
  204.     return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
  205.                           &boe_nt51017_10_800p_bl_ops, &props);
  206. }
  207.  
  208. static int boe_nt51017_10_800p_probe(struct mipi_dsi_device *dsi)
  209. {
  210.     struct device *dev = &dsi->dev;
  211.     struct boe_nt51017_10_800p *ctx;
  212.     int ret;
  213.  
  214.     ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
  215.     if (!ctx)
  216.         return -ENOMEM;
  217.  
  218.     ctx->supplies[0].supply = "vddio";
  219.     ctx->supplies[1].supply = "vdd";
  220.     ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
  221.                       ctx->supplies);
  222.     if (ret < 0)
  223.         return dev_err_probe(dev, ret, "Failed to get regulators\n");
  224.  
  225.     ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
  226.     if (IS_ERR(ctx->reset_gpio))
  227.         return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
  228.                      "Failed to get reset-gpios\n");
  229.     ctx->vcc_gpio = devm_gpiod_get(dev, "vcc", GPIOD_OUT_HIGH);
  230.     if (IS_ERR(ctx->vcc_gpio))
  231.         return dev_err_probe(dev, PTR_ERR(ctx->vcc_gpio),
  232.                      "Failed to get vcc-gpios\n");
  233.     ctx->vled_gpio = devm_gpiod_get(dev, "vled", GPIOD_OUT_HIGH);
  234.     if (IS_ERR(ctx->vled_gpio))
  235.         return dev_err_probe(dev, PTR_ERR(ctx->vled_gpio),
  236.                      "Failed to get vled-gpios\n");
  237.     ctx->dsi = dsi;
  238.     mipi_dsi_set_drvdata(dsi, ctx);
  239.  
  240.     dsi->lanes = 4;
  241.     dsi->format = MIPI_DSI_FMT_RGB888;
  242.     dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
  243.               MIPI_DSI_MODE_VIDEO_HSE |
  244.               MIPI_DSI_MODE_LPM;
  245.  
  246.     drm_panel_init(&ctx->panel, dev, &boe_nt51017_10_800p_panel_funcs,
  247.                DRM_MODE_CONNECTOR_DSI);
  248.     ctx->panel.prepare_prev_first = true;
  249.  
  250.     ctx->panel.backlight = boe_nt51017_10_800p_create_backlight(dsi);
  251.     if (IS_ERR(ctx->panel.backlight))
  252.         return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
  253.                      "Failed to create backlight\n");
  254.  
  255.     drm_panel_add(&ctx->panel);
  256.  
  257.     ret = mipi_dsi_attach(dsi);
  258.     if (ret < 0) {
  259.         drm_panel_remove(&ctx->panel);
  260.         return dev_err_probe(dev, ret, "Failed to attach to DSI host\n");
  261.     }
  262.  
  263.     return 0;
  264. }
  265.  
  266. static void boe_nt51017_10_800p_remove(struct mipi_dsi_device *dsi)
  267. {
  268.     struct boe_nt51017_10_800p *ctx = mipi_dsi_get_drvdata(dsi);
  269.     int ret;
  270.  
  271.     ret = mipi_dsi_detach(dsi);
  272.     if (ret < 0)
  273.         dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
  274.  
  275.     drm_panel_remove(&ctx->panel);
  276. }
  277.  
  278. static const struct of_device_id boe_nt51017_10_800p_of_match[] = {
  279.     { .compatible = "huawei,boe-nt51017" }, // FIXME
  280.     { /* sentinel */ }
  281. };
  282. MODULE_DEVICE_TABLE(of, boe_nt51017_10_800p_of_match);
  283.  
  284. static struct mipi_dsi_driver boe_nt51017_10_800p_driver = {
  285.     .probe = boe_nt51017_10_800p_probe,
  286.     .remove = boe_nt51017_10_800p_remove,
  287.     .driver = {
  288.         .name = "panel-huawei-hwt1a21w-boe-nt51017",
  289.         .of_match_table = boe_nt51017_10_800p_of_match,
  290.     },
  291. };
  292. module_mipi_dsi_driver(boe_nt51017_10_800p_driver);
  293.  
  294. MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
  295. MODULE_DESCRIPTION("DRM driver for BOE_NT51017_10_800P_VIDEO");
  296. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment