linux/drivers/video/omap2/dss/output.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Texas Instruments Ltd
   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
  23#include <video/omapdss.h>
  24
  25#include "dss.h"
  26
  27static LIST_HEAD(output_list);
  28static DEFINE_MUTEX(output_lock);
  29
  30int omapdss_output_set_device(struct omap_dss_device *out,
  31                struct omap_dss_device *dssdev)
  32{
  33        int r;
  34
  35        mutex_lock(&output_lock);
  36
  37        if (out->dst) {
  38                DSSERR("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                DSSERR("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                DSSERR("output doesn't have a device connected to it\n");
  71                r = -EINVAL;
  72                goto err;
  73        }
  74
  75        if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) {
  76                DSSERR("device %s is not disabled, cannot unset device\n",
  77                                out->dst->name);
  78                r = -EINVAL;
  79                goto err;
  80        }
  81
  82        out->dst->src = NULL;
  83        out->dst = NULL;
  84
  85        mutex_unlock(&output_lock);
  86
  87        return 0;
  88err:
  89        mutex_unlock(&output_lock);
  90
  91        return r;
  92}
  93EXPORT_SYMBOL(omapdss_output_unset_device);
  94
  95int omapdss_register_output(struct omap_dss_device *out)
  96{
  97        list_add_tail(&out->list, &output_list);
  98        return 0;
  99}
 100EXPORT_SYMBOL(omapdss_register_output);
 101
 102void omapdss_unregister_output(struct omap_dss_device *out)
 103{
 104        list_del(&out->list);
 105}
 106EXPORT_SYMBOL(omapdss_unregister_output);
 107
 108struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id)
 109{
 110        struct omap_dss_device *out;
 111
 112        list_for_each_entry(out, &output_list, list) {
 113                if (out->id == id)
 114                        return out;
 115        }
 116
 117        return NULL;
 118}
 119EXPORT_SYMBOL(omap_dss_get_output);
 120
 121struct omap_dss_device *omap_dss_find_output(const char *name)
 122{
 123        struct omap_dss_device *out;
 124
 125        list_for_each_entry(out, &output_list, list) {
 126                if (strcmp(out->name, name) == 0)
 127                        return omap_dss_get_device(out);
 128        }
 129
 130        return NULL;
 131}
 132EXPORT_SYMBOL(omap_dss_find_output);
 133
 134struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node)
 135{
 136        struct omap_dss_device *out;
 137
 138        list_for_each_entry(out, &output_list, list) {
 139                if (out->dev->of_node == node)
 140                        return omap_dss_get_device(out);
 141        }
 142
 143        return NULL;
 144}
 145EXPORT_SYMBOL(omap_dss_find_output_by_node);
 146
 147struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
 148{
 149        while (dssdev->src)
 150                dssdev = dssdev->src;
 151
 152        if (dssdev->id != 0)
 153                return omap_dss_get_device(dssdev);
 154
 155        return NULL;
 156}
 157EXPORT_SYMBOL(omapdss_find_output_from_display);
 158
 159struct omap_overlay_manager *omapdss_find_mgr_from_display(struct omap_dss_device *dssdev)
 160{
 161        struct omap_dss_device *out;
 162        struct omap_overlay_manager *mgr;
 163
 164        out = omapdss_find_output_from_display(dssdev);
 165
 166        if (out == NULL)
 167                return NULL;
 168
 169        mgr = out->manager;
 170
 171        omap_dss_put_device(out);
 172
 173        return mgr;
 174}
 175EXPORT_SYMBOL(omapdss_find_mgr_from_display);
 176
 177static const struct dss_mgr_ops *dss_mgr_ops;
 178
 179int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
 180{
 181        if (dss_mgr_ops)
 182                return -EBUSY;
 183
 184        dss_mgr_ops = mgr_ops;
 185
 186        return 0;
 187}
 188EXPORT_SYMBOL(dss_install_mgr_ops);
 189
 190void dss_uninstall_mgr_ops(void)
 191{
 192        dss_mgr_ops = NULL;
 193}
 194EXPORT_SYMBOL(dss_uninstall_mgr_ops);
 195
 196int dss_mgr_connect(struct omap_overlay_manager *mgr,
 197                struct omap_dss_device *dst)
 198{
 199        return dss_mgr_ops->connect(mgr, dst);
 200}
 201EXPORT_SYMBOL(dss_mgr_connect);
 202
 203void dss_mgr_disconnect(struct omap_overlay_manager *mgr,
 204                struct omap_dss_device *dst)
 205{
 206        dss_mgr_ops->disconnect(mgr, dst);
 207}
 208EXPORT_SYMBOL(dss_mgr_disconnect);
 209
 210void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
 211                const struct omap_video_timings *timings)
 212{
 213        dss_mgr_ops->set_timings(mgr, timings);
 214}
 215EXPORT_SYMBOL(dss_mgr_set_timings);
 216
 217void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
 218                const struct dss_lcd_mgr_config *config)
 219{
 220        dss_mgr_ops->set_lcd_config(mgr, config);
 221}
 222EXPORT_SYMBOL(dss_mgr_set_lcd_config);
 223
 224int dss_mgr_enable(struct omap_overlay_manager *mgr)
 225{
 226        return dss_mgr_ops->enable(mgr);
 227}
 228EXPORT_SYMBOL(dss_mgr_enable);
 229
 230void dss_mgr_disable(struct omap_overlay_manager *mgr)
 231{
 232        dss_mgr_ops->disable(mgr);
 233}
 234EXPORT_SYMBOL(dss_mgr_disable);
 235
 236void dss_mgr_start_update(struct omap_overlay_manager *mgr)
 237{
 238        dss_mgr_ops->start_update(mgr);
 239}
 240EXPORT_SYMBOL(dss_mgr_start_update);
 241
 242int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
 243                void (*handler)(void *), void *data)
 244{
 245        return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
 246}
 247EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
 248
 249void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
 250                void (*handler)(void *), void *data)
 251{
 252        dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
 253}
 254EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
 255