root/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sharp_ls_connect
  2. sharp_ls_disconnect
  3. sharp_ls_enable
  4. sharp_ls_disable
  5. sharp_ls_set_timings
  6. sharp_ls_get_timings
  7. sharp_ls_check_timings
  8. sharp_ls_get_gpio_of
  9. sharp_ls_probe_of
  10. sharp_ls_probe
  11. sharp_ls_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * LCD panel driver for Sharp LS037V7DW01
   4  *
   5  * Copyright (C) 2013 Texas Instruments
   6  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
   7  */
   8 
   9 #include <linux/delay.h>
  10 #include <linux/gpio.h>
  11 #include <linux/module.h>
  12 #include <linux/of.h>
  13 #include <linux/of_gpio.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/slab.h>
  16 #include <linux/regulator/consumer.h>
  17 #include <video/omapfb_dss.h>
  18 
  19 struct panel_drv_data {
  20         struct omap_dss_device dssdev;
  21         struct omap_dss_device *in;
  22         struct regulator *vcc;
  23 
  24         int data_lines;
  25 
  26         struct omap_video_timings videomode;
  27 
  28         struct gpio_desc *resb_gpio;    /* low = reset active min 20 us */
  29         struct gpio_desc *ini_gpio;     /* high = power on */
  30         struct gpio_desc *mo_gpio;      /* low = 480x640, high = 240x320 */
  31         struct gpio_desc *lr_gpio;      /* high = conventional horizontal scanning */
  32         struct gpio_desc *ud_gpio;      /* high = conventional vertical scanning */
  33 };
  34 
  35 static const struct omap_video_timings sharp_ls_timings = {
  36         .x_res = 480,
  37         .y_res = 640,
  38 
  39         .pixelclock     = 19200000,
  40 
  41         .hsw            = 2,
  42         .hfp            = 1,
  43         .hbp            = 28,
  44 
  45         .vsw            = 1,
  46         .vfp            = 1,
  47         .vbp            = 1,
  48 
  49         .vsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
  50         .hsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
  51         .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
  52         .de_level       = OMAPDSS_SIG_ACTIVE_HIGH,
  53         .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
  54 };
  55 
  56 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
  57 
  58 static int sharp_ls_connect(struct omap_dss_device *dssdev)
  59 {
  60         struct panel_drv_data *ddata = to_panel_data(dssdev);
  61         struct omap_dss_device *in = ddata->in;
  62         int r;
  63 
  64         if (omapdss_device_is_connected(dssdev))
  65                 return 0;
  66 
  67         r = in->ops.dpi->connect(in, dssdev);
  68         if (r)
  69                 return r;
  70 
  71         return 0;
  72 }
  73 
  74 static void sharp_ls_disconnect(struct omap_dss_device *dssdev)
  75 {
  76         struct panel_drv_data *ddata = to_panel_data(dssdev);
  77         struct omap_dss_device *in = ddata->in;
  78 
  79         if (!omapdss_device_is_connected(dssdev))
  80                 return;
  81 
  82         in->ops.dpi->disconnect(in, dssdev);
  83 }
  84 
  85 static int sharp_ls_enable(struct omap_dss_device *dssdev)
  86 {
  87         struct panel_drv_data *ddata = to_panel_data(dssdev);
  88         struct omap_dss_device *in = ddata->in;
  89         int r;
  90 
  91         if (!omapdss_device_is_connected(dssdev))
  92                 return -ENODEV;
  93 
  94         if (omapdss_device_is_enabled(dssdev))
  95                 return 0;
  96 
  97         if (ddata->data_lines)
  98                 in->ops.dpi->set_data_lines(in, ddata->data_lines);
  99         in->ops.dpi->set_timings(in, &ddata->videomode);
 100 
 101         if (ddata->vcc) {
 102                 r = regulator_enable(ddata->vcc);
 103                 if (r != 0)
 104                         return r;
 105         }
 106 
 107         r = in->ops.dpi->enable(in);
 108         if (r) {
 109                 regulator_disable(ddata->vcc);
 110                 return r;
 111         }
 112 
 113         /* wait couple of vsyncs until enabling the LCD */
 114         msleep(50);
 115 
 116         if (ddata->resb_gpio)
 117                 gpiod_set_value_cansleep(ddata->resb_gpio, 1);
 118 
 119         if (ddata->ini_gpio)
 120                 gpiod_set_value_cansleep(ddata->ini_gpio, 1);
 121 
 122         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 123 
 124         return 0;
 125 }
 126 
 127 static void sharp_ls_disable(struct omap_dss_device *dssdev)
 128 {
 129         struct panel_drv_data *ddata = to_panel_data(dssdev);
 130         struct omap_dss_device *in = ddata->in;
 131 
 132         if (!omapdss_device_is_enabled(dssdev))
 133                 return;
 134 
 135         if (ddata->ini_gpio)
 136                 gpiod_set_value_cansleep(ddata->ini_gpio, 0);
 137 
 138         if (ddata->resb_gpio)
 139                 gpiod_set_value_cansleep(ddata->resb_gpio, 0);
 140 
 141         /* wait at least 5 vsyncs after disabling the LCD */
 142 
 143         msleep(100);
 144 
 145         in->ops.dpi->disable(in);
 146 
 147         if (ddata->vcc)
 148                 regulator_disable(ddata->vcc);
 149 
 150         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 151 }
 152 
 153 static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
 154                 struct omap_video_timings *timings)
 155 {
 156         struct panel_drv_data *ddata = to_panel_data(dssdev);
 157         struct omap_dss_device *in = ddata->in;
 158 
 159         ddata->videomode = *timings;
 160         dssdev->panel.timings = *timings;
 161 
 162         in->ops.dpi->set_timings(in, timings);
 163 }
 164 
 165 static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
 166                 struct omap_video_timings *timings)
 167 {
 168         struct panel_drv_data *ddata = to_panel_data(dssdev);
 169 
 170         *timings = ddata->videomode;
 171 }
 172 
 173 static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
 174                 struct omap_video_timings *timings)
 175 {
 176         struct panel_drv_data *ddata = to_panel_data(dssdev);
 177         struct omap_dss_device *in = ddata->in;
 178 
 179         return in->ops.dpi->check_timings(in, timings);
 180 }
 181 
 182 static struct omap_dss_driver sharp_ls_ops = {
 183         .connect        = sharp_ls_connect,
 184         .disconnect     = sharp_ls_disconnect,
 185 
 186         .enable         = sharp_ls_enable,
 187         .disable        = sharp_ls_disable,
 188 
 189         .set_timings    = sharp_ls_set_timings,
 190         .get_timings    = sharp_ls_get_timings,
 191         .check_timings  = sharp_ls_check_timings,
 192 
 193         .get_resolution = omapdss_default_get_resolution,
 194 };
 195 
 196 static  int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
 197         const char *desc, struct gpio_desc **gpiod)
 198 {
 199         struct gpio_desc *gd;
 200 
 201         *gpiod = NULL;
 202 
 203         gd = devm_gpiod_get_index(dev, desc, index, GPIOD_OUT_LOW);
 204         if (IS_ERR(gd))
 205                 return PTR_ERR(gd);
 206 
 207         *gpiod = gd;
 208         return 0;
 209 }
 210 
 211 static int sharp_ls_probe_of(struct platform_device *pdev)
 212 {
 213         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 214         struct device_node *node = pdev->dev.of_node;
 215         struct omap_dss_device *in;
 216         int r;
 217 
 218         ddata->vcc = devm_regulator_get(&pdev->dev, "envdd");
 219         if (IS_ERR(ddata->vcc)) {
 220                 dev_err(&pdev->dev, "failed to get regulator\n");
 221                 return PTR_ERR(ddata->vcc);
 222         }
 223 
 224         /* lcd INI */
 225         r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "enable", &ddata->ini_gpio);
 226         if (r)
 227                 return r;
 228 
 229         /* lcd RESB */
 230         r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "reset", &ddata->resb_gpio);
 231         if (r)
 232                 return r;
 233 
 234         /* lcd MO */
 235         r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "mode", &ddata->mo_gpio);
 236         if (r)
 237                 return r;
 238 
 239         /* lcd LR */
 240         r = sharp_ls_get_gpio_of(&pdev->dev, 1, 1, "mode", &ddata->lr_gpio);
 241         if (r)
 242                 return r;
 243 
 244         /* lcd UD */
 245         r = sharp_ls_get_gpio_of(&pdev->dev, 2, 1, "mode", &ddata->ud_gpio);
 246         if (r)
 247                 return r;
 248 
 249         in = omapdss_of_find_source_for_first_ep(node);
 250         if (IS_ERR(in)) {
 251                 dev_err(&pdev->dev, "failed to find video source\n");
 252                 return PTR_ERR(in);
 253         }
 254 
 255         ddata->in = in;
 256 
 257         return 0;
 258 }
 259 
 260 static int sharp_ls_probe(struct platform_device *pdev)
 261 {
 262         struct panel_drv_data *ddata;
 263         struct omap_dss_device *dssdev;
 264         int r;
 265 
 266         if (!pdev->dev.of_node)
 267                 return -ENODEV;
 268 
 269         ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
 270         if (ddata == NULL)
 271                 return -ENOMEM;
 272 
 273         platform_set_drvdata(pdev, ddata);
 274 
 275         r = sharp_ls_probe_of(pdev);
 276         if (r)
 277                 return r;
 278 
 279         ddata->videomode = sharp_ls_timings;
 280 
 281         dssdev = &ddata->dssdev;
 282         dssdev->dev = &pdev->dev;
 283         dssdev->driver = &sharp_ls_ops;
 284         dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 285         dssdev->owner = THIS_MODULE;
 286         dssdev->panel.timings = ddata->videomode;
 287         dssdev->phy.dpi.data_lines = ddata->data_lines;
 288 
 289         r = omapdss_register_display(dssdev);
 290         if (r) {
 291                 dev_err(&pdev->dev, "Failed to register panel\n");
 292                 goto err_reg;
 293         }
 294 
 295         return 0;
 296 
 297 err_reg:
 298         omap_dss_put_device(ddata->in);
 299         return r;
 300 }
 301 
 302 static int __exit sharp_ls_remove(struct platform_device *pdev)
 303 {
 304         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 305         struct omap_dss_device *dssdev = &ddata->dssdev;
 306         struct omap_dss_device *in = ddata->in;
 307 
 308         omapdss_unregister_display(dssdev);
 309 
 310         sharp_ls_disable(dssdev);
 311         sharp_ls_disconnect(dssdev);
 312 
 313         omap_dss_put_device(in);
 314 
 315         return 0;
 316 }
 317 
 318 static const struct of_device_id sharp_ls_of_match[] = {
 319         { .compatible = "omapdss,sharp,ls037v7dw01", },
 320         {},
 321 };
 322 
 323 MODULE_DEVICE_TABLE(of, sharp_ls_of_match);
 324 
 325 static struct platform_driver sharp_ls_driver = {
 326         .probe = sharp_ls_probe,
 327         .remove = __exit_p(sharp_ls_remove),
 328         .driver = {
 329                 .name = "panel-sharp-ls037v7dw01",
 330                 .of_match_table = sharp_ls_of_match,
 331                 .suppress_bind_attrs = true,
 332         },
 333 };
 334 
 335 module_platform_driver(sharp_ls_driver);
 336 
 337 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
 338 MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
 339 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */