linux/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * OPA362 analog video amplifier with output/power control
   4 *
   5 * Copyright (C) 2014 Golden Delicious Computers
   6 * Author: H. Nikolaus Schaller <hns@goldelico.com>
   7 *
   8 * based on encoder-tfp410
   9 *
  10 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
  11 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
  12 */
  13
  14#include <linux/gpio/consumer.h>
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/slab.h>
  18
  19#include "../dss/omapdss.h"
  20
  21struct panel_drv_data {
  22        struct omap_dss_device dssdev;
  23
  24        struct gpio_desc *enable_gpio;
  25};
  26
  27#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
  28
  29static int opa362_connect(struct omap_dss_device *src,
  30                          struct omap_dss_device *dst)
  31{
  32        return omapdss_device_connect(dst->dss, dst, dst->next);
  33}
  34
  35static void opa362_disconnect(struct omap_dss_device *src,
  36                              struct omap_dss_device *dst)
  37{
  38        omapdss_device_disconnect(dst, dst->next);
  39}
  40
  41static void opa362_enable(struct omap_dss_device *dssdev)
  42{
  43        struct panel_drv_data *ddata = to_panel_data(dssdev);
  44
  45        if (ddata->enable_gpio)
  46                gpiod_set_value_cansleep(ddata->enable_gpio, 1);
  47}
  48
  49static void opa362_disable(struct omap_dss_device *dssdev)
  50{
  51        struct panel_drv_data *ddata = to_panel_data(dssdev);
  52
  53        if (ddata->enable_gpio)
  54                gpiod_set_value_cansleep(ddata->enable_gpio, 0);
  55}
  56
  57static const struct omap_dss_device_ops opa362_ops = {
  58        .connect        = opa362_connect,
  59        .disconnect     = opa362_disconnect,
  60        .enable         = opa362_enable,
  61        .disable        = opa362_disable,
  62};
  63
  64static int opa362_probe(struct platform_device *pdev)
  65{
  66        struct panel_drv_data *ddata;
  67        struct omap_dss_device *dssdev;
  68        struct gpio_desc *gpio;
  69
  70        dev_dbg(&pdev->dev, "probe\n");
  71
  72        ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
  73        if (!ddata)
  74                return -ENOMEM;
  75
  76        platform_set_drvdata(pdev, ddata);
  77
  78        gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
  79        if (IS_ERR(gpio))
  80                return PTR_ERR(gpio);
  81
  82        ddata->enable_gpio = gpio;
  83
  84        dssdev = &ddata->dssdev;
  85        dssdev->ops = &opa362_ops;
  86        dssdev->dev = &pdev->dev;
  87        dssdev->type = OMAP_DISPLAY_TYPE_VENC;
  88        dssdev->owner = THIS_MODULE;
  89        dssdev->of_ports = BIT(1) | BIT(0);
  90
  91        dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
  92        if (IS_ERR(dssdev->next)) {
  93                if (PTR_ERR(dssdev->next) != -EPROBE_DEFER)
  94                        dev_err(&pdev->dev, "failed to find video sink\n");
  95                return PTR_ERR(dssdev->next);
  96        }
  97
  98        omapdss_device_register(dssdev);
  99
 100        return 0;
 101}
 102
 103static int __exit opa362_remove(struct platform_device *pdev)
 104{
 105        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 106        struct omap_dss_device *dssdev = &ddata->dssdev;
 107
 108        if (dssdev->next)
 109                omapdss_device_put(dssdev->next);
 110        omapdss_device_unregister(&ddata->dssdev);
 111
 112        opa362_disable(dssdev);
 113
 114        return 0;
 115}
 116
 117static const struct of_device_id opa362_of_match[] = {
 118        { .compatible = "omapdss,ti,opa362", },
 119        {},
 120};
 121MODULE_DEVICE_TABLE(of, opa362_of_match);
 122
 123static struct platform_driver opa362_driver = {
 124        .probe  = opa362_probe,
 125        .remove = __exit_p(opa362_remove),
 126        .driver = {
 127                .name   = "amplifier-opa362",
 128                .of_match_table = opa362_of_match,
 129                .suppress_bind_attrs = true,
 130        },
 131};
 132
 133module_platform_driver(opa362_driver);
 134
 135MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
 136MODULE_DESCRIPTION("OPA362 analog video amplifier with output/power control");
 137MODULE_LICENSE("GPL v2");
 138