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_fbdev.h" 19 20static LIST_HEAD(exynos_drm_subdrv_list); 21 22int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) 23{ 24 if (!subdrv) 25 return -EINVAL; 26 27 list_add_tail(&subdrv->list, &exynos_drm_subdrv_list); 28 29 return 0; 30} 31 32int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv) 33{ 34 if (!subdrv) 35 return -EINVAL; 36 37 list_del(&subdrv->list); 38 39 return 0; 40} 41 42int exynos_drm_device_subdrv_probe(struct drm_device *dev) 43{ 44 struct exynos_drm_subdrv *subdrv, *n; 45 int err; 46 47 if (!dev) 48 return -EINVAL; 49 50 list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) { 51 if (subdrv->probe) { 52 subdrv->drm_dev = dev; 53 54 /* 55 * this probe callback would be called by sub driver 56 * after setting of all resources to this sub driver, 57 * such as clock, irq and register map are done. 58 */ 59 err = subdrv->probe(dev, subdrv->dev); 60 if (err) { 61 DRM_DEBUG("exynos drm subdrv probe failed.\n"); 62 list_del(&subdrv->list); 63 continue; 64 } 65 } 66 } 67 68 return 0; 69} 70 71int exynos_drm_device_subdrv_remove(struct drm_device *dev) 72{ 73 struct exynos_drm_subdrv *subdrv; 74 75 if (!dev) { 76 WARN(1, "Unexpected drm device unregister!\n"); 77 return -EINVAL; 78 } 79 80 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { 81 if (subdrv->remove) 82 subdrv->remove(dev, subdrv->dev); 83 } 84 85 return 0; 86} 87 88int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) 89{ 90 struct exynos_drm_subdrv *subdrv; 91 int ret; 92 93 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { 94 if (subdrv->open) { 95 ret = subdrv->open(dev, subdrv->dev, file); 96 if (ret) 97 goto err; 98 } 99 } 100 101 return 0; 102 103err: 104 list_for_each_entry_reverse(subdrv, &subdrv->list, list) { 105 if (subdrv->close) 106 subdrv->close(dev, subdrv->dev, file); 107 } 108 return ret; 109} 110 111void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file) 112{ 113 struct exynos_drm_subdrv *subdrv; 114 115 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { 116 if (subdrv->close) 117 subdrv->close(dev, subdrv->dev, file); 118 } 119} 120