drm/tgm: add sub driver handling interface. 68/136968/4
authorjonggab.park <jonggab.park@samsung.com>
Fri, 28 Apr 2017 05:09:54 +0000 (14:09 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Tue, 4 Jul 2017 02:25:37 +0000 (02:25 +0000)
It doesn't have the pp interface for the pp driver.
And this patch is from product kernel.

Change-Id: Iceb891e602fe6e6e246445b7d845927cc39a73c0
Signed-off-by: Jin-young Jeon <jy0.jeon@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/tgm/tgm_drv.c
drivers/gpu/drm/tgm/tgm_drv.h

index 2053b00cb472bb20c20af5122ff84d9c23413968..bd8570042f51e6ff9bdbd95264166aebd6f4826e 100644 (file)
@@ -30,6 +30,113 @@ struct component_dev {
        struct device *irq_dev;
 };
 
+static LIST_HEAD(tgm_subdrv_list);
+
+int tgm_subdrv_register(struct tgm_subdrv *subdrv)
+{
+       if (!subdrv)
+               return -EINVAL;
+
+       list_add_tail(&subdrv->list, &tgm_subdrv_list);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tgm_subdrv_register);
+
+int tgm_subdrv_unregister(struct tgm_subdrv *subdrv)
+{
+       if (!subdrv)
+               return -EINVAL;
+
+       list_del(&subdrv->list);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tgm_subdrv_unregister);
+
+int tgm_device_subdrv_probe(struct drm_device *dev)
+{
+       struct tgm_subdrv *subdrv, *n;
+       int err;
+
+       if (!dev)
+               return -EINVAL;
+
+       list_for_each_entry_safe(subdrv, n, &tgm_subdrv_list, list) {
+               if (subdrv->probe) {
+                       subdrv->drm_dev = dev;
+
+                       /*
+                        * this probe callback would be called by sub driver
+                        * after setting of all resources to this sub driver,
+                        * such as clock, irq and register map are done.
+                        */
+                       err = subdrv->probe(dev, subdrv->dev);
+                       if (err) {
+                               DRM_DEBUG("exynos drm subdrv probe failed.\n");
+                               list_del(&subdrv->list);
+                               continue;
+                       }
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tgm_device_subdrv_probe);
+
+int tgm_device_subdrv_remove(struct drm_device *dev)
+{
+       struct tgm_subdrv *subdrv;
+
+       if (!dev) {
+               WARN(1, "Unexpected drm device unregister!\n");
+               return -EINVAL;
+       }
+
+       list_for_each_entry(subdrv, &tgm_subdrv_list, list) {
+               if (subdrv->remove)
+                       subdrv->remove(dev, subdrv->dev);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tgm_device_subdrv_remove);
+
+int tgm_subdrv_open(struct drm_device *dev, struct drm_file *file)
+{
+       struct tgm_subdrv *subdrv;
+       int ret;
+
+       list_for_each_entry(subdrv, &tgm_subdrv_list, list) {
+               if (subdrv->open) {
+                       ret = subdrv->open(dev, subdrv->dev, file);
+                       if (ret)
+                               goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
+               if (subdrv->close)
+                       subdrv->close(dev, subdrv->dev, file);
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tgm_subdrv_open);
+
+void tgm_subdrv_close(struct drm_device *dev, struct drm_file *file)
+{
+       struct tgm_subdrv *subdrv;
+
+       list_for_each_entry(subdrv, &tgm_subdrv_list, list) {
+               if (subdrv->close)
+                       subdrv->close(dev, subdrv->dev, file);
+       }
+}
+EXPORT_SYMBOL_GPL(tgm_subdrv_close);
+
 static int tgm_drv_load(struct drm_device *drm_dev, unsigned long flags)
 {
        struct tgm_drv_private *dev_priv;
index 5af11712b575ce1a5d8f0f20ed34ef2d2753b9ea..a0f0ce07dd1e7f6195300cef1949c321fb7083d8 100644 (file)
@@ -33,9 +33,29 @@ struct tgm_drv_file_private {
        pid_t tgid;
 };
 
+struct tgm_subdrv {
+       struct list_head list;
+       struct device *dev;
+       struct drm_device *drm_dev;
+
+       int (*probe)(struct drm_device *drm_dev, struct device *dev);
+       void (*remove)(struct drm_device *drm_dev, struct device *dev);
+       int (*open)(struct drm_device *drm_dev, struct device *dev,
+                       struct drm_file *file);
+       void (*close)(struct drm_device *drm_dev, struct device *dev,
+                       struct drm_file *file);
+};
+
 int tgm_drv_component_add(struct device *dev,
                enum tgm_drv_dev_type dev_type);
 void tgm_drv_component_del(struct device *dev,
                enum tgm_drv_dev_type dev_type);
 
+int tgm_subdrv_register(struct tgm_subdrv *drm_subdrv);
+int tgm_subdrv_unregister(struct tgm_subdrv *drm_subdrv);
+int tgm_device_subdrv_probe(struct drm_device *dev);
+int tgm_device_subdrv_remove(struct drm_device *dev);
+int tgm_subdrv_open(struct drm_device *dev, struct drm_file *file);
+void tgm_subdrv_close(struct drm_device *dev, struct drm_file *file);
+
 #endif /* _TGM_DRV_H_ */