mirror of https://gitee.com/openkylin/linux.git
drm/exynos: separated subdrv_probe function into two parts.
Changelog v2: fixed the issue that when sub driver is probed, no kms drivers such as fimd or hdmi are failed. no kms drivers have no manager so if manager is null then encoder and connector creation should be ignored. Changelog v1: this patch separates exynos_drm_subdrv_probe function into sub driver's probe call and encoder/connector creation so that exynos drm core module can take exception when some operation was failed properly. Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
This commit is contained in:
parent
29cb602532
commit
41fecf3e82
|
@ -34,33 +34,15 @@
|
|||
|
||||
static LIST_HEAD(exynos_drm_subdrv_list);
|
||||
|
||||
static int exynos_drm_subdrv_probe(struct drm_device *dev,
|
||||
static int exynos_drm_create_enc_conn(struct drm_device *dev,
|
||||
struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (subdrv->probe) {
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* 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 or by load()
|
||||
* of exynos drm driver.
|
||||
*
|
||||
* P.S. note that this driver is considered for modularization.
|
||||
*/
|
||||
ret = subdrv->probe(dev, subdrv->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!subdrv->manager)
|
||||
return 0;
|
||||
|
||||
subdrv->manager->dev = subdrv->dev;
|
||||
|
||||
/* create and initialize a encoder for this sub driver. */
|
||||
|
@ -78,24 +60,22 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
|
|||
connector = exynos_drm_connector_create(dev, encoder);
|
||||
if (!connector) {
|
||||
DRM_ERROR("failed to create connector\n");
|
||||
encoder->funcs->destroy(encoder);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto err_destroy_encoder;
|
||||
}
|
||||
|
||||
subdrv->encoder = encoder;
|
||||
subdrv->connector = connector;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_encoder:
|
||||
encoder->funcs->destroy(encoder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void exynos_drm_subdrv_remove(struct drm_device *dev,
|
||||
struct exynos_drm_subdrv *subdrv)
|
||||
static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (subdrv->remove)
|
||||
subdrv->remove(dev, subdrv->dev);
|
||||
|
||||
if (subdrv->encoder) {
|
||||
struct drm_encoder *encoder = subdrv->encoder;
|
||||
encoder->funcs->destroy(encoder);
|
||||
|
@ -109,9 +89,43 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
static int exynos_drm_subdrv_probe(struct drm_device *dev,
|
||||
struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
if (subdrv->probe) {
|
||||
int ret;
|
||||
|
||||
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 or by load()
|
||||
* of exynos drm driver.
|
||||
*
|
||||
* P.S. note that this driver is considered for modularization.
|
||||
*/
|
||||
ret = subdrv->probe(dev, subdrv->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_drm_subdrv_remove(struct drm_device *dev,
|
||||
struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (subdrv->remove)
|
||||
subdrv->remove(dev, subdrv->dev);
|
||||
}
|
||||
|
||||
int exynos_drm_device_register(struct drm_device *dev)
|
||||
{
|
||||
struct exynos_drm_subdrv *subdrv, *n;
|
||||
unsigned int fine_cnt = 0;
|
||||
int err;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
@ -120,14 +134,36 @@ int exynos_drm_device_register(struct drm_device *dev)
|
|||
return -EINVAL;
|
||||
|
||||
list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
|
||||
subdrv->drm_dev = dev;
|
||||
err = exynos_drm_subdrv_probe(dev, subdrv);
|
||||
if (err) {
|
||||
DRM_DEBUG("exynos drm subdrv probe failed.\n");
|
||||
list_del(&subdrv->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if manager is null then it means that this sub driver
|
||||
* doesn't need encoder and connector.
|
||||
*/
|
||||
if (!subdrv->manager) {
|
||||
fine_cnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
err = exynos_drm_create_enc_conn(dev, subdrv);
|
||||
if (err) {
|
||||
DRM_DEBUG("failed to create encoder and connector.\n");
|
||||
exynos_drm_subdrv_remove(dev, subdrv);
|
||||
list_del(&subdrv->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
fine_cnt++;
|
||||
}
|
||||
|
||||
if (!fine_cnt)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(exynos_drm_device_register);
|
||||
|
@ -143,8 +179,10 @@ int exynos_drm_device_unregister(struct drm_device *dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
|
||||
list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
|
||||
exynos_drm_subdrv_remove(dev, subdrv);
|
||||
exynos_drm_destroy_enc_conn(subdrv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue