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

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

DEFINITIONS

This source file includes following definitions.
  1. panel_dpi_connect
  2. panel_dpi_disconnect
  3. panel_dpi_enable
  4. panel_dpi_disable
  5. panel_dpi_set_timings
  6. panel_dpi_get_timings
  7. panel_dpi_check_timings
  8. panel_dpi_probe_pdata
  9. panel_dpi_probe_of
  10. panel_dpi_probe
  11. panel_dpi_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Generic MIPI DPI Panel Driver
   4  *
   5  * Copyright (C) 2013 Texas Instruments
   6  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
   7  */
   8 
   9 #include <linux/gpio.h>
  10 #include <linux/module.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/slab.h>
  13 #include <linux/of.h>
  14 #include <linux/of_gpio.h>
  15 
  16 #include <video/omapfb_dss.h>
  17 #include <video/omap-panel-data.h>
  18 #include <video/of_display_timing.h>
  19 
  20 struct panel_drv_data {
  21         struct omap_dss_device dssdev;
  22         struct omap_dss_device *in;
  23 
  24         int data_lines;
  25 
  26         struct omap_video_timings videomode;
  27 
  28         /* used for non-DT boot, to be removed */
  29         int backlight_gpio;
  30 
  31         struct gpio_desc *enable_gpio;
  32 };
  33 
  34 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
  35 
  36 static int panel_dpi_connect(struct omap_dss_device *dssdev)
  37 {
  38         struct panel_drv_data *ddata = to_panel_data(dssdev);
  39         struct omap_dss_device *in = ddata->in;
  40         int r;
  41 
  42         if (omapdss_device_is_connected(dssdev))
  43                 return 0;
  44 
  45         r = in->ops.dpi->connect(in, dssdev);
  46         if (r)
  47                 return r;
  48 
  49         return 0;
  50 }
  51 
  52 static void panel_dpi_disconnect(struct omap_dss_device *dssdev)
  53 {
  54         struct panel_drv_data *ddata = to_panel_data(dssdev);
  55         struct omap_dss_device *in = ddata->in;
  56 
  57         if (!omapdss_device_is_connected(dssdev))
  58                 return;
  59 
  60         in->ops.dpi->disconnect(in, dssdev);
  61 }
  62 
  63 static int panel_dpi_enable(struct omap_dss_device *dssdev)
  64 {
  65         struct panel_drv_data *ddata = to_panel_data(dssdev);
  66         struct omap_dss_device *in = ddata->in;
  67         int r;
  68 
  69         if (!omapdss_device_is_connected(dssdev))
  70                 return -ENODEV;
  71 
  72         if (omapdss_device_is_enabled(dssdev))
  73                 return 0;
  74 
  75         if (ddata->data_lines)
  76                 in->ops.dpi->set_data_lines(in, ddata->data_lines);
  77         in->ops.dpi->set_timings(in, &ddata->videomode);
  78 
  79         r = in->ops.dpi->enable(in);
  80         if (r)
  81                 return r;
  82 
  83         gpiod_set_value_cansleep(ddata->enable_gpio, 1);
  84 
  85         if (gpio_is_valid(ddata->backlight_gpio))
  86                 gpio_set_value_cansleep(ddata->backlight_gpio, 1);
  87 
  88         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
  89 
  90         return 0;
  91 }
  92 
  93 static void panel_dpi_disable(struct omap_dss_device *dssdev)
  94 {
  95         struct panel_drv_data *ddata = to_panel_data(dssdev);
  96         struct omap_dss_device *in = ddata->in;
  97 
  98         if (!omapdss_device_is_enabled(dssdev))
  99                 return;
 100 
 101         if (gpio_is_valid(ddata->backlight_gpio))
 102                 gpio_set_value_cansleep(ddata->backlight_gpio, 0);
 103 
 104         gpiod_set_value_cansleep(ddata->enable_gpio, 0);
 105 
 106         in->ops.dpi->disable(in);
 107 
 108         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 109 }
 110 
 111 static void panel_dpi_set_timings(struct omap_dss_device *dssdev,
 112                 struct omap_video_timings *timings)
 113 {
 114         struct panel_drv_data *ddata = to_panel_data(dssdev);
 115         struct omap_dss_device *in = ddata->in;
 116 
 117         ddata->videomode = *timings;
 118         dssdev->panel.timings = *timings;
 119 
 120         in->ops.dpi->set_timings(in, timings);
 121 }
 122 
 123 static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
 124                 struct omap_video_timings *timings)
 125 {
 126         struct panel_drv_data *ddata = to_panel_data(dssdev);
 127 
 128         *timings = ddata->videomode;
 129 }
 130 
 131 static int panel_dpi_check_timings(struct omap_dss_device *dssdev,
 132                 struct omap_video_timings *timings)
 133 {
 134         struct panel_drv_data *ddata = to_panel_data(dssdev);
 135         struct omap_dss_device *in = ddata->in;
 136 
 137         return in->ops.dpi->check_timings(in, timings);
 138 }
 139 
 140 static struct omap_dss_driver panel_dpi_ops = {
 141         .connect        = panel_dpi_connect,
 142         .disconnect     = panel_dpi_disconnect,
 143 
 144         .enable         = panel_dpi_enable,
 145         .disable        = panel_dpi_disable,
 146 
 147         .set_timings    = panel_dpi_set_timings,
 148         .get_timings    = panel_dpi_get_timings,
 149         .check_timings  = panel_dpi_check_timings,
 150 
 151         .get_resolution = omapdss_default_get_resolution,
 152 };
 153 
 154 static int panel_dpi_probe_pdata(struct platform_device *pdev)
 155 {
 156         const struct panel_dpi_platform_data *pdata;
 157         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 158         struct omap_dss_device *dssdev, *in;
 159         struct videomode vm;
 160         int r;
 161 
 162         pdata = dev_get_platdata(&pdev->dev);
 163 
 164         in = omap_dss_find_output(pdata->source);
 165         if (in == NULL) {
 166                 dev_err(&pdev->dev, "failed to find video source '%s'\n",
 167                                 pdata->source);
 168                 return -EPROBE_DEFER;
 169         }
 170 
 171         ddata->in = in;
 172 
 173         ddata->data_lines = pdata->data_lines;
 174 
 175         videomode_from_timing(pdata->display_timing, &vm);
 176         videomode_to_omap_video_timings(&vm, &ddata->videomode);
 177 
 178         dssdev = &ddata->dssdev;
 179         dssdev->name = pdata->name;
 180 
 181         r = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio,
 182                                         GPIOF_OUT_INIT_LOW, "panel enable");
 183         if (r)
 184                 goto err_gpio;
 185 
 186         ddata->enable_gpio = gpio_to_desc(pdata->enable_gpio);
 187 
 188         ddata->backlight_gpio = pdata->backlight_gpio;
 189 
 190         return 0;
 191 
 192 err_gpio:
 193         omap_dss_put_device(ddata->in);
 194         return r;
 195 }
 196 
 197 static int panel_dpi_probe_of(struct platform_device *pdev)
 198 {
 199         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 200         struct device_node *node = pdev->dev.of_node;
 201         struct omap_dss_device *in;
 202         int r;
 203         struct display_timing timing;
 204         struct videomode vm;
 205         struct gpio_desc *gpio;
 206 
 207         gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
 208         if (IS_ERR(gpio))
 209                 return PTR_ERR(gpio);
 210 
 211         ddata->enable_gpio = gpio;
 212 
 213         ddata->backlight_gpio = -ENOENT;
 214 
 215         r = of_get_display_timing(node, "panel-timing", &timing);
 216         if (r) {
 217                 dev_err(&pdev->dev, "failed to get video timing\n");
 218                 return r;
 219         }
 220 
 221         videomode_from_timing(&timing, &vm);
 222         videomode_to_omap_video_timings(&vm, &ddata->videomode);
 223 
 224         in = omapdss_of_find_source_for_first_ep(node);
 225         if (IS_ERR(in)) {
 226                 dev_err(&pdev->dev, "failed to find video source\n");
 227                 return PTR_ERR(in);
 228         }
 229 
 230         ddata->in = in;
 231 
 232         return 0;
 233 }
 234 
 235 static int panel_dpi_probe(struct platform_device *pdev)
 236 {
 237         struct panel_drv_data *ddata;
 238         struct omap_dss_device *dssdev;
 239         int r;
 240 
 241         ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
 242         if (ddata == NULL)
 243                 return -ENOMEM;
 244 
 245         platform_set_drvdata(pdev, ddata);
 246 
 247         if (dev_get_platdata(&pdev->dev)) {
 248                 r = panel_dpi_probe_pdata(pdev);
 249                 if (r)
 250                         return r;
 251         } else if (pdev->dev.of_node) {
 252                 r = panel_dpi_probe_of(pdev);
 253                 if (r)
 254                         return r;
 255         } else {
 256                 return -ENODEV;
 257         }
 258 
 259         if (gpio_is_valid(ddata->backlight_gpio)) {
 260                 r = devm_gpio_request_one(&pdev->dev, ddata->backlight_gpio,
 261                                 GPIOF_OUT_INIT_LOW, "panel backlight");
 262                 if (r)
 263                         goto err_gpio;
 264         }
 265 
 266         dssdev = &ddata->dssdev;
 267         dssdev->dev = &pdev->dev;
 268         dssdev->driver = &panel_dpi_ops;
 269         dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 270         dssdev->owner = THIS_MODULE;
 271         dssdev->panel.timings = ddata->videomode;
 272         dssdev->phy.dpi.data_lines = ddata->data_lines;
 273 
 274         r = omapdss_register_display(dssdev);
 275         if (r) {
 276                 dev_err(&pdev->dev, "Failed to register panel\n");
 277                 goto err_reg;
 278         }
 279 
 280         return 0;
 281 
 282 err_reg:
 283 err_gpio:
 284         omap_dss_put_device(ddata->in);
 285         return r;
 286 }
 287 
 288 static int __exit panel_dpi_remove(struct platform_device *pdev)
 289 {
 290         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 291         struct omap_dss_device *dssdev = &ddata->dssdev;
 292         struct omap_dss_device *in = ddata->in;
 293 
 294         omapdss_unregister_display(dssdev);
 295 
 296         panel_dpi_disable(dssdev);
 297         panel_dpi_disconnect(dssdev);
 298 
 299         omap_dss_put_device(in);
 300 
 301         return 0;
 302 }
 303 
 304 static const struct of_device_id panel_dpi_of_match[] = {
 305         { .compatible = "omapdss,panel-dpi", },
 306         {},
 307 };
 308 
 309 MODULE_DEVICE_TABLE(of, panel_dpi_of_match);
 310 
 311 static struct platform_driver panel_dpi_driver = {
 312         .probe = panel_dpi_probe,
 313         .remove = __exit_p(panel_dpi_remove),
 314         .driver = {
 315                 .name = "panel-dpi",
 316                 .of_match_table = panel_dpi_of_match,
 317                 .suppress_bind_attrs = true,
 318         },
 319 };
 320 
 321 module_platform_driver(panel_dpi_driver);
 322 
 323 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
 324 MODULE_DESCRIPTION("Generic MIPI DPI Panel Driver");
 325 MODULE_LICENSE("GPL");

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