linux/drivers/gpu/drm/exynos/exynos_drm_core.c
<<
>>
Prefs
   1/* exynos_drm_core.c
   2 *
   3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
   4 * Author:
   5 *      Inki Dae <inki.dae@samsung.com>
   6 *      Joonyoung Shim <jy0922.shim@samsung.com>
   7 *      Seung-Woo Kim <sw0312.kim@samsung.com>
   8 *
   9 * This program is free software; you can redistribute  it and/or modify it
  10 * under  the terms of  the GNU General  Public License as published by the
  11 * Free Software Foundation;  either version 2 of the  License, or (at your
  12 * option) any later version.
  13 */
  14
  15#include <drm/drmP.h>
  16#include "exynos_drm_drv.h"
  17#include "exynos_drm_crtc.h"
  18#include "exynos_drm_encoder.h"
  19#include "exynos_drm_fbdev.h"
  20
  21static LIST_HEAD(exynos_drm_subdrv_list);
  22
  23int exynos_drm_create_enc_conn(struct drm_device *dev,
  24                                        struct exynos_drm_display *display)
  25{
  26        struct drm_encoder *encoder;
  27        int ret;
  28        unsigned long possible_crtcs = 0;
  29
  30        ret = exynos_drm_crtc_get_pipe_from_type(dev, display->type);
  31        if (ret < 0)
  32                return ret;
  33
  34        possible_crtcs |= 1 << ret;
  35
  36        /* create and initialize a encoder for this sub driver. */
  37        encoder = exynos_drm_encoder_create(dev, display, possible_crtcs);
  38        if (!encoder) {
  39                DRM_ERROR("failed to create encoder\n");
  40                return -EFAULT;
  41        }
  42
  43        display->encoder = encoder;
  44
  45        ret = display->ops->create_connector(display, encoder);
  46        if (ret) {
  47                DRM_ERROR("failed to create connector ret = %d\n", ret);
  48                goto err_destroy_encoder;
  49        }
  50
  51        return 0;
  52
  53err_destroy_encoder:
  54        encoder->funcs->destroy(encoder);
  55        return ret;
  56}
  57
  58int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
  59{
  60        if (!subdrv)
  61                return -EINVAL;
  62
  63        list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
  64
  65        return 0;
  66}
  67EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
  68
  69int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
  70{
  71        if (!subdrv)
  72                return -EINVAL;
  73
  74        list_del(&subdrv->list);
  75
  76        return 0;
  77}
  78EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
  79
  80int exynos_drm_device_subdrv_probe(struct drm_device *dev)
  81{
  82        struct exynos_drm_subdrv *subdrv, *n;
  83        int err;
  84
  85        if (!dev)
  86                return -EINVAL;
  87
  88        list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
  89                if (subdrv->probe) {
  90                        subdrv->drm_dev = dev;
  91
  92                        /*
  93                         * this probe callback would be called by sub driver
  94                         * after setting of all resources to this sub driver,
  95                         * such as clock, irq and register map are done.
  96                         */
  97                        err = subdrv->probe(dev, subdrv->dev);
  98                        if (err) {
  99                                DRM_DEBUG("exynos drm subdrv probe failed.\n");
 100                                list_del(&subdrv->list);
 101                                continue;
 102                        }
 103                }
 104        }
 105
 106        return 0;
 107}
 108EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_probe);
 109
 110int exynos_drm_device_subdrv_remove(struct drm_device *dev)
 111{
 112        struct exynos_drm_subdrv *subdrv;
 113
 114        if (!dev) {
 115                WARN(1, "Unexpected drm device unregister!\n");
 116                return -EINVAL;
 117        }
 118
 119        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
 120                if (subdrv->remove)
 121                        subdrv->remove(dev, subdrv->dev);
 122        }
 123
 124        return 0;
 125}
 126EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_remove);
 127
 128int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
 129{
 130        struct exynos_drm_subdrv *subdrv;
 131        int ret;
 132
 133        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
 134                if (subdrv->open) {
 135                        ret = subdrv->open(dev, subdrv->dev, file);
 136                        if (ret)
 137                                goto err;
 138                }
 139        }
 140
 141        return 0;
 142
 143err:
 144        list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
 145                if (subdrv->close)
 146                        subdrv->close(dev, subdrv->dev, file);
 147        }
 148        return ret;
 149}
 150EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open);
 151
 152void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
 153{
 154        struct exynos_drm_subdrv *subdrv;
 155
 156        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
 157                if (subdrv->close)
 158                        subdrv->close(dev, subdrv->dev, file);
 159        }
 160}
 161EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
 162