Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2021, Linaro Limited
0004  *
0005  * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
0006  *   Copyright (c) 2013, The Linux Foundation. All rights reserved.
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/of.h>
0014 #include <linux/regulator/consumer.h>
0015 
0016 #include <drm/drm_mipi_dsi.h>
0017 #include <drm/drm_modes.h>
0018 #include <drm/drm_panel.h>
0019 
0020 struct truly_nt35521 {
0021     struct drm_panel panel;
0022     struct mipi_dsi_device *dsi;
0023     struct regulator_bulk_data supplies[2];
0024     struct gpio_desc *reset_gpio;
0025     struct gpio_desc *blen_gpio;
0026     bool prepared;
0027     bool enabled;
0028 };
0029 
0030 static inline
0031 struct truly_nt35521 *to_truly_nt35521(struct drm_panel *panel)
0032 {
0033     return container_of(panel, struct truly_nt35521, panel);
0034 }
0035 
0036 #define dsi_generic_write_seq(dsi, seq...) do {             \
0037         static const u8 d[] = { seq };              \
0038         int ret;                        \
0039         ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));    \
0040         if (ret < 0)                        \
0041             return ret;                 \
0042     } while (0)
0043 
0044 static void truly_nt35521_reset(struct truly_nt35521 *ctx)
0045 {
0046     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0047     usleep_range(1000, 2000);
0048     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0049     usleep_range(10000, 11000);
0050     gpiod_set_value_cansleep(ctx->reset_gpio, 0);
0051     msleep(150);
0052 }
0053 
0054 static int truly_nt35521_on(struct truly_nt35521 *ctx)
0055 {
0056     struct mipi_dsi_device *dsi = ctx->dsi;
0057     struct device *dev = &dsi->dev;
0058     int ret;
0059 
0060     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0061 
0062     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
0063     dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
0064     dsi_generic_write_seq(dsi, 0x6f, 0x11, 0x00);
0065     dsi_generic_write_seq(dsi, 0xf7, 0x20, 0x00);
0066     dsi_generic_write_seq(dsi, 0x6f, 0x01);
0067     dsi_generic_write_seq(dsi, 0xb1, 0x21);
0068     dsi_generic_write_seq(dsi, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);
0069     dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x02, 0x0c, 0x02);
0070     dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
0071     dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
0072     dsi_generic_write_seq(dsi, 0xb6, 0x02);
0073     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
0074     dsi_generic_write_seq(dsi, 0xb0, 0x09, 0x09);
0075     dsi_generic_write_seq(dsi, 0xb1, 0x09, 0x09);
0076     dsi_generic_write_seq(dsi, 0xbc, 0x8c, 0x00);
0077     dsi_generic_write_seq(dsi, 0xbd, 0x8c, 0x00);
0078     dsi_generic_write_seq(dsi, 0xca, 0x00);
0079     dsi_generic_write_seq(dsi, 0xc0, 0x04);
0080     dsi_generic_write_seq(dsi, 0xbe, 0xb5);
0081     dsi_generic_write_seq(dsi, 0xb3, 0x35, 0x35);
0082     dsi_generic_write_seq(dsi, 0xb4, 0x25, 0x25);
0083     dsi_generic_write_seq(dsi, 0xb9, 0x43, 0x43);
0084     dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
0085     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
0086     dsi_generic_write_seq(dsi, 0xee, 0x03);
0087     dsi_generic_write_seq(dsi, 0xb0,
0088                   0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,
0089                   0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);
0090     dsi_generic_write_seq(dsi, 0xb1,
0091                   0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,
0092                   0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);
0093     dsi_generic_write_seq(dsi, 0xb2,
0094                   0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,
0095                   0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);
0096     dsi_generic_write_seq(dsi, 0xb3, 0x03, 0x96, 0x03, 0x98);
0097     dsi_generic_write_seq(dsi, 0xb4,
0098                   0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,
0099                   0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);
0100     dsi_generic_write_seq(dsi, 0xb5,
0101                   0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,
0102                   0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);
0103     dsi_generic_write_seq(dsi, 0xb6,
0104                   0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,
0105                   0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);
0106     dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xb8, 0x03, 0xba);
0107     dsi_generic_write_seq(dsi, 0xb8,
0108                   0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,
0109                   0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);
0110     dsi_generic_write_seq(dsi, 0xb9,
0111                   0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,
0112                   0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);
0113     dsi_generic_write_seq(dsi, 0xba,
0114                   0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,
0115                   0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);
0116     dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf6, 0x03, 0xf7);
0117     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
0118     dsi_generic_write_seq(dsi, 0xb0, 0x22, 0x00);
0119     dsi_generic_write_seq(dsi, 0xb1, 0x22, 0x00);
0120     dsi_generic_write_seq(dsi, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);
0121     dsi_generic_write_seq(dsi, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);
0122     dsi_generic_write_seq(dsi, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);
0123     dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);
0124     dsi_generic_write_seq(dsi, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);
0125     dsi_generic_write_seq(dsi, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);
0126     dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);
0127     dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);
0128     dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x34, 0x00, 0x00);
0129     dsi_generic_write_seq(dsi, 0xc1, 0x00, 0x00, 0x34, 0x00);
0130     dsi_generic_write_seq(dsi, 0xc2, 0x00, 0x00, 0x34, 0x00);
0131     dsi_generic_write_seq(dsi, 0xc3, 0x00, 0x00, 0x34, 0x00);
0132     dsi_generic_write_seq(dsi, 0xc4, 0x60);
0133     dsi_generic_write_seq(dsi, 0xc5, 0xc0);
0134     dsi_generic_write_seq(dsi, 0xc6, 0x00);
0135     dsi_generic_write_seq(dsi, 0xc7, 0x00);
0136     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
0137     dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
0138     dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
0139     dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
0140     dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
0141     dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
0142     dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
0143     dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
0144     dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
0145     dsi_generic_write_seq(dsi, 0xb8, 0x00);
0146     dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
0147     dsi_generic_write_seq(dsi, 0xba, 0x00, 0x00);
0148     dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x03);
0149     dsi_generic_write_seq(dsi, 0xbc, 0x02, 0x03);
0150     dsi_generic_write_seq(dsi, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);
0151     dsi_generic_write_seq(dsi, 0xc0, 0x0b);
0152     dsi_generic_write_seq(dsi, 0xc1, 0x09);
0153     dsi_generic_write_seq(dsi, 0xc2, 0xa6);
0154     dsi_generic_write_seq(dsi, 0xc3, 0x05);
0155     dsi_generic_write_seq(dsi, 0xc4, 0x00);
0156     dsi_generic_write_seq(dsi, 0xc5, 0x02);
0157     dsi_generic_write_seq(dsi, 0xc6, 0x22);
0158     dsi_generic_write_seq(dsi, 0xc7, 0x03);
0159     dsi_generic_write_seq(dsi, 0xc8, 0x07, 0x20);
0160     dsi_generic_write_seq(dsi, 0xc9, 0x03, 0x20);
0161     dsi_generic_write_seq(dsi, 0xca, 0x01, 0x60);
0162     dsi_generic_write_seq(dsi, 0xcb, 0x01, 0x60);
0163     dsi_generic_write_seq(dsi, 0xcc, 0x00, 0x00, 0x02);
0164     dsi_generic_write_seq(dsi, 0xcd, 0x00, 0x00, 0x02);
0165     dsi_generic_write_seq(dsi, 0xce, 0x00, 0x00, 0x02);
0166     dsi_generic_write_seq(dsi, 0xcf, 0x00, 0x00, 0x02);
0167     dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);
0168     dsi_generic_write_seq(dsi, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);
0169     dsi_generic_write_seq(dsi, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);
0170     dsi_generic_write_seq(dsi, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);
0171     dsi_generic_write_seq(dsi, 0xd0,
0172                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
0173     dsi_generic_write_seq(dsi, 0xd5,
0174                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0175                   0x00, 0x00, 0x00);
0176     dsi_generic_write_seq(dsi, 0xd6,
0177                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0178                   0x00, 0x00, 0x00);
0179     dsi_generic_write_seq(dsi, 0xd7,
0180                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0181                   0x00, 0x00, 0x00);
0182     dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
0183     dsi_generic_write_seq(dsi, 0xe5, 0x06);
0184     dsi_generic_write_seq(dsi, 0xe6, 0x06);
0185     dsi_generic_write_seq(dsi, 0xe7, 0x00);
0186     dsi_generic_write_seq(dsi, 0xe8, 0x06);
0187     dsi_generic_write_seq(dsi, 0xe9, 0x06);
0188     dsi_generic_write_seq(dsi, 0xea, 0x06);
0189     dsi_generic_write_seq(dsi, 0xeb, 0x00);
0190     dsi_generic_write_seq(dsi, 0xec, 0x00);
0191     dsi_generic_write_seq(dsi, 0xed, 0x30);
0192     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
0193     dsi_generic_write_seq(dsi, 0xb0, 0x31, 0x31);
0194     dsi_generic_write_seq(dsi, 0xb1, 0x31, 0x31);
0195     dsi_generic_write_seq(dsi, 0xb2, 0x2d, 0x2e);
0196     dsi_generic_write_seq(dsi, 0xb3, 0x31, 0x34);
0197     dsi_generic_write_seq(dsi, 0xb4, 0x29, 0x2a);
0198     dsi_generic_write_seq(dsi, 0xb5, 0x12, 0x10);
0199     dsi_generic_write_seq(dsi, 0xb6, 0x18, 0x16);
0200     dsi_generic_write_seq(dsi, 0xb7, 0x00, 0x02);
0201     dsi_generic_write_seq(dsi, 0xb8, 0x08, 0x31);
0202     dsi_generic_write_seq(dsi, 0xb9, 0x31, 0x31);
0203     dsi_generic_write_seq(dsi, 0xba, 0x31, 0x31);
0204     dsi_generic_write_seq(dsi, 0xbb, 0x31, 0x08);
0205     dsi_generic_write_seq(dsi, 0xbc, 0x03, 0x01);
0206     dsi_generic_write_seq(dsi, 0xbd, 0x17, 0x19);
0207     dsi_generic_write_seq(dsi, 0xbe, 0x11, 0x13);
0208     dsi_generic_write_seq(dsi, 0xbf, 0x2a, 0x29);
0209     dsi_generic_write_seq(dsi, 0xc0, 0x34, 0x31);
0210     dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2d);
0211     dsi_generic_write_seq(dsi, 0xc2, 0x31, 0x31);
0212     dsi_generic_write_seq(dsi, 0xc3, 0x31, 0x31);
0213     dsi_generic_write_seq(dsi, 0xc4, 0x31, 0x31);
0214     dsi_generic_write_seq(dsi, 0xc5, 0x31, 0x31);
0215     dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2d);
0216     dsi_generic_write_seq(dsi, 0xc7, 0x31, 0x34);
0217     dsi_generic_write_seq(dsi, 0xc8, 0x29, 0x2a);
0218     dsi_generic_write_seq(dsi, 0xc9, 0x17, 0x19);
0219     dsi_generic_write_seq(dsi, 0xca, 0x11, 0x13);
0220     dsi_generic_write_seq(dsi, 0xcb, 0x03, 0x01);
0221     dsi_generic_write_seq(dsi, 0xcc, 0x08, 0x31);
0222     dsi_generic_write_seq(dsi, 0xcd, 0x31, 0x31);
0223     dsi_generic_write_seq(dsi, 0xce, 0x31, 0x31);
0224     dsi_generic_write_seq(dsi, 0xcf, 0x31, 0x08);
0225     dsi_generic_write_seq(dsi, 0xd0, 0x00, 0x02);
0226     dsi_generic_write_seq(dsi, 0xd1, 0x12, 0x10);
0227     dsi_generic_write_seq(dsi, 0xd2, 0x18, 0x16);
0228     dsi_generic_write_seq(dsi, 0xd3, 0x2a, 0x29);
0229     dsi_generic_write_seq(dsi, 0xd4, 0x34, 0x31);
0230     dsi_generic_write_seq(dsi, 0xd5, 0x2d, 0x2e);
0231     dsi_generic_write_seq(dsi, 0xd6, 0x31, 0x31);
0232     dsi_generic_write_seq(dsi, 0xd7, 0x31, 0x31);
0233     dsi_generic_write_seq(dsi, 0xe5, 0x31, 0x31);
0234     dsi_generic_write_seq(dsi, 0xe6, 0x31, 0x31);
0235     dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
0236     dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
0237     dsi_generic_write_seq(dsi, 0xe7, 0x00);
0238     dsi_generic_write_seq(dsi, 0x6f, 0x02);
0239     dsi_generic_write_seq(dsi, 0xf7, 0x47);
0240     dsi_generic_write_seq(dsi, 0x6f, 0x0a);
0241     dsi_generic_write_seq(dsi, 0xf7, 0x02);
0242     dsi_generic_write_seq(dsi, 0x6f, 0x17);
0243     dsi_generic_write_seq(dsi, 0xf4, 0x60);
0244     dsi_generic_write_seq(dsi, 0x6f, 0x01);
0245     dsi_generic_write_seq(dsi, 0xf9, 0x46);
0246     dsi_generic_write_seq(dsi, 0x6f, 0x11);
0247     dsi_generic_write_seq(dsi, 0xf3, 0x01);
0248     dsi_generic_write_seq(dsi, 0x35, 0x00);
0249     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
0250     dsi_generic_write_seq(dsi, 0xd9, 0x02, 0x03, 0x00);
0251     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
0252     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
0253     dsi_generic_write_seq(dsi, 0xb1, 0x6c, 0x21);
0254     dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);
0255     dsi_generic_write_seq(dsi, 0x35, 0x00);
0256 
0257     ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0258     if (ret < 0) {
0259         dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
0260         return ret;
0261     }
0262     msleep(120);
0263 
0264     ret = mipi_dsi_dcs_set_display_on(dsi);
0265     if (ret < 0) {
0266         dev_err(dev, "Failed to set display on: %d\n", ret);
0267         return ret;
0268     }
0269     usleep_range(1000, 2000);
0270 
0271     dsi_generic_write_seq(dsi, 0x53, 0x24);
0272 
0273     return 0;
0274 }
0275 
0276 static int truly_nt35521_off(struct truly_nt35521 *ctx)
0277 {
0278     struct mipi_dsi_device *dsi = ctx->dsi;
0279     struct device *dev = &dsi->dev;
0280     int ret;
0281 
0282     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0283 
0284     ret = mipi_dsi_dcs_set_display_off(dsi);
0285     if (ret < 0) {
0286         dev_err(dev, "Failed to set display off: %d\n", ret);
0287         return ret;
0288     }
0289     msleep(50);
0290 
0291     ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0292     if (ret < 0) {
0293         dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
0294         return ret;
0295     }
0296     msleep(150);
0297 
0298     return 0;
0299 }
0300 
0301 static int truly_nt35521_prepare(struct drm_panel *panel)
0302 {
0303     struct truly_nt35521 *ctx = to_truly_nt35521(panel);
0304     struct device *dev = &ctx->dsi->dev;
0305     int ret;
0306 
0307     if (ctx->prepared)
0308         return 0;
0309 
0310     ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
0311     if (ret < 0) {
0312         dev_err(dev, "Failed to enable regulators: %d\n", ret);
0313         return ret;
0314     }
0315 
0316     truly_nt35521_reset(ctx);
0317 
0318     ret = truly_nt35521_on(ctx);
0319     if (ret < 0) {
0320         dev_err(dev, "Failed to initialize panel: %d\n", ret);
0321         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0322         return ret;
0323     }
0324 
0325     ctx->prepared = true;
0326     return 0;
0327 }
0328 
0329 static int truly_nt35521_unprepare(struct drm_panel *panel)
0330 {
0331     struct truly_nt35521 *ctx = to_truly_nt35521(panel);
0332     struct device *dev = &ctx->dsi->dev;
0333     int ret;
0334 
0335     if (!ctx->prepared)
0336         return 0;
0337 
0338     ret = truly_nt35521_off(ctx);
0339     if (ret < 0)
0340         dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
0341 
0342     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0343     regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
0344                    ctx->supplies);
0345 
0346     ctx->prepared = false;
0347     return 0;
0348 }
0349 
0350 static int truly_nt35521_enable(struct drm_panel *panel)
0351 {
0352     struct truly_nt35521 *ctx = to_truly_nt35521(panel);
0353 
0354     if (ctx->enabled)
0355         return 0;
0356 
0357     gpiod_set_value_cansleep(ctx->blen_gpio, 1);
0358 
0359     ctx->enabled = true;
0360     return 0;
0361 }
0362 
0363 static int truly_nt35521_disable(struct drm_panel *panel)
0364 {
0365     struct truly_nt35521 *ctx = to_truly_nt35521(panel);
0366 
0367     if (!ctx->enabled)
0368         return 0;
0369 
0370     gpiod_set_value_cansleep(ctx->blen_gpio, 0);
0371 
0372     ctx->enabled = false;
0373     return 0;
0374 }
0375 
0376 static const struct drm_display_mode truly_nt35521_mode = {
0377     .clock = (720 + 232 + 20 + 112) * (1280 + 18 + 1 + 18) * 60 / 1000,
0378     .hdisplay = 720,
0379     .hsync_start = 720 + 232,
0380     .hsync_end = 720 + 232 + 20,
0381     .htotal = 720 + 232 + 20 + 112,
0382     .vdisplay = 1280,
0383     .vsync_start = 1280 + 18,
0384     .vsync_end = 1280 + 18 + 1,
0385     .vtotal = 1280 + 18 + 1 + 18,
0386     .width_mm = 65,
0387     .height_mm = 116,
0388 };
0389 
0390 static int truly_nt35521_get_modes(struct drm_panel *panel,
0391                    struct drm_connector *connector)
0392 {
0393     struct drm_display_mode *mode;
0394 
0395     mode = drm_mode_duplicate(connector->dev, &truly_nt35521_mode);
0396     if (!mode)
0397         return -ENOMEM;
0398 
0399     drm_mode_set_name(mode);
0400 
0401     mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0402     connector->display_info.width_mm = mode->width_mm;
0403     connector->display_info.height_mm = mode->height_mm;
0404     drm_mode_probed_add(connector, mode);
0405 
0406     return 1;
0407 }
0408 
0409 static const struct drm_panel_funcs truly_nt35521_panel_funcs = {
0410     .prepare = truly_nt35521_prepare,
0411     .unprepare = truly_nt35521_unprepare,
0412     .enable = truly_nt35521_enable,
0413     .disable = truly_nt35521_disable,
0414     .get_modes = truly_nt35521_get_modes,
0415 };
0416 
0417 static int truly_nt35521_bl_update_status(struct backlight_device *bl)
0418 {
0419     struct mipi_dsi_device *dsi = bl_get_data(bl);
0420     u16 brightness = backlight_get_brightness(bl);
0421     int ret;
0422 
0423     ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
0424     if (ret < 0)
0425         return ret;
0426 
0427     return 0;
0428 }
0429 
0430 static int truly_nt35521_bl_get_brightness(struct backlight_device *bl)
0431 {
0432     struct mipi_dsi_device *dsi = bl_get_data(bl);
0433     u16 brightness;
0434     int ret;
0435 
0436     ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
0437     if (ret < 0)
0438         return ret;
0439 
0440     return brightness & 0xff;
0441 }
0442 
0443 static const struct backlight_ops truly_nt35521_bl_ops = {
0444     .update_status = truly_nt35521_bl_update_status,
0445     .get_brightness = truly_nt35521_bl_get_brightness,
0446 };
0447 
0448 static struct backlight_device *
0449 truly_nt35521_create_backlight(struct mipi_dsi_device *dsi)
0450 {
0451     struct device *dev = &dsi->dev;
0452     const struct backlight_properties props = {
0453         .type = BACKLIGHT_RAW,
0454         .brightness = 255,
0455         .max_brightness = 255,
0456     };
0457 
0458     return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
0459                           &truly_nt35521_bl_ops, &props);
0460 }
0461 
0462 static int truly_nt35521_probe(struct mipi_dsi_device *dsi)
0463 {
0464     struct device *dev = &dsi->dev;
0465     struct truly_nt35521 *ctx;
0466     int ret;
0467 
0468     ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0469     if (!ctx)
0470         return -ENOMEM;
0471 
0472     ctx->supplies[0].supply = "positive5";
0473     ctx->supplies[1].supply = "negative5";
0474     ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
0475                       ctx->supplies);
0476     if (ret < 0) {
0477         dev_err(dev, "Failed to get regulators: %d\n", ret);
0478         return ret;
0479     }
0480 
0481     ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0482     if (IS_ERR(ctx->reset_gpio))
0483         return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
0484                      "Failed to get reset-gpios\n");
0485 
0486     ctx->blen_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW);
0487     if (IS_ERR(ctx->blen_gpio))
0488         return dev_err_probe(dev, PTR_ERR(ctx->blen_gpio),
0489                      "Failed to get backlight-gpios\n");
0490 
0491     ctx->dsi = dsi;
0492     mipi_dsi_set_drvdata(dsi, ctx);
0493 
0494     dsi->lanes = 4;
0495     dsi->format = MIPI_DSI_FMT_RGB888;
0496     dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
0497               MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET |
0498               MIPI_DSI_CLOCK_NON_CONTINUOUS;
0499 
0500     drm_panel_init(&ctx->panel, dev, &truly_nt35521_panel_funcs,
0501                DRM_MODE_CONNECTOR_DSI);
0502 
0503     ctx->panel.backlight = truly_nt35521_create_backlight(dsi);
0504     if (IS_ERR(ctx->panel.backlight))
0505         return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
0506                      "Failed to create backlight\n");
0507 
0508     drm_panel_add(&ctx->panel);
0509 
0510     ret = mipi_dsi_attach(dsi);
0511     if (ret < 0) {
0512         dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
0513         drm_panel_remove(&ctx->panel);
0514         return ret;
0515     }
0516 
0517     return 0;
0518 }
0519 
0520 static int truly_nt35521_remove(struct mipi_dsi_device *dsi)
0521 {
0522     struct truly_nt35521 *ctx = mipi_dsi_get_drvdata(dsi);
0523     int ret;
0524 
0525     ret = mipi_dsi_detach(dsi);
0526     if (ret < 0)
0527         dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
0528 
0529     drm_panel_remove(&ctx->panel);
0530 
0531     return 0;
0532 }
0533 
0534 static const struct of_device_id truly_nt35521_of_match[] = {
0535     { .compatible = "sony,tulip-truly-nt35521" },
0536     { /* sentinel */ }
0537 };
0538 MODULE_DEVICE_TABLE(of, truly_nt35521_of_match);
0539 
0540 static struct mipi_dsi_driver truly_nt35521_driver = {
0541     .probe = truly_nt35521_probe,
0542     .remove = truly_nt35521_remove,
0543     .driver = {
0544         .name = "panel-truly-nt35521",
0545         .of_match_table = truly_nt35521_of_match,
0546     },
0547 };
0548 module_mipi_dsi_driver(truly_nt35521_driver);
0549 
0550 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
0551 MODULE_DESCRIPTION("DRM driver for Sony Tulip Truly NT35521 panel");
0552 MODULE_LICENSE("GPL v2");