root/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c

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

DEFINITIONS

This source file includes following definitions.
  1. tfp410_encoder_dpms
  2. tfp410_encoder_prepare
  3. tfp410_encoder_commit
  4. tfp410_encoder_mode_set
  5. tfp410_encoder_create
  6. tfp410_connector_destroy
  7. tfp410_connector_detect
  8. tfp410_connector_get_modes
  9. tfp410_connector_best_encoder
  10. tfp410_connector_create
  11. tfp410_modeset_init
  12. tfp410_probe
  13. tfp410_remove
  14. tilcdc_tfp410_init
  15. tilcdc_tfp410_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2012 Texas Instruments
   4  * Author: Rob Clark <robdclark@gmail.com>
   5  */
   6 
   7 #include <linux/gpio.h>
   8 #include <linux/mod_devicetable.h>
   9 #include <linux/of_gpio.h>
  10 #include <linux/pinctrl/consumer.h>
  11 #include <linux/platform_device.h>
  12 
  13 #include <drm/drm_atomic_helper.h>
  14 #include <drm/drm_encoder.h>
  15 #include <drm/drm_modeset_helper_vtables.h>
  16 #include <drm/drm_probe_helper.h>
  17 
  18 #include "tilcdc_drv.h"
  19 #include "tilcdc_tfp410.h"
  20 
  21 struct tfp410_module {
  22         struct tilcdc_module base;
  23         struct i2c_adapter *i2c;
  24         int gpio;
  25 };
  26 #define to_tfp410_module(x) container_of(x, struct tfp410_module, base)
  27 
  28 
  29 static const struct tilcdc_panel_info dvi_info = {
  30                 .ac_bias                = 255,
  31                 .ac_bias_intrpt         = 0,
  32                 .dma_burst_sz           = 16,
  33                 .bpp                    = 16,
  34                 .fdd                    = 0x80,
  35                 .tft_alt_mode           = 0,
  36                 .sync_edge              = 0,
  37                 .sync_ctrl              = 1,
  38                 .raster_order           = 0,
  39 };
  40 
  41 /*
  42  * Encoder:
  43  */
  44 
  45 struct tfp410_encoder {
  46         struct drm_encoder base;
  47         struct tfp410_module *mod;
  48         int dpms;
  49 };
  50 #define to_tfp410_encoder(x) container_of(x, struct tfp410_encoder, base)
  51 
  52 static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode)
  53 {
  54         struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
  55 
  56         if (tfp410_encoder->dpms == mode)
  57                 return;
  58 
  59         if (mode == DRM_MODE_DPMS_ON) {
  60                 DBG("Power on");
  61                 gpio_direction_output(tfp410_encoder->mod->gpio, 1);
  62         } else {
  63                 DBG("Power off");
  64                 gpio_direction_output(tfp410_encoder->mod->gpio, 0);
  65         }
  66 
  67         tfp410_encoder->dpms = mode;
  68 }
  69 
  70 static void tfp410_encoder_prepare(struct drm_encoder *encoder)
  71 {
  72         tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
  73 }
  74 
  75 static void tfp410_encoder_commit(struct drm_encoder *encoder)
  76 {
  77         tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
  78 }
  79 
  80 static void tfp410_encoder_mode_set(struct drm_encoder *encoder,
  81                 struct drm_display_mode *mode,
  82                 struct drm_display_mode *adjusted_mode)
  83 {
  84         /* nothing needed */
  85 }
  86 
  87 static const struct drm_encoder_funcs tfp410_encoder_funcs = {
  88                 .destroy        = drm_encoder_cleanup,
  89 };
  90 
  91 static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = {
  92                 .dpms           = tfp410_encoder_dpms,
  93                 .prepare        = tfp410_encoder_prepare,
  94                 .commit         = tfp410_encoder_commit,
  95                 .mode_set       = tfp410_encoder_mode_set,
  96 };
  97 
  98 static struct drm_encoder *tfp410_encoder_create(struct drm_device *dev,
  99                 struct tfp410_module *mod)
 100 {
 101         struct tfp410_encoder *tfp410_encoder;
 102         struct drm_encoder *encoder;
 103         int ret;
 104 
 105         tfp410_encoder = devm_kzalloc(dev->dev, sizeof(*tfp410_encoder),
 106                                       GFP_KERNEL);
 107         if (!tfp410_encoder)
 108                 return NULL;
 109 
 110         tfp410_encoder->dpms = DRM_MODE_DPMS_OFF;
 111         tfp410_encoder->mod = mod;
 112 
 113         encoder = &tfp410_encoder->base;
 114         encoder->possible_crtcs = 1;
 115 
 116         ret = drm_encoder_init(dev, encoder, &tfp410_encoder_funcs,
 117                         DRM_MODE_ENCODER_TMDS, NULL);
 118         if (ret < 0)
 119                 goto fail;
 120 
 121         drm_encoder_helper_add(encoder, &tfp410_encoder_helper_funcs);
 122 
 123         return encoder;
 124 
 125 fail:
 126         drm_encoder_cleanup(encoder);
 127         return NULL;
 128 }
 129 
 130 /*
 131  * Connector:
 132  */
 133 
 134 struct tfp410_connector {
 135         struct drm_connector base;
 136 
 137         struct drm_encoder *encoder;  /* our connected encoder */
 138         struct tfp410_module *mod;
 139 };
 140 #define to_tfp410_connector(x) container_of(x, struct tfp410_connector, base)
 141 
 142 
 143 static void tfp410_connector_destroy(struct drm_connector *connector)
 144 {
 145         drm_connector_unregister(connector);
 146         drm_connector_cleanup(connector);
 147 }
 148 
 149 static enum drm_connector_status tfp410_connector_detect(
 150                 struct drm_connector *connector,
 151                 bool force)
 152 {
 153         struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
 154 
 155         if (drm_probe_ddc(tfp410_connector->mod->i2c))
 156                 return connector_status_connected;
 157 
 158         return connector_status_unknown;
 159 }
 160 
 161 static int tfp410_connector_get_modes(struct drm_connector *connector)
 162 {
 163         struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
 164         struct edid *edid;
 165         int ret = 0;
 166 
 167         edid = drm_get_edid(connector, tfp410_connector->mod->i2c);
 168 
 169         drm_connector_update_edid_property(connector, edid);
 170 
 171         if (edid) {
 172                 ret = drm_add_edid_modes(connector, edid);
 173                 kfree(edid);
 174         }
 175 
 176         return ret;
 177 }
 178 
 179 static struct drm_encoder *tfp410_connector_best_encoder(
 180                 struct drm_connector *connector)
 181 {
 182         struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
 183         return tfp410_connector->encoder;
 184 }
 185 
 186 static const struct drm_connector_funcs tfp410_connector_funcs = {
 187         .destroy            = tfp410_connector_destroy,
 188         .detect             = tfp410_connector_detect,
 189         .fill_modes         = drm_helper_probe_single_connector_modes,
 190         .reset              = drm_atomic_helper_connector_reset,
 191         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 192         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 193 };
 194 
 195 static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
 196         .get_modes          = tfp410_connector_get_modes,
 197         .best_encoder       = tfp410_connector_best_encoder,
 198 };
 199 
 200 static struct drm_connector *tfp410_connector_create(struct drm_device *dev,
 201                 struct tfp410_module *mod, struct drm_encoder *encoder)
 202 {
 203         struct tfp410_connector *tfp410_connector;
 204         struct drm_connector *connector;
 205         int ret;
 206 
 207         tfp410_connector = devm_kzalloc(dev->dev, sizeof(*tfp410_connector),
 208                                         GFP_KERNEL);
 209         if (!tfp410_connector)
 210                 return NULL;
 211 
 212         tfp410_connector->encoder = encoder;
 213         tfp410_connector->mod = mod;
 214 
 215         connector = &tfp410_connector->base;
 216 
 217         drm_connector_init(dev, connector, &tfp410_connector_funcs,
 218                         DRM_MODE_CONNECTOR_DVID);
 219         drm_connector_helper_add(connector, &tfp410_connector_helper_funcs);
 220 
 221         connector->polled = DRM_CONNECTOR_POLL_CONNECT |
 222                         DRM_CONNECTOR_POLL_DISCONNECT;
 223 
 224         connector->interlace_allowed = 0;
 225         connector->doublescan_allowed = 0;
 226 
 227         ret = drm_connector_attach_encoder(connector, encoder);
 228         if (ret)
 229                 goto fail;
 230 
 231         return connector;
 232 
 233 fail:
 234         tfp410_connector_destroy(connector);
 235         return NULL;
 236 }
 237 
 238 /*
 239  * Module:
 240  */
 241 
 242 static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
 243 {
 244         struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
 245         struct tilcdc_drm_private *priv = dev->dev_private;
 246         struct drm_encoder *encoder;
 247         struct drm_connector *connector;
 248 
 249         encoder = tfp410_encoder_create(dev, tfp410_mod);
 250         if (!encoder)
 251                 return -ENOMEM;
 252 
 253         connector = tfp410_connector_create(dev, tfp410_mod, encoder);
 254         if (!connector)
 255                 return -ENOMEM;
 256 
 257         priv->encoders[priv->num_encoders++] = encoder;
 258         priv->connectors[priv->num_connectors++] = connector;
 259 
 260         tilcdc_crtc_set_panel_info(priv->crtc, &dvi_info);
 261         return 0;
 262 }
 263 
 264 static const struct tilcdc_module_ops tfp410_module_ops = {
 265                 .modeset_init = tfp410_modeset_init,
 266 };
 267 
 268 /*
 269  * Device:
 270  */
 271 
 272 static int tfp410_probe(struct platform_device *pdev)
 273 {
 274         struct device_node *node = pdev->dev.of_node;
 275         struct device_node *i2c_node;
 276         struct tfp410_module *tfp410_mod;
 277         struct tilcdc_module *mod;
 278         struct pinctrl *pinctrl;
 279         uint32_t i2c_phandle;
 280         int ret = -EINVAL;
 281 
 282         /* bail out early if no DT data: */
 283         if (!node) {
 284                 dev_err(&pdev->dev, "device-tree data is missing\n");
 285                 return -ENXIO;
 286         }
 287 
 288         tfp410_mod = devm_kzalloc(&pdev->dev, sizeof(*tfp410_mod), GFP_KERNEL);
 289         if (!tfp410_mod)
 290                 return -ENOMEM;
 291 
 292         mod = &tfp410_mod->base;
 293         pdev->dev.platform_data = mod;
 294 
 295         tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
 296 
 297         pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 298         if (IS_ERR(pinctrl))
 299                 dev_warn(&pdev->dev, "pins are not configured\n");
 300 
 301         if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
 302                 dev_err(&pdev->dev, "could not get i2c bus phandle\n");
 303                 goto fail;
 304         }
 305 
 306         i2c_node = of_find_node_by_phandle(i2c_phandle);
 307         if (!i2c_node) {
 308                 dev_err(&pdev->dev, "could not get i2c bus node\n");
 309                 goto fail;
 310         }
 311 
 312         tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
 313         if (!tfp410_mod->i2c) {
 314                 dev_err(&pdev->dev, "could not get i2c\n");
 315                 of_node_put(i2c_node);
 316                 goto fail;
 317         }
 318 
 319         of_node_put(i2c_node);
 320 
 321         tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio",
 322                         0, NULL);
 323         if (tfp410_mod->gpio < 0) {
 324                 dev_warn(&pdev->dev, "No power down GPIO\n");
 325         } else {
 326                 ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
 327                 if (ret) {
 328                         dev_err(&pdev->dev, "could not get DVI_PDn gpio\n");
 329                         goto fail_adapter;
 330                 }
 331         }
 332 
 333         return 0;
 334 
 335 fail_adapter:
 336         i2c_put_adapter(tfp410_mod->i2c);
 337 
 338 fail:
 339         tilcdc_module_cleanup(mod);
 340         return ret;
 341 }
 342 
 343 static int tfp410_remove(struct platform_device *pdev)
 344 {
 345         struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
 346         struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
 347 
 348         i2c_put_adapter(tfp410_mod->i2c);
 349         gpio_free(tfp410_mod->gpio);
 350 
 351         tilcdc_module_cleanup(mod);
 352 
 353         return 0;
 354 }
 355 
 356 static const struct of_device_id tfp410_of_match[] = {
 357                 { .compatible = "ti,tilcdc,tfp410", },
 358                 { },
 359 };
 360 
 361 struct platform_driver tfp410_driver = {
 362         .probe = tfp410_probe,
 363         .remove = tfp410_remove,
 364         .driver = {
 365                 .owner = THIS_MODULE,
 366                 .name = "tfp410",
 367                 .of_match_table = tfp410_of_match,
 368         },
 369 };
 370 
 371 int __init tilcdc_tfp410_init(void)
 372 {
 373         return platform_driver_register(&tfp410_driver);
 374 }
 375 
 376 void __exit tilcdc_tfp410_fini(void)
 377 {
 378         platform_driver_unregister(&tfp410_driver);
 379 }

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