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