linux/drivers/gpu/drm/omapdrm/dss/display.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/video/omap2/dss/display.c
   3 *
   4 * Copyright (C) 2009 Nokia Corporation
   5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
   6 *
   7 * Some code and ideas taken from drivers/video/omap/ driver
   8 * by Imre Deak.
   9 *
  10 * This program is free software; you can redistribute it and/or modify it
  11 * under the terms of the GNU General Public License version 2 as published by
  12 * the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful, but WITHOUT
  15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  17 * more details.
  18 *
  19 * You should have received a copy of the GNU General Public License along with
  20 * this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22
  23#define DSS_SUBSYS_NAME "DISPLAY"
  24
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/jiffies.h>
  28#include <linux/platform_device.h>
  29#include <linux/of.h>
  30
  31#include "omapdss.h"
  32
  33void omapdss_default_get_timings(struct omap_dss_device *dssdev,
  34                                 struct videomode *vm)
  35{
  36        *vm = dssdev->panel.vm;
  37}
  38EXPORT_SYMBOL(omapdss_default_get_timings);
  39
  40static LIST_HEAD(panel_list);
  41static DEFINE_MUTEX(panel_list_mutex);
  42static int disp_num_counter;
  43
  44int omapdss_register_display(struct omap_dss_device *dssdev)
  45{
  46        struct omap_dss_driver *drv = dssdev->driver;
  47        struct list_head *cur;
  48        int id;
  49
  50        /*
  51         * Note: this presumes that all displays either have an DT alias, or
  52         * none has.
  53         */
  54        id = of_alias_get_id(dssdev->dev->of_node, "display");
  55        if (id < 0)
  56                id = disp_num_counter++;
  57
  58        snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id);
  59
  60        /* Use 'label' property for name, if it exists */
  61        of_property_read_string(dssdev->dev->of_node, "label", &dssdev->name);
  62
  63        if (dssdev->name == NULL)
  64                dssdev->name = dssdev->alias;
  65
  66        if (drv && drv->get_timings == NULL)
  67                drv->get_timings = omapdss_default_get_timings;
  68
  69        mutex_lock(&panel_list_mutex);
  70        list_for_each(cur, &panel_list) {
  71                struct omap_dss_device *ldev = list_entry(cur,
  72                                                         struct omap_dss_device,
  73                                                         panel_list);
  74                if (strcmp(ldev->alias, dssdev->alias) > 0)
  75                        break;
  76        }
  77        list_add_tail(&dssdev->panel_list, cur);
  78        mutex_unlock(&panel_list_mutex);
  79        return 0;
  80}
  81EXPORT_SYMBOL(omapdss_register_display);
  82
  83void omapdss_unregister_display(struct omap_dss_device *dssdev)
  84{
  85        mutex_lock(&panel_list_mutex);
  86        list_del(&dssdev->panel_list);
  87        mutex_unlock(&panel_list_mutex);
  88}
  89EXPORT_SYMBOL(omapdss_unregister_display);
  90
  91bool omapdss_component_is_display(struct device_node *node)
  92{
  93        struct omap_dss_device *dssdev;
  94        bool found = false;
  95
  96        mutex_lock(&panel_list_mutex);
  97        list_for_each_entry(dssdev, &panel_list, panel_list) {
  98                if (dssdev->dev->of_node == node) {
  99                        found = true;
 100                        goto out;
 101                }
 102        }
 103out:
 104        mutex_unlock(&panel_list_mutex);
 105        return found;
 106}
 107EXPORT_SYMBOL(omapdss_component_is_display);
 108
 109struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev)
 110{
 111        if (!try_module_get(dssdev->owner))
 112                return NULL;
 113
 114        if (get_device(dssdev->dev) == NULL) {
 115                module_put(dssdev->owner);
 116                return NULL;
 117        }
 118
 119        return dssdev;
 120}
 121EXPORT_SYMBOL(omap_dss_get_device);
 122
 123void omap_dss_put_device(struct omap_dss_device *dssdev)
 124{
 125        put_device(dssdev->dev);
 126        module_put(dssdev->owner);
 127}
 128EXPORT_SYMBOL(omap_dss_put_device);
 129
 130/*
 131 * ref count of the found device is incremented.
 132 * ref count of from-device is decremented.
 133 */
 134struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
 135{
 136        struct list_head *l;
 137        struct omap_dss_device *dssdev;
 138
 139        mutex_lock(&panel_list_mutex);
 140
 141        if (list_empty(&panel_list)) {
 142                dssdev = NULL;
 143                goto out;
 144        }
 145
 146        if (from == NULL) {
 147                dssdev = list_first_entry(&panel_list, struct omap_dss_device,
 148                                panel_list);
 149                omap_dss_get_device(dssdev);
 150                goto out;
 151        }
 152
 153        omap_dss_put_device(from);
 154
 155        list_for_each(l, &panel_list) {
 156                dssdev = list_entry(l, struct omap_dss_device, panel_list);
 157                if (dssdev == from) {
 158                        if (list_is_last(l, &panel_list)) {
 159                                dssdev = NULL;
 160                                goto out;
 161                        }
 162
 163                        dssdev = list_entry(l->next, struct omap_dss_device,
 164                                        panel_list);
 165                        omap_dss_get_device(dssdev);
 166                        goto out;
 167                }
 168        }
 169
 170        WARN(1, "'from' dssdev not found\n");
 171
 172        dssdev = NULL;
 173out:
 174        mutex_unlock(&panel_list_mutex);
 175        return dssdev;
 176}
 177EXPORT_SYMBOL(omap_dss_get_next_device);
 178
 179struct omap_dss_device *omap_dss_find_device(void *data,
 180                int (*match)(struct omap_dss_device *dssdev, void *data))
 181{
 182        struct omap_dss_device *dssdev = NULL;
 183
 184        while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
 185                if (match(dssdev, data))
 186                        return dssdev;
 187        }
 188
 189        return NULL;
 190}
 191EXPORT_SYMBOL(omap_dss_find_device);
 192