0001
0002
0003
0004
0005
0006
0007
0008
0009
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 <video/mipi_display.h>
0017
0018 #include <drm/drm_crtc.h>
0019 #include <drm/drm_device.h>
0020 #include <drm/drm_mipi_dsi.h>
0021 #include <drm/drm_panel.h>
0022
0023 struct sharp_nt_panel {
0024 struct drm_panel base;
0025 struct mipi_dsi_device *dsi;
0026
0027 struct regulator *supply;
0028 struct gpio_desc *reset_gpio;
0029
0030 bool prepared;
0031 bool enabled;
0032
0033 const struct drm_display_mode *mode;
0034 };
0035
0036 static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel)
0037 {
0038 return container_of(panel, struct sharp_nt_panel, base);
0039 }
0040
0041 static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt)
0042 {
0043 struct mipi_dsi_device *dsi = sharp_nt->dsi;
0044 int ret;
0045
0046 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0047
0048 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0049 if (ret < 0)
0050 return ret;
0051
0052 msleep(120);
0053
0054
0055 ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1);
0056 if (ret < 0)
0057 return ret;
0058
0059
0060 ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT |
0061 (MIPI_DCS_PIXEL_FMT_24BIT << 4));
0062 if (ret < 0)
0063 return ret;
0064
0065 return 0;
0066 }
0067
0068 static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt)
0069 {
0070 struct mipi_dsi_device *dsi = sharp_nt->dsi;
0071 int ret;
0072
0073 dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0074
0075 ret = mipi_dsi_dcs_set_display_on(dsi);
0076 if (ret < 0)
0077 return ret;
0078
0079 return 0;
0080 }
0081
0082 static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt)
0083 {
0084 struct mipi_dsi_device *dsi = sharp_nt->dsi;
0085 int ret;
0086
0087 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0088
0089 ret = mipi_dsi_dcs_set_display_off(dsi);
0090 if (ret < 0)
0091 return ret;
0092
0093 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0094 if (ret < 0)
0095 return ret;
0096
0097 return 0;
0098 }
0099
0100
0101 static int sharp_nt_panel_disable(struct drm_panel *panel)
0102 {
0103 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
0104
0105 if (!sharp_nt->enabled)
0106 return 0;
0107
0108 sharp_nt->enabled = false;
0109
0110 return 0;
0111 }
0112
0113 static int sharp_nt_panel_unprepare(struct drm_panel *panel)
0114 {
0115 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
0116 int ret;
0117
0118 if (!sharp_nt->prepared)
0119 return 0;
0120
0121 ret = sharp_nt_panel_off(sharp_nt);
0122 if (ret < 0) {
0123 dev_err(panel->dev, "failed to set panel off: %d\n", ret);
0124 return ret;
0125 }
0126
0127 regulator_disable(sharp_nt->supply);
0128 if (sharp_nt->reset_gpio)
0129 gpiod_set_value(sharp_nt->reset_gpio, 0);
0130
0131 sharp_nt->prepared = false;
0132
0133 return 0;
0134 }
0135
0136 static int sharp_nt_panel_prepare(struct drm_panel *panel)
0137 {
0138 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
0139 int ret;
0140
0141 if (sharp_nt->prepared)
0142 return 0;
0143
0144 ret = regulator_enable(sharp_nt->supply);
0145 if (ret < 0)
0146 return ret;
0147
0148 msleep(20);
0149
0150 if (sharp_nt->reset_gpio) {
0151 gpiod_set_value(sharp_nt->reset_gpio, 1);
0152 msleep(1);
0153 gpiod_set_value(sharp_nt->reset_gpio, 0);
0154 msleep(1);
0155 gpiod_set_value(sharp_nt->reset_gpio, 1);
0156 msleep(10);
0157 }
0158
0159 ret = sharp_nt_panel_init(sharp_nt);
0160 if (ret < 0) {
0161 dev_err(panel->dev, "failed to init panel: %d\n", ret);
0162 goto poweroff;
0163 }
0164
0165 ret = sharp_nt_panel_on(sharp_nt);
0166 if (ret < 0) {
0167 dev_err(panel->dev, "failed to set panel on: %d\n", ret);
0168 goto poweroff;
0169 }
0170
0171 sharp_nt->prepared = true;
0172
0173 return 0;
0174
0175 poweroff:
0176 regulator_disable(sharp_nt->supply);
0177 if (sharp_nt->reset_gpio)
0178 gpiod_set_value(sharp_nt->reset_gpio, 0);
0179 return ret;
0180 }
0181
0182 static int sharp_nt_panel_enable(struct drm_panel *panel)
0183 {
0184 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel);
0185
0186 if (sharp_nt->enabled)
0187 return 0;
0188
0189 sharp_nt->enabled = true;
0190
0191 return 0;
0192 }
0193
0194 static const struct drm_display_mode default_mode = {
0195 .clock = 41118,
0196 .hdisplay = 540,
0197 .hsync_start = 540 + 48,
0198 .hsync_end = 540 + 48 + 80,
0199 .htotal = 540 + 48 + 80 + 32,
0200 .vdisplay = 960,
0201 .vsync_start = 960 + 3,
0202 .vsync_end = 960 + 3 + 15,
0203 .vtotal = 960 + 3 + 15 + 1,
0204 };
0205
0206 static int sharp_nt_panel_get_modes(struct drm_panel *panel,
0207 struct drm_connector *connector)
0208 {
0209 struct drm_display_mode *mode;
0210
0211 mode = drm_mode_duplicate(connector->dev, &default_mode);
0212 if (!mode) {
0213 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
0214 default_mode.hdisplay, default_mode.vdisplay,
0215 drm_mode_vrefresh(&default_mode));
0216 return -ENOMEM;
0217 }
0218
0219 drm_mode_set_name(mode);
0220
0221 drm_mode_probed_add(connector, mode);
0222
0223 connector->display_info.width_mm = 54;
0224 connector->display_info.height_mm = 95;
0225
0226 return 1;
0227 }
0228
0229 static const struct drm_panel_funcs sharp_nt_panel_funcs = {
0230 .disable = sharp_nt_panel_disable,
0231 .unprepare = sharp_nt_panel_unprepare,
0232 .prepare = sharp_nt_panel_prepare,
0233 .enable = sharp_nt_panel_enable,
0234 .get_modes = sharp_nt_panel_get_modes,
0235 };
0236
0237 static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt)
0238 {
0239 struct device *dev = &sharp_nt->dsi->dev;
0240 int ret;
0241
0242 sharp_nt->mode = &default_mode;
0243
0244 sharp_nt->supply = devm_regulator_get(dev, "avdd");
0245 if (IS_ERR(sharp_nt->supply))
0246 return PTR_ERR(sharp_nt->supply);
0247
0248 sharp_nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
0249 if (IS_ERR(sharp_nt->reset_gpio)) {
0250 dev_err(dev, "cannot get reset-gpios %ld\n",
0251 PTR_ERR(sharp_nt->reset_gpio));
0252 sharp_nt->reset_gpio = NULL;
0253 } else {
0254 gpiod_set_value(sharp_nt->reset_gpio, 0);
0255 }
0256
0257 drm_panel_init(&sharp_nt->base, &sharp_nt->dsi->dev,
0258 &sharp_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
0259
0260 ret = drm_panel_of_backlight(&sharp_nt->base);
0261 if (ret)
0262 return ret;
0263
0264 drm_panel_add(&sharp_nt->base);
0265
0266 return 0;
0267 }
0268
0269 static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt)
0270 {
0271 if (sharp_nt->base.dev)
0272 drm_panel_remove(&sharp_nt->base);
0273 }
0274
0275 static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
0276 {
0277 struct sharp_nt_panel *sharp_nt;
0278 int ret;
0279
0280 dsi->lanes = 2;
0281 dsi->format = MIPI_DSI_FMT_RGB888;
0282 dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
0283 MIPI_DSI_MODE_VIDEO_HSE |
0284 MIPI_DSI_CLOCK_NON_CONTINUOUS |
0285 MIPI_DSI_MODE_NO_EOT_PACKET;
0286
0287 sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
0288 if (!sharp_nt)
0289 return -ENOMEM;
0290
0291 mipi_dsi_set_drvdata(dsi, sharp_nt);
0292
0293 sharp_nt->dsi = dsi;
0294
0295 ret = sharp_nt_panel_add(sharp_nt);
0296 if (ret < 0)
0297 return ret;
0298
0299 ret = mipi_dsi_attach(dsi);
0300 if (ret < 0) {
0301 sharp_nt_panel_del(sharp_nt);
0302 return ret;
0303 }
0304
0305 return 0;
0306 }
0307
0308 static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
0309 {
0310 struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
0311 int ret;
0312
0313 ret = drm_panel_disable(&sharp_nt->base);
0314 if (ret < 0)
0315 dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
0316
0317 ret = mipi_dsi_detach(dsi);
0318 if (ret < 0)
0319 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
0320
0321 sharp_nt_panel_del(sharp_nt);
0322
0323 return 0;
0324 }
0325
0326 static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
0327 {
0328 struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
0329
0330 drm_panel_disable(&sharp_nt->base);
0331 }
0332
0333 static const struct of_device_id sharp_nt_of_match[] = {
0334 { .compatible = "sharp,ls043t1le01-qhd", },
0335 { }
0336 };
0337 MODULE_DEVICE_TABLE(of, sharp_nt_of_match);
0338
0339 static struct mipi_dsi_driver sharp_nt_panel_driver = {
0340 .driver = {
0341 .name = "panel-sharp-ls043t1le01-qhd",
0342 .of_match_table = sharp_nt_of_match,
0343 },
0344 .probe = sharp_nt_panel_probe,
0345 .remove = sharp_nt_panel_remove,
0346 .shutdown = sharp_nt_panel_shutdown,
0347 };
0348 module_mipi_dsi_driver(sharp_nt_panel_driver);
0349
0350 MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>");
0351 MODULE_DESCRIPTION("Sharp LS043T1LE01 NT35565-based qHD (540x960) video mode panel driver");
0352 MODULE_LICENSE("GPL v2");