linux/drivers/gpu/drm/omapdrm/dss/output.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
   3 * Author: Archit Taneja <archit@ti.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/kernel.h>
  19#include <linux/module.h>
  20#include <linux/platform_device.h>
  21#include <linux/slab.h>
  22#include <linux/of.h>
  23
  24#include "omapdss.h"
  25
  26static LIST_HEAD(output_list);
  27static DEFINE_MUTEX(output_lock);
  28
  29int omapdss_output_set_device(struct omap_dss_device *out,
  30                struct omap_dss_device *dssdev)
  31{
  32        int r;
  33
  34        mutex_lock(&output_lock);
  35
  36        if (out->dst) {
  37                dev_err(out->dev,
  38                        "output already has device %s connected to it\n",
  39                        out->dst->name);
  40                r = -EINVAL;
  41                goto err;
  42        }
  43
  44        if (out->output_type != dssdev->type) {
  45                dev_err(out->dev, "output type and display type don't match\n");
  46                r = -EINVAL;
  47                goto err;
  48        }
  49
  50        out->dst = dssdev;
  51        dssdev->src = out;
  52
  53        mutex_unlock(&output_lock);
  54
  55        return 0;
  56err:
  57        mutex_unlock(&output_lock);
  58
  59        return r;
  60}
  61EXPORT_SYMBOL(omapdss_output_set_device);
  62
  63int omapdss_output_unset_device(struct omap_dss_device *out)
  64{
  65        int r;
  66
  67        mutex_lock(&output_lock);
  68
  69        if (!out->dst) {
  70                dev_err(out->dev,
  71                        "output doesn't have a device connected to it\n");
  72                r = -EINVAL;
  73                goto err;
  74        }
  75
  76        if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
  77                dev_err(out->dev,
  78                        "device %s is not disabled, cannot unset device\n",
  79                        out->dst->name);
  80                r = -EINVAL;
  81                goto err;
  82        }
  83
  84        out->dst->src = NULL;
  85        out->dst = NULL;
  86
  87        mutex_unlock(&output_lock);
  88
  89        return 0;
  90err:
  91        mutex_unlock(&output_lock);
  92
  93        return r;
  94}
  95EXPORT_SYMBOL(omapdss_output_unset_device);
  96
  97int omapdss_register_output(struct omap_dss_device *out)
  98{
  99        list_add_tail(&out->list, &output_list);
 100        return 0;
 101}
 102EXPORT_SYMBOL(omapdss_register_output);
 103
 104void omapdss_unregister_output(struct omap_dss_device *out)
 105{
 106        list_del(&out->list);
 107}
 108EXPORT_SYMBOL(omapdss_unregister_output);
 109
 110bool omapdss_component_is_output(struct device_node *node)
 111{
 112        struct omap_dss_device *out;
 113
 114        list_for_each_entry(out, &output_list, list) {
 115                if (out->dev->of_node == node)
 116                        return true;
 117        }
 118
 119        return false;
 120}
 121EXPORT_SYMBOL(omapdss_component_is_output);
 122
 123struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
 124{
 125        struct omap_dss_device *out;
 126
 127        list_for_each_entry(out, &output_list, list) {
 128                if (out->id == id)
 129                        return out;
 130        }
 131
 132        return NULL;
 133}
 134EXPORT_SYMBOL(omap_dss_get_output);
 135
 136struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port)
 137{
 138        struct device_node *src_node;
 139        struct omap_dss_device *out;
 140        u32 reg;
 141
 142        src_node = dss_of_port_get_parent_device(port);
 143        if (!src_node)
 144                return NULL;
 145
 146        reg = dss_of_port_get_port_number(port);
 147
 148        list_for_each_entry(out, &output_list, list) {
 149                if (out->dev->of_node == src_node && out->port_num == reg) {
 150                        of_node_put(src_node);
 151                        return omap_dss_get_device(out);
 152                }
 153        }
 154
 155        of_node_put(src_node);
 156
 157        return NULL;
 158}
 159
 160struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
 161{
 162        while (dssdev->src)
 163                dssdev = dssdev->src;
 164
 165        if (dssdev->id != 0)
 166                return omap_dss_get_device(dssdev);
 167
 168        return NULL;
 169}
 170EXPORT_SYMBOL(omapdss_find_output_from_display);
 171
 172static const struct dss_mgr_ops *dss_mgr_ops;
 173static struct omap_drm_private *dss_mgr_ops_priv;
 174
 175int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops,
 176                        struct omap_drm_private *priv)
 177{
 178        if (dss_mgr_ops)
 179                return -EBUSY;
 180
 181        dss_mgr_ops = mgr_ops;
 182        dss_mgr_ops_priv = priv;
 183
 184        return 0;
 185}
 186EXPORT_SYMBOL(dss_install_mgr_ops);
 187
 188void dss_uninstall_mgr_ops(void)
 189{
 190        dss_mgr_ops = NULL;
 191        dss_mgr_ops_priv = NULL;
 192}
 193EXPORT_SYMBOL(dss_uninstall_mgr_ops);
 194
 195int dss_mgr_connect(struct omap_dss_device *dssdev, struct omap_dss_device *dst)
 196{
 197        return dss_mgr_ops->connect(dss_mgr_ops_priv,
 198                                    dssdev->dispc_channel, dst);
 199}
 200EXPORT_SYMBOL(dss_mgr_connect);
 201
 202void dss_mgr_disconnect(struct omap_dss_device *dssdev,
 203                        struct omap_dss_device *dst)
 204{
 205        dss_mgr_ops->disconnect(dss_mgr_ops_priv, dssdev->dispc_channel, dst);
 206}
 207EXPORT_SYMBOL(dss_mgr_disconnect);
 208
 209void dss_mgr_set_timings(struct omap_dss_device *dssdev,
 210                         const struct videomode *vm)
 211{
 212        dss_mgr_ops->set_timings(dss_mgr_ops_priv, dssdev->dispc_channel, vm);
 213}
 214EXPORT_SYMBOL(dss_mgr_set_timings);
 215
 216void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev,
 217                const struct dss_lcd_mgr_config *config)
 218{
 219        dss_mgr_ops->set_lcd_config(dss_mgr_ops_priv,
 220                                    dssdev->dispc_channel, config);
 221}
 222EXPORT_SYMBOL(dss_mgr_set_lcd_config);
 223
 224int dss_mgr_enable(struct omap_dss_device *dssdev)
 225{
 226        return dss_mgr_ops->enable(dss_mgr_ops_priv, dssdev->dispc_channel);
 227}
 228EXPORT_SYMBOL(dss_mgr_enable);
 229
 230void dss_mgr_disable(struct omap_dss_device *dssdev)
 231{
 232        dss_mgr_ops->disable(dss_mgr_ops_priv, dssdev->dispc_channel);
 233}
 234EXPORT_SYMBOL(dss_mgr_disable);
 235
 236void dss_mgr_start_update(struct omap_dss_device *dssdev)
 237{
 238        dss_mgr_ops->start_update(dss_mgr_ops_priv, dssdev->dispc_channel);
 239}
 240EXPORT_SYMBOL(dss_mgr_start_update);
 241
 242int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev,
 243                void (*handler)(void *), void *data)
 244{
 245        return dss_mgr_ops->register_framedone_handler(dss_mgr_ops_priv,
 246                                                       dssdev->dispc_channel,
 247                                                       handler, data);
 248}
 249EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
 250
 251void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev,
 252                void (*handler)(void *), void *data)
 253{
 254        dss_mgr_ops->unregister_framedone_handler(dss_mgr_ops_priv,
 255                                                  dssdev->dispc_channel,
 256                                                  handler, data);
 257}
 258EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
 259