Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Novatek NT35950 DriverIC panels driver
0004  *
0005  * Copyright (c) 2021 AngeloGioacchino Del Regno
0006  *                    <angelogioacchino.delregno@somainline.org>
0007  */
0008 #include <linux/delay.h>
0009 #include <linux/gpio/consumer.h>
0010 #include <linux/module.h>
0011 #include <linux/of_device.h>
0012 #include <linux/of_graph.h>
0013 #include <linux/regulator/consumer.h>
0014 
0015 #include <drm/drm_connector.h>
0016 #include <drm/drm_crtc.h>
0017 #include <drm/drm_mipi_dsi.h>
0018 #include <drm/drm_modes.h>
0019 #include <drm/drm_panel.h>
0020 
0021 #define MCS_CMD_MAUCCTR         0xf0 /* Manufacturer command enable */
0022 #define MCS_PARAM_SCALER_FUNCTION   0x58 /* Scale-up function */
0023 #define MCS_PARAM_SCALEUP_MODE      0xc9
0024  #define MCS_SCALEUP_SIMPLE     0x0
0025  #define MCS_SCALEUP_BILINEAR       BIT(0)
0026  #define MCS_SCALEUP_DUPLICATE      (BIT(0) | BIT(4))
0027 
0028 /* VESA Display Stream Compression param */
0029 #define MCS_PARAM_VESA_DSC_ON       0x03
0030 
0031 /* Data Compression mode */
0032 #define MCS_PARAM_DATA_COMPRESSION  0x90
0033  #define MCS_DATA_COMPRESSION_NONE  0x00
0034  #define MCS_DATA_COMPRESSION_FBC   0x02
0035  #define MCS_DATA_COMPRESSION_DSC   0x03
0036 
0037 /* Display Output control */
0038 #define MCS_PARAM_DISP_OUTPUT_CTRL  0xb4
0039  #define MCS_DISP_OUT_SRAM_EN       BIT(0)
0040  #define MCS_DISP_OUT_VIDEO_MODE    BIT(4)
0041 
0042 /* VESA Display Stream Compression setting */
0043 #define MCS_PARAM_VESA_DSC_SETTING  0xc0
0044 
0045 /* SubPixel Rendering (SPR) */
0046 #define MCS_PARAM_SPR_EN        0xe3
0047 #define MCS_PARAM_SPR_MODE      0xef
0048  #define MCS_SPR_MODE_YYG_RAINBOW_RGB   0x01
0049 
0050 #define NT35950_VREG_MAX        4
0051 
0052 struct nt35950 {
0053     struct drm_panel panel;
0054     struct drm_connector *connector;
0055     struct mipi_dsi_device *dsi[2];
0056     struct regulator_bulk_data vregs[NT35950_VREG_MAX];
0057     struct gpio_desc *reset_gpio;
0058     const struct nt35950_panel_desc *desc;
0059 
0060     int cur_mode;
0061     u8 last_page;
0062     bool prepared;
0063 };
0064 
0065 struct nt35950_panel_mode {
0066     const struct drm_display_mode mode;
0067 
0068     bool enable_sram;
0069     bool is_video_mode;
0070     u8 scaler_on;
0071     u8 scaler_mode;
0072     u8 compression;
0073     u8 spr_en;
0074     u8 spr_mode;
0075 };
0076 
0077 struct nt35950_panel_desc {
0078     const char *model_name;
0079     const struct mipi_dsi_device_info dsi_info;
0080     const struct nt35950_panel_mode *mode_data;
0081 
0082     bool is_dual_dsi;
0083     u8 num_lanes;
0084     u8 num_modes;
0085 };
0086 
0087 static inline struct nt35950 *to_nt35950(struct drm_panel *panel)
0088 {
0089     return container_of(panel, struct nt35950, panel);
0090 }
0091 
0092 #define dsi_dcs_write_seq(dsi, seq...) do {             \
0093         static const u8 d[] = { seq };              \
0094         int ret;                        \
0095         ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
0096         if (ret < 0)                        \
0097             return ret;                 \
0098     } while (0)
0099 
0100 static void nt35950_reset(struct nt35950 *nt)
0101 {
0102     gpiod_set_value_cansleep(nt->reset_gpio, 1);
0103     usleep_range(12000, 13000);
0104     gpiod_set_value_cansleep(nt->reset_gpio, 0);
0105     usleep_range(300, 400);
0106     gpiod_set_value_cansleep(nt->reset_gpio, 1);
0107     usleep_range(12000, 13000);
0108 }
0109 
0110 /*
0111  * nt35950_set_cmd2_page - Select manufacturer control (CMD2) page
0112  * @nt:   Main driver structure
0113  * @page: Page number (0-7)
0114  *
0115  * Return: Number of transferred bytes or negative number on error
0116  */
0117 static int nt35950_set_cmd2_page(struct nt35950 *nt, u8 page)
0118 {
0119     const u8 mauc_cmd2_page[] = { MCS_CMD_MAUCCTR, 0x55, 0xaa, 0x52,
0120                       0x08, page };
0121     int ret;
0122 
0123     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], mauc_cmd2_page,
0124                     ARRAY_SIZE(mauc_cmd2_page));
0125     if (ret < 0)
0126         return ret;
0127 
0128     nt->last_page = page;
0129     return 0;
0130 }
0131 
0132 /*
0133  * nt35950_set_data_compression - Set data compression mode
0134  * @nt:        Main driver structure
0135  * @comp_mode: Compression mode
0136  *
0137  * Return: Number of transferred bytes or negative number on error
0138  */
0139 static int nt35950_set_data_compression(struct nt35950 *nt, u8 comp_mode)
0140 {
0141     u8 cmd_data_compression[] = { MCS_PARAM_DATA_COMPRESSION, comp_mode };
0142     u8 cmd_vesa_dsc_on[] = { MCS_PARAM_VESA_DSC_ON, !!comp_mode };
0143     u8 cmd_vesa_dsc_setting[] = { MCS_PARAM_VESA_DSC_SETTING, 0x03 };
0144     u8 last_page = nt->last_page;
0145     int ret;
0146 
0147     /* Set CMD2 Page 0 if we're not there yet */
0148     if (last_page != 0) {
0149         ret = nt35950_set_cmd2_page(nt, 0);
0150         if (ret < 0)
0151             return ret;
0152     }
0153 
0154     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_data_compression,
0155                     ARRAY_SIZE(cmd_data_compression));
0156     if (ret < 0)
0157         return ret;
0158 
0159     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_vesa_dsc_on,
0160                     ARRAY_SIZE(cmd_vesa_dsc_on));
0161     if (ret < 0)
0162         return ret;
0163 
0164     /* Set the vesa dsc setting on Page 4 */
0165     ret = nt35950_set_cmd2_page(nt, 4);
0166     if (ret < 0)
0167         return ret;
0168 
0169     /* Display Stream Compression setting, always 0x03 */
0170     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_vesa_dsc_setting,
0171                     ARRAY_SIZE(cmd_vesa_dsc_setting));
0172     if (ret < 0)
0173         return ret;
0174 
0175     /* Get back to the previously set page */
0176     return nt35950_set_cmd2_page(nt, last_page);
0177 }
0178 
0179 /*
0180  * nt35950_set_scaler - Enable/disable resolution upscaling
0181  * @nt:        Main driver structure
0182  * @scale_up:  Scale up function control
0183  *
0184  * Return: Number of transferred bytes or negative number on error
0185  */
0186 static int nt35950_set_scaler(struct nt35950 *nt, u8 scale_up)
0187 {
0188     u8 cmd_scaler[] = { MCS_PARAM_SCALER_FUNCTION, scale_up };
0189 
0190     return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_scaler,
0191                      ARRAY_SIZE(cmd_scaler));
0192 }
0193 
0194 /*
0195  * nt35950_set_scale_mode - Resolution upscaling mode
0196  * @nt:   Main driver structure
0197  * @mode: Scaler mode (MCS_DATA_COMPRESSION_*)
0198  *
0199  * Return: Number of transferred bytes or negative number on error
0200  */
0201 static int nt35950_set_scale_mode(struct nt35950 *nt, u8 mode)
0202 {
0203     u8 cmd_scaler[] = { MCS_PARAM_SCALEUP_MODE, mode };
0204 
0205     return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_scaler,
0206                      ARRAY_SIZE(cmd_scaler));
0207 }
0208 
0209 /*
0210  * nt35950_inject_black_image - Display a completely black image
0211  * @nt:   Main driver structure
0212  *
0213  * After IC setup, the attached panel may show random data
0214  * due to driveric behavior changes (resolution, compression,
0215  * scaling, etc). This function, called after parameters setup,
0216  * makes the driver ic to output a completely black image to
0217  * the display.
0218  * It makes sense to push a black image before sending the sleep-out
0219  * and display-on commands.
0220  *
0221  * Return: Number of transferred bytes or negative number on error
0222  */
0223 static int nt35950_inject_black_image(struct nt35950 *nt)
0224 {
0225     const u8 cmd0_black_img[] = { 0x6f, 0x01 };
0226     const u8 cmd1_black_img[] = { 0xf3, 0x10 };
0227     u8 cmd_test[] = { 0xff, 0xaa, 0x55, 0xa5, 0x80 };
0228     int ret;
0229 
0230     /* Enable test command */
0231     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_test, ARRAY_SIZE(cmd_test));
0232     if (ret < 0)
0233         return ret;
0234 
0235     /* Send a black image */
0236     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd0_black_img,
0237                     ARRAY_SIZE(cmd0_black_img));
0238     if (ret < 0)
0239         return ret;
0240     ret = mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd1_black_img,
0241                     ARRAY_SIZE(cmd1_black_img));
0242     if (ret < 0)
0243         return ret;
0244 
0245     /* Disable test command */
0246     cmd_test[ARRAY_SIZE(cmd_test) - 1] = 0x00;
0247     return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_test, ARRAY_SIZE(cmd_test));
0248 }
0249 
0250 /*
0251  * nt35950_set_dispout - Set Display Output register parameters
0252  * @nt:    Main driver structure
0253  *
0254  * Return: Number of transferred bytes or negative number on error
0255  */
0256 static int nt35950_set_dispout(struct nt35950 *nt)
0257 {
0258     u8 cmd_dispout[] = { MCS_PARAM_DISP_OUTPUT_CTRL, 0x00 };
0259     const struct nt35950_panel_mode *mode_data = nt->desc->mode_data;
0260 
0261     if (mode_data[nt->cur_mode].is_video_mode)
0262         cmd_dispout[1] |= MCS_DISP_OUT_VIDEO_MODE;
0263     if (mode_data[nt->cur_mode].enable_sram)
0264         cmd_dispout[1] |= MCS_DISP_OUT_SRAM_EN;
0265 
0266     return mipi_dsi_dcs_write_buffer(nt->dsi[0], cmd_dispout,
0267                      ARRAY_SIZE(cmd_dispout));
0268 }
0269 
0270 static int nt35950_get_current_mode(struct nt35950 *nt)
0271 {
0272     struct drm_connector *connector = nt->connector;
0273     struct drm_crtc_state *crtc_state;
0274     int i;
0275 
0276     /* Return the default (first) mode if no info available yet */
0277     if (!connector->state || !connector->state->crtc)
0278         return 0;
0279 
0280     crtc_state = connector->state->crtc->state;
0281 
0282     for (i = 0; i < nt->desc->num_modes; i++) {
0283         if (drm_mode_match(&crtc_state->mode,
0284                    &nt->desc->mode_data[i].mode,
0285                    DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_CLOCK))
0286             return i;
0287     }
0288 
0289     return 0;
0290 }
0291 
0292 static int nt35950_on(struct nt35950 *nt)
0293 {
0294     const struct nt35950_panel_mode *mode_data = nt->desc->mode_data;
0295     struct mipi_dsi_device *dsi = nt->dsi[0];
0296     struct device *dev = &dsi->dev;
0297     int ret;
0298 
0299     nt->cur_mode = nt35950_get_current_mode(nt);
0300     nt->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM;
0301     nt->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM;
0302 
0303     ret = nt35950_set_cmd2_page(nt, 0);
0304     if (ret < 0)
0305         return ret;
0306 
0307     ret = nt35950_set_data_compression(nt, mode_data[nt->cur_mode].compression);
0308     if (ret < 0)
0309         return ret;
0310 
0311     ret = nt35950_set_scale_mode(nt, mode_data[nt->cur_mode].scaler_mode);
0312     if (ret < 0)
0313         return ret;
0314 
0315     ret = nt35950_set_scaler(nt, mode_data[nt->cur_mode].scaler_on);
0316     if (ret < 0)
0317         return ret;
0318 
0319     ret = nt35950_set_dispout(nt);
0320     if (ret < 0)
0321         return ret;
0322 
0323     ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
0324     if (ret < 0) {
0325         dev_err(dev, "Failed to set tear on: %d\n", ret);
0326         return ret;
0327     }
0328 
0329     ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0);
0330     if (ret < 0) {
0331         dev_err(dev, "Failed to set tear scanline: %d\n", ret);
0332         return ret;
0333     }
0334 
0335     /* CMD2 Page 1 */
0336     ret = nt35950_set_cmd2_page(nt, 1);
0337     if (ret < 0)
0338         return ret;
0339 
0340     /* Unknown command */
0341     dsi_dcs_write_seq(dsi, 0xd4, 0x88, 0x88);
0342 
0343     /* CMD2 Page 7 */
0344     ret = nt35950_set_cmd2_page(nt, 7);
0345     if (ret < 0)
0346         return ret;
0347 
0348     /* Enable SubPixel Rendering */
0349     dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_EN, 0x01);
0350 
0351     /* SPR Mode: YYG Rainbow-RGB */
0352     dsi_dcs_write_seq(dsi, MCS_PARAM_SPR_MODE, MCS_SPR_MODE_YYG_RAINBOW_RGB);
0353 
0354     /* CMD3 */
0355     ret = nt35950_inject_black_image(nt);
0356     if (ret < 0)
0357         return ret;
0358 
0359     ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0360     if (ret < 0)
0361         return ret;
0362     msleep(120);
0363 
0364     ret = mipi_dsi_dcs_set_display_on(dsi);
0365     if (ret < 0)
0366         return ret;
0367     msleep(120);
0368 
0369     nt->dsi[0]->mode_flags &= ~MIPI_DSI_MODE_LPM;
0370     nt->dsi[1]->mode_flags &= ~MIPI_DSI_MODE_LPM;
0371 
0372     return 0;
0373 }
0374 
0375 static int nt35950_off(struct nt35950 *nt)
0376 {
0377     struct device *dev = &nt->dsi[0]->dev;
0378     int ret;
0379 
0380     ret = mipi_dsi_dcs_set_display_off(nt->dsi[0]);
0381     if (ret < 0) {
0382         dev_err(dev, "Failed to set display off: %d\n", ret);
0383         goto set_lpm;
0384     }
0385     usleep_range(10000, 11000);
0386 
0387     ret = mipi_dsi_dcs_enter_sleep_mode(nt->dsi[0]);
0388     if (ret < 0) {
0389         dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
0390         goto set_lpm;
0391     }
0392     msleep(150);
0393 
0394 set_lpm:
0395     nt->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM;
0396     nt->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM;
0397 
0398     return 0;
0399 }
0400 
0401 static int nt35950_sharp_init_vregs(struct nt35950 *nt, struct device *dev)
0402 {
0403     int ret;
0404 
0405     nt->vregs[0].supply = "vddio";
0406     nt->vregs[1].supply = "avdd";
0407     nt->vregs[2].supply = "avee";
0408     nt->vregs[3].supply = "dvdd";
0409     ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->vregs),
0410                       nt->vregs);
0411     if (ret < 0)
0412         return ret;
0413 
0414     ret = regulator_is_supported_voltage(nt->vregs[0].consumer,
0415                          1750000, 1950000);
0416     if (!ret)
0417         return -EINVAL;
0418     ret = regulator_is_supported_voltage(nt->vregs[1].consumer,
0419                          5200000, 5900000);
0420     if (!ret)
0421         return -EINVAL;
0422     /* AVEE is negative: -5.90V to -5.20V */
0423     ret = regulator_is_supported_voltage(nt->vregs[2].consumer,
0424                          5200000, 5900000);
0425     if (!ret)
0426         return -EINVAL;
0427 
0428     ret = regulator_is_supported_voltage(nt->vregs[3].consumer,
0429                          1300000, 1400000);
0430     if (!ret)
0431         return -EINVAL;
0432 
0433     return 0;
0434 }
0435 
0436 static int nt35950_prepare(struct drm_panel *panel)
0437 {
0438     struct nt35950 *nt = to_nt35950(panel);
0439     struct device *dev = &nt->dsi[0]->dev;
0440     int ret;
0441 
0442     if (nt->prepared)
0443         return 0;
0444 
0445     ret = regulator_enable(nt->vregs[0].consumer);
0446     if (ret)
0447         return ret;
0448     usleep_range(2000, 5000);
0449 
0450     ret = regulator_enable(nt->vregs[3].consumer);
0451     if (ret)
0452         goto end;
0453     usleep_range(15000, 18000);
0454 
0455     ret = regulator_enable(nt->vregs[1].consumer);
0456     if (ret)
0457         goto end;
0458 
0459     ret = regulator_enable(nt->vregs[2].consumer);
0460     if (ret)
0461         goto end;
0462     usleep_range(12000, 13000);
0463 
0464     nt35950_reset(nt);
0465 
0466     ret = nt35950_on(nt);
0467     if (ret < 0) {
0468         dev_err(dev, "Failed to initialize panel: %d\n", ret);
0469         goto end;
0470     }
0471     nt->prepared = true;
0472 
0473 end:
0474     if (ret < 0) {
0475         regulator_bulk_disable(ARRAY_SIZE(nt->vregs), nt->vregs);
0476         return ret;
0477     }
0478 
0479     return 0;
0480 }
0481 
0482 static int nt35950_unprepare(struct drm_panel *panel)
0483 {
0484     struct nt35950 *nt = to_nt35950(panel);
0485     struct device *dev = &nt->dsi[0]->dev;
0486     int ret;
0487 
0488     if (!nt->prepared)
0489         return 0;
0490 
0491     ret = nt35950_off(nt);
0492     if (ret < 0)
0493         dev_err(dev, "Failed to deinitialize panel: %d\n", ret);
0494 
0495     gpiod_set_value_cansleep(nt->reset_gpio, 0);
0496     regulator_bulk_disable(ARRAY_SIZE(nt->vregs), nt->vregs);
0497 
0498     nt->prepared = false;
0499     return 0;
0500 }
0501 
0502 static int nt35950_get_modes(struct drm_panel *panel,
0503                  struct drm_connector *connector)
0504 {
0505     struct nt35950 *nt = to_nt35950(panel);
0506     int i;
0507 
0508     for (i = 0; i < nt->desc->num_modes; i++) {
0509         struct drm_display_mode *mode;
0510 
0511         mode = drm_mode_duplicate(connector->dev,
0512                       &nt->desc->mode_data[i].mode);
0513         if (!mode)
0514             return -ENOMEM;
0515 
0516         drm_mode_set_name(mode);
0517 
0518         mode->type |= DRM_MODE_TYPE_DRIVER;
0519         if (nt->desc->num_modes == 1)
0520             mode->type |= DRM_MODE_TYPE_PREFERRED;
0521 
0522         drm_mode_probed_add(connector, mode);
0523     }
0524 
0525     connector->display_info.bpc = 8;
0526     connector->display_info.height_mm = nt->desc->mode_data[0].mode.height_mm;
0527     connector->display_info.width_mm = nt->desc->mode_data[0].mode.width_mm;
0528     nt->connector = connector;
0529 
0530     return nt->desc->num_modes;
0531 }
0532 
0533 static const struct drm_panel_funcs nt35950_panel_funcs = {
0534     .prepare = nt35950_prepare,
0535     .unprepare = nt35950_unprepare,
0536     .get_modes = nt35950_get_modes,
0537 };
0538 
0539 static int nt35950_probe(struct mipi_dsi_device *dsi)
0540 {
0541     struct device *dev = &dsi->dev;
0542     struct device_node *dsi_r;
0543     struct mipi_dsi_host *dsi_r_host;
0544     struct nt35950 *nt;
0545     const struct mipi_dsi_device_info *info;
0546     int i, num_dsis = 1, ret;
0547 
0548     nt = devm_kzalloc(dev, sizeof(*nt), GFP_KERNEL);
0549     if (!nt)
0550         return -ENOMEM;
0551 
0552     ret = nt35950_sharp_init_vregs(nt, dev);
0553     if (ret)
0554         return dev_err_probe(dev, ret, "Regulator init failure.\n");
0555 
0556     nt->desc = of_device_get_match_data(dev);
0557     if (!nt->desc)
0558         return -ENODEV;
0559 
0560     nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
0561     if (IS_ERR(nt->reset_gpio)) {
0562         return dev_err_probe(dev, PTR_ERR(nt->reset_gpio),
0563                      "Failed to get reset gpio\n");
0564     }
0565 
0566     /* If the panel is connected on two DSIs then DSI0 left, DSI1 right */
0567     if (nt->desc->is_dual_dsi) {
0568         info = &nt->desc->dsi_info;
0569         dsi_r = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
0570         if (!dsi_r) {
0571             dev_err(dev, "Cannot get secondary DSI node.\n");
0572             return -ENODEV;
0573         }
0574         dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r);
0575         of_node_put(dsi_r);
0576         if (!dsi_r_host) {
0577             dev_err(dev, "Cannot get secondary DSI host\n");
0578             return -EPROBE_DEFER;
0579         }
0580 
0581         nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info);
0582         if (!nt->dsi[1]) {
0583             dev_err(dev, "Cannot get secondary DSI node\n");
0584             return -ENODEV;
0585         }
0586         num_dsis++;
0587     }
0588 
0589     nt->dsi[0] = dsi;
0590     mipi_dsi_set_drvdata(dsi, nt);
0591 
0592     drm_panel_init(&nt->panel, dev, &nt35950_panel_funcs,
0593                DRM_MODE_CONNECTOR_DSI);
0594 
0595     ret = drm_panel_of_backlight(&nt->panel);
0596     if (ret)
0597         return dev_err_probe(dev, ret, "Failed to get backlight\n");
0598 
0599     drm_panel_add(&nt->panel);
0600 
0601     for (i = 0; i < num_dsis; i++) {
0602         nt->dsi[i]->lanes = nt->desc->num_lanes;
0603         nt->dsi[i]->format = MIPI_DSI_FMT_RGB888;
0604 
0605         nt->dsi[i]->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
0606                      MIPI_DSI_MODE_LPM;
0607 
0608         if (nt->desc->mode_data[0].is_video_mode)
0609             nt->dsi[i]->mode_flags |= MIPI_DSI_MODE_VIDEO;
0610 
0611         ret = mipi_dsi_attach(nt->dsi[i]);
0612         if (ret < 0) {
0613             return dev_err_probe(dev, ret,
0614                          "Cannot attach to DSI%d host.\n", i);
0615         }
0616     }
0617 
0618     /* Make sure to set RESX LOW before starting the power-on sequence */
0619     gpiod_set_value_cansleep(nt->reset_gpio, 0);
0620     return 0;
0621 }
0622 
0623 static int nt35950_remove(struct mipi_dsi_device *dsi)
0624 {
0625     struct nt35950 *nt = mipi_dsi_get_drvdata(dsi);
0626     int ret;
0627 
0628     ret = mipi_dsi_detach(nt->dsi[0]);
0629     if (ret < 0)
0630         dev_err(&dsi->dev,
0631             "Failed to detach from DSI0 host: %d\n", ret);
0632 
0633     if (nt->dsi[1]) {
0634         ret = mipi_dsi_detach(nt->dsi[1]);
0635         if (ret < 0)
0636             dev_err(&dsi->dev,
0637                 "Failed to detach from DSI1 host: %d\n", ret);
0638         mipi_dsi_device_unregister(nt->dsi[1]);
0639     }
0640 
0641     drm_panel_remove(&nt->panel);
0642 
0643     return 0;
0644 }
0645 
0646 static const struct nt35950_panel_mode sharp_ls055d1sx04_modes[] = {
0647     {
0648         /* 1920x1080 60Hz no compression */
0649         .mode = {
0650             .clock = 214537,
0651             .hdisplay = 1080,
0652             .hsync_start = 1080 + 400,
0653             .hsync_end = 1080 + 400 + 40,
0654             .htotal = 1080 + 400 + 40 + 300,
0655             .vdisplay = 1920,
0656             .vsync_start = 1920 + 12,
0657             .vsync_end = 1920 + 12 + 2,
0658             .vtotal = 1920 + 12 + 2 + 10,
0659             .width_mm = 68,
0660             .height_mm = 121,
0661         },
0662         .compression = MCS_DATA_COMPRESSION_NONE,
0663         .enable_sram = true,
0664         .is_video_mode = false,
0665         .scaler_on = 1,
0666         .scaler_mode = MCS_SCALEUP_DUPLICATE,
0667     },
0668     /* TODO: Add 2160x3840 60Hz when DSC is supported */
0669 };
0670 
0671 static const struct nt35950_panel_desc sharp_ls055d1sx04 = {
0672     .model_name = "Sharp LS055D1SX04",
0673     .dsi_info = {
0674         .type = "LS055D1SX04",
0675         .channel = 0,
0676         .node = NULL,
0677     },
0678     .mode_data = sharp_ls055d1sx04_modes,
0679     .num_modes = ARRAY_SIZE(sharp_ls055d1sx04_modes),
0680     .is_dual_dsi = true,
0681     .num_lanes = 4,
0682 };
0683 
0684 static const struct of_device_id nt35950_of_match[] = {
0685     { .compatible = "sharp,ls055d1sx04", .data = &sharp_ls055d1sx04 },
0686     {  }
0687 };
0688 MODULE_DEVICE_TABLE(of, nt35950_of_match);
0689 
0690 static struct mipi_dsi_driver nt35950_driver = {
0691     .probe = nt35950_probe,
0692     .remove = nt35950_remove,
0693     .driver = {
0694         .name = "panel-novatek-nt35950",
0695         .of_match_table = nt35950_of_match,
0696     },
0697 };
0698 module_mipi_dsi_driver(nt35950_driver);
0699 
0700 MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>");
0701 MODULE_DESCRIPTION("Novatek NT35950 DriverIC panels driver");
0702 MODULE_LICENSE("GPL v2");