root/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c

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

DEFINITIONS

This source file includes following definitions.
  1. tfp410_connect
  2. tfp410_disconnect
  3. tfp410_enable
  4. tfp410_disable
  5. tfp410_fix_timings
  6. tfp410_set_timings
  7. tfp410_get_timings
  8. tfp410_check_timings
  9. tfp410_probe_of
  10. tfp410_probe
  11. tfp410_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * TFP410 DPI-to-DVI encoder 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_gpio.h>
  14 
  15 #include <video/omapfb_dss.h>
  16 
  17 struct panel_drv_data {
  18         struct omap_dss_device dssdev;
  19         struct omap_dss_device *in;
  20 
  21         int pd_gpio;
  22         int data_lines;
  23 
  24         struct omap_video_timings timings;
  25 };
  26 
  27 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
  28 
  29 static int tfp410_connect(struct omap_dss_device *dssdev,
  30                 struct omap_dss_device *dst)
  31 {
  32         struct panel_drv_data *ddata = to_panel_data(dssdev);
  33         struct omap_dss_device *in = ddata->in;
  34         int r;
  35 
  36         if (omapdss_device_is_connected(dssdev))
  37                 return -EBUSY;
  38 
  39         r = in->ops.dpi->connect(in, dssdev);
  40         if (r)
  41                 return r;
  42 
  43         dst->src = dssdev;
  44         dssdev->dst = dst;
  45 
  46         return 0;
  47 }
  48 
  49 static void tfp410_disconnect(struct omap_dss_device *dssdev,
  50                 struct omap_dss_device *dst)
  51 {
  52         struct panel_drv_data *ddata = to_panel_data(dssdev);
  53         struct omap_dss_device *in = ddata->in;
  54 
  55         WARN_ON(!omapdss_device_is_connected(dssdev));
  56         if (!omapdss_device_is_connected(dssdev))
  57                 return;
  58 
  59         WARN_ON(dst != dssdev->dst);
  60         if (dst != dssdev->dst)
  61                 return;
  62 
  63         dst->src = NULL;
  64         dssdev->dst = NULL;
  65 
  66         in->ops.dpi->disconnect(in, &ddata->dssdev);
  67 }
  68 
  69 static int tfp410_enable(struct omap_dss_device *dssdev)
  70 {
  71         struct panel_drv_data *ddata = to_panel_data(dssdev);
  72         struct omap_dss_device *in = ddata->in;
  73         int r;
  74 
  75         if (!omapdss_device_is_connected(dssdev))
  76                 return -ENODEV;
  77 
  78         if (omapdss_device_is_enabled(dssdev))
  79                 return 0;
  80 
  81         in->ops.dpi->set_timings(in, &ddata->timings);
  82         if (ddata->data_lines)
  83                 in->ops.dpi->set_data_lines(in, ddata->data_lines);
  84 
  85         r = in->ops.dpi->enable(in);
  86         if (r)
  87                 return r;
  88 
  89         if (gpio_is_valid(ddata->pd_gpio))
  90                 gpio_set_value_cansleep(ddata->pd_gpio, 1);
  91 
  92         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
  93 
  94         return 0;
  95 }
  96 
  97 static void tfp410_disable(struct omap_dss_device *dssdev)
  98 {
  99         struct panel_drv_data *ddata = to_panel_data(dssdev);
 100         struct omap_dss_device *in = ddata->in;
 101 
 102         if (!omapdss_device_is_enabled(dssdev))
 103                 return;
 104 
 105         if (gpio_is_valid(ddata->pd_gpio))
 106                 gpio_set_value_cansleep(ddata->pd_gpio, 0);
 107 
 108         in->ops.dpi->disable(in);
 109 
 110         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 111 }
 112 
 113 static void tfp410_fix_timings(struct omap_video_timings *timings)
 114 {
 115         timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 116         timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
 117         timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
 118 }
 119 
 120 static void tfp410_set_timings(struct omap_dss_device *dssdev,
 121                 struct omap_video_timings *timings)
 122 {
 123         struct panel_drv_data *ddata = to_panel_data(dssdev);
 124         struct omap_dss_device *in = ddata->in;
 125 
 126         tfp410_fix_timings(timings);
 127 
 128         ddata->timings = *timings;
 129         dssdev->panel.timings = *timings;
 130 
 131         in->ops.dpi->set_timings(in, timings);
 132 }
 133 
 134 static void tfp410_get_timings(struct omap_dss_device *dssdev,
 135                 struct omap_video_timings *timings)
 136 {
 137         struct panel_drv_data *ddata = to_panel_data(dssdev);
 138 
 139         *timings = ddata->timings;
 140 }
 141 
 142 static int tfp410_check_timings(struct omap_dss_device *dssdev,
 143                 struct omap_video_timings *timings)
 144 {
 145         struct panel_drv_data *ddata = to_panel_data(dssdev);
 146         struct omap_dss_device *in = ddata->in;
 147 
 148         tfp410_fix_timings(timings);
 149 
 150         return in->ops.dpi->check_timings(in, timings);
 151 }
 152 
 153 static const struct omapdss_dvi_ops tfp410_dvi_ops = {
 154         .connect        = tfp410_connect,
 155         .disconnect     = tfp410_disconnect,
 156 
 157         .enable         = tfp410_enable,
 158         .disable        = tfp410_disable,
 159 
 160         .check_timings  = tfp410_check_timings,
 161         .set_timings    = tfp410_set_timings,
 162         .get_timings    = tfp410_get_timings,
 163 };
 164 
 165 static int tfp410_probe_of(struct platform_device *pdev)
 166 {
 167         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 168         struct device_node *node = pdev->dev.of_node;
 169         struct omap_dss_device *in;
 170         int gpio;
 171 
 172         gpio = of_get_named_gpio(node, "powerdown-gpios", 0);
 173 
 174         if (gpio_is_valid(gpio) || gpio == -ENOENT) {
 175                 ddata->pd_gpio = gpio;
 176         } else {
 177                 dev_err(&pdev->dev, "failed to parse PD gpio\n");
 178                 return gpio;
 179         }
 180 
 181         in = omapdss_of_find_source_for_first_ep(node);
 182         if (IS_ERR(in)) {
 183                 dev_err(&pdev->dev, "failed to find video source\n");
 184                 return PTR_ERR(in);
 185         }
 186 
 187         ddata->in = in;
 188 
 189         return 0;
 190 }
 191 
 192 static int tfp410_probe(struct platform_device *pdev)
 193 {
 194         struct panel_drv_data *ddata;
 195         struct omap_dss_device *dssdev;
 196         int r;
 197 
 198         if (!pdev->dev.of_node)
 199                 return -ENODEV;
 200 
 201         ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
 202         if (!ddata)
 203                 return -ENOMEM;
 204 
 205         platform_set_drvdata(pdev, ddata);
 206 
 207         r = tfp410_probe_of(pdev);
 208         if (r)
 209                 return r;
 210 
 211         if (gpio_is_valid(ddata->pd_gpio)) {
 212                 r = devm_gpio_request_one(&pdev->dev, ddata->pd_gpio,
 213                                 GPIOF_OUT_INIT_LOW, "tfp410 PD");
 214                 if (r) {
 215                         dev_err(&pdev->dev, "Failed to request PD GPIO %d\n",
 216                                         ddata->pd_gpio);
 217                         goto err_gpio;
 218                 }
 219         }
 220 
 221         dssdev = &ddata->dssdev;
 222         dssdev->ops.dvi = &tfp410_dvi_ops;
 223         dssdev->dev = &pdev->dev;
 224         dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 225         dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
 226         dssdev->owner = THIS_MODULE;
 227         dssdev->phy.dpi.data_lines = ddata->data_lines;
 228         dssdev->port_num = 1;
 229 
 230         r = omapdss_register_output(dssdev);
 231         if (r) {
 232                 dev_err(&pdev->dev, "Failed to register output\n");
 233                 goto err_reg;
 234         }
 235 
 236         return 0;
 237 err_reg:
 238 err_gpio:
 239         omap_dss_put_device(ddata->in);
 240         return r;
 241 }
 242 
 243 static int __exit tfp410_remove(struct platform_device *pdev)
 244 {
 245         struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 246         struct omap_dss_device *dssdev = &ddata->dssdev;
 247         struct omap_dss_device *in = ddata->in;
 248 
 249         omapdss_unregister_output(&ddata->dssdev);
 250 
 251         WARN_ON(omapdss_device_is_enabled(dssdev));
 252         if (omapdss_device_is_enabled(dssdev))
 253                 tfp410_disable(dssdev);
 254 
 255         WARN_ON(omapdss_device_is_connected(dssdev));
 256         if (omapdss_device_is_connected(dssdev))
 257                 tfp410_disconnect(dssdev, dssdev->dst);
 258 
 259         omap_dss_put_device(in);
 260 
 261         return 0;
 262 }
 263 
 264 static const struct of_device_id tfp410_of_match[] = {
 265         { .compatible = "omapdss,ti,tfp410", },
 266         {},
 267 };
 268 
 269 MODULE_DEVICE_TABLE(of, tfp410_of_match);
 270 
 271 static struct platform_driver tfp410_driver = {
 272         .probe  = tfp410_probe,
 273         .remove = __exit_p(tfp410_remove),
 274         .driver = {
 275                 .name   = "tfp410",
 276                 .of_match_table = tfp410_of_match,
 277                 .suppress_bind_attrs = true,
 278         },
 279 };
 280 
 281 module_platform_driver(tfp410_driver);
 282 
 283 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
 284 MODULE_DESCRIPTION("TFP410 DPI to DVI encoder driver");
 285 MODULE_LICENSE("GPL");

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