Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (c) 2021 Linaro Ltd.
0003  * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
0004  *   Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
0005  */
0006 
0007 #include <linux/delay.h>
0008 #include <linux/gpio/consumer.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/regulator/consumer.h>
0012 
0013 #include <video/mipi_display.h>
0014 
0015 #include <drm/drm_mipi_dsi.h>
0016 #include <drm/drm_modes.h>
0017 #include <drm/drm_panel.h>
0018 
0019 struct sharp_ls060 {
0020     struct drm_panel panel;
0021     struct mipi_dsi_device *dsi;
0022     struct regulator *vddi_supply;
0023     struct regulator *vddh_supply;
0024     struct regulator *avdd_supply;
0025     struct regulator *avee_supply;
0026     struct gpio_desc *reset_gpio;
0027     bool prepared;
0028 };
0029 
0030 static inline struct sharp_ls060 *to_sharp_ls060(struct drm_panel *panel)
0031 {
0032     return container_of(panel, struct sharp_ls060, panel);
0033 }
0034 
0035 #define dsi_dcs_write_seq(dsi, seq...) ({               \
0036         static const u8 d[] = { seq };              \
0037                                     \
0038         mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));   \
0039     })
0040 
0041 static void sharp_ls060_reset(struct sharp_ls060 *ctx)
0042 {
0043     gpiod_set_value_cansleep(ctx->reset_gpio, 0);
0044     usleep_range(10000, 11000);
0045     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0046     usleep_range(10000, 11000);
0047     gpiod_set_value_cansleep(ctx->reset_gpio, 0);
0048     usleep_range(10000, 11000);
0049 }
0050 
0051 static int sharp_ls060_on(struct sharp_ls060 *ctx)
0052 {
0053     struct mipi_dsi_device *dsi = ctx->dsi;
0054     struct device *dev = &dsi->dev;
0055     int ret;
0056 
0057     dsi->mode_flags |= MIPI_DSI_MODE_LPM;
0058 
0059     ret = dsi_dcs_write_seq(dsi, 0xbb, 0x13);
0060     if (ret < 0) {
0061         dev_err(dev, "Failed to send command: %d\n", ret);
0062         return ret;
0063     }
0064 
0065     ret = dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);
0066     if (ret < 0) {
0067         dev_err(dev, "Failed to send command: %d\n", ret);
0068         return ret;
0069     }
0070 
0071     ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0072     if (ret < 0) {
0073         dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
0074         return ret;
0075     }
0076     msleep(120);
0077 
0078     ret = mipi_dsi_dcs_set_display_on(dsi);
0079     if (ret < 0) {
0080         dev_err(dev, "Failed to set display on: %d\n", ret);
0081         return ret;
0082     }
0083     msleep(50);
0084 
0085     return 0;
0086 }
0087 
0088 static int sharp_ls060_off(struct sharp_ls060 *ctx)
0089 {
0090     struct mipi_dsi_device *dsi = ctx->dsi;
0091     struct device *dev = &dsi->dev;
0092     int ret;
0093 
0094     dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
0095 
0096     ret = mipi_dsi_dcs_set_display_off(dsi);
0097     if (ret < 0) {
0098         dev_err(dev, "Failed to set display off: %d\n", ret);
0099         return ret;
0100     }
0101     usleep_range(2000, 3000);
0102 
0103     ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0104     if (ret < 0) {
0105         dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
0106         return ret;
0107     }
0108     msleep(121);
0109 
0110     return 0;
0111 }
0112 
0113 static int sharp_ls060_prepare(struct drm_panel *panel)
0114 {
0115     struct sharp_ls060 *ctx = to_sharp_ls060(panel);
0116     struct device *dev = &ctx->dsi->dev;
0117     int ret;
0118 
0119     if (ctx->prepared)
0120         return 0;
0121 
0122     ret = regulator_enable(ctx->vddi_supply);
0123     if (ret < 0)
0124         return ret;
0125 
0126     ret = regulator_enable(ctx->avdd_supply);
0127     if (ret < 0)
0128         goto err_avdd;
0129 
0130     usleep_range(1000, 2000);
0131 
0132     ret = regulator_enable(ctx->avee_supply);
0133     if (ret < 0)
0134         goto err_avee;
0135 
0136     usleep_range(10000, 11000);
0137 
0138     ret = regulator_enable(ctx->vddh_supply);
0139     if (ret < 0)
0140         goto err_vddh;
0141 
0142     usleep_range(10000, 11000);
0143 
0144     sharp_ls060_reset(ctx);
0145 
0146     ret = sharp_ls060_on(ctx);
0147     if (ret < 0) {
0148         dev_err(dev, "Failed to initialize panel: %d\n", ret);
0149         goto err_on;
0150     }
0151 
0152     ctx->prepared = true;
0153 
0154     return 0;
0155 
0156 err_on:
0157     regulator_disable(ctx->vddh_supply);
0158 
0159     usleep_range(10000, 11000);
0160 
0161 err_vddh:
0162     regulator_disable(ctx->avee_supply);
0163 
0164 err_avee:
0165     regulator_disable(ctx->avdd_supply);
0166 
0167     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0168 
0169 err_avdd:
0170     regulator_disable(ctx->vddi_supply);
0171 
0172     return ret;
0173 }
0174 
0175 static int sharp_ls060_unprepare(struct drm_panel *panel)
0176 {
0177     struct sharp_ls060 *ctx = to_sharp_ls060(panel);
0178     struct device *dev = &ctx->dsi->dev;
0179     int ret;
0180 
0181     if (!ctx->prepared)
0182         return 0;
0183 
0184     ret = sharp_ls060_off(ctx);
0185     if (ret < 0)
0186         dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
0187 
0188     regulator_disable(ctx->vddh_supply);
0189 
0190     usleep_range(10000, 11000);
0191 
0192     regulator_disable(ctx->avee_supply);
0193     regulator_disable(ctx->avdd_supply);
0194 
0195     gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0196 
0197     regulator_disable(ctx->vddi_supply);
0198 
0199     ctx->prepared = false;
0200     return 0;
0201 }
0202 
0203 static const struct drm_display_mode sharp_ls060_mode = {
0204     .clock = (1080 + 96 + 16 + 64) * (1920 + 4 + 1 + 16) * 60 / 1000,
0205     .hdisplay = 1080,
0206     .hsync_start = 1080 + 96,
0207     .hsync_end = 1080 + 96 + 16,
0208     .htotal = 1080 + 96 + 16 + 64,
0209     .vdisplay = 1920,
0210     .vsync_start = 1920 + 4,
0211     .vsync_end = 1920 + 4 + 1,
0212     .vtotal = 1920 + 4 + 1 + 16,
0213     .width_mm = 75,
0214     .height_mm = 132,
0215 };
0216 
0217 static int sharp_ls060_get_modes(struct drm_panel *panel,
0218                  struct drm_connector *connector)
0219 {
0220     struct drm_display_mode *mode;
0221 
0222     mode = drm_mode_duplicate(connector->dev, &sharp_ls060_mode);
0223     if (!mode)
0224         return -ENOMEM;
0225 
0226     drm_mode_set_name(mode);
0227 
0228     mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0229     connector->display_info.width_mm = mode->width_mm;
0230     connector->display_info.height_mm = mode->height_mm;
0231     drm_mode_probed_add(connector, mode);
0232 
0233     return 1;
0234 }
0235 
0236 static const struct drm_panel_funcs sharp_ls060_panel_funcs = {
0237     .prepare = sharp_ls060_prepare,
0238     .unprepare = sharp_ls060_unprepare,
0239     .get_modes = sharp_ls060_get_modes,
0240 };
0241 
0242 static int sharp_ls060_probe(struct mipi_dsi_device *dsi)
0243 {
0244     struct device *dev = &dsi->dev;
0245     struct sharp_ls060 *ctx;
0246     int ret;
0247 
0248     ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0249     if (!ctx)
0250         return -ENOMEM;
0251 
0252     ctx->vddi_supply = devm_regulator_get(dev, "vddi");
0253     if (IS_ERR(ctx->vddi_supply))
0254         return PTR_ERR(ctx->vddi_supply);
0255 
0256     ctx->vddh_supply = devm_regulator_get(dev, "vddh");
0257     if (IS_ERR(ctx->vddh_supply))
0258         return PTR_ERR(ctx->vddh_supply);
0259 
0260     ctx->avdd_supply = devm_regulator_get(dev, "avdd");
0261     if (IS_ERR(ctx->avdd_supply))
0262         return PTR_ERR(ctx->avdd_supply);
0263 
0264     ctx->avee_supply = devm_regulator_get(dev, "avee");
0265     if (IS_ERR(ctx->avee_supply))
0266         return PTR_ERR(ctx->avee_supply);
0267 
0268     ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0269     if (IS_ERR(ctx->reset_gpio))
0270         return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
0271                      "Failed to get reset-gpios\n");
0272 
0273     ctx->dsi = dsi;
0274     mipi_dsi_set_drvdata(dsi, ctx);
0275 
0276     dsi->lanes = 4;
0277     dsi->format = MIPI_DSI_FMT_RGB888;
0278     dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
0279               MIPI_DSI_MODE_NO_EOT_PACKET |
0280               MIPI_DSI_CLOCK_NON_CONTINUOUS;
0281 
0282     drm_panel_init(&ctx->panel, dev, &sharp_ls060_panel_funcs,
0283                DRM_MODE_CONNECTOR_DSI);
0284 
0285     ret = drm_panel_of_backlight(&ctx->panel);
0286     if (ret)
0287         return dev_err_probe(dev, ret, "Failed to get backlight\n");
0288 
0289     drm_panel_add(&ctx->panel);
0290 
0291     ret = mipi_dsi_attach(dsi);
0292     if (ret < 0) {
0293         dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
0294         drm_panel_remove(&ctx->panel);
0295         return ret;
0296     }
0297 
0298     return 0;
0299 }
0300 
0301 static int sharp_ls060_remove(struct mipi_dsi_device *dsi)
0302 {
0303     struct sharp_ls060 *ctx = mipi_dsi_get_drvdata(dsi);
0304     int ret;
0305 
0306     ret = mipi_dsi_detach(dsi);
0307     if (ret < 0)
0308         dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
0309 
0310     drm_panel_remove(&ctx->panel);
0311 
0312     return 0;
0313 }
0314 
0315 static const struct of_device_id sharp_ls060t1sx01_of_match[] = {
0316     { .compatible = "sharp,ls060t1sx01" },
0317     { /* sentinel */ }
0318 };
0319 MODULE_DEVICE_TABLE(of, sharp_ls060t1sx01_of_match);
0320 
0321 static struct mipi_dsi_driver sharp_ls060_driver = {
0322     .probe = sharp_ls060_probe,
0323     .remove = sharp_ls060_remove,
0324     .driver = {
0325         .name = "panel-sharp-ls060t1sx01",
0326         .of_match_table = sharp_ls060t1sx01_of_match,
0327     },
0328 };
0329 module_mipi_dsi_driver(sharp_ls060_driver);
0330 
0331 MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
0332 MODULE_DESCRIPTION("DRM driver for Sharp LS060T1SX01 1080p video mode dsi panel");
0333 MODULE_LICENSE("GPL v2");