diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 4d6b86791187..7b90a897beeb 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -1992,7 +1992,7 @@ static struct platform_driver fimc_driver = { int __init fimc_register_driver(void) { - return platform_driver_probe(&fimc_driver, fimc_probe); + return platform_driver_register(&fimc_driver); } void __exit fimc_unregister_driver(void) diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 62ed37e40149..75296a625a9d 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -214,14 +214,20 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, return NULL; adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num); - if (!adapter) - return NULL; + if (!adapter) { + v4l2_warn(&fmd->v4l2_dev, + "Failed to get I2C adapter %d, deferring probe\n", + s_info->pdata->i2c_bus_num); + return ERR_PTR(-EPROBE_DEFER); + } sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, s_info->pdata->board_info, NULL); if (IS_ERR_OR_NULL(sd)) { i2c_put_adapter(adapter); - v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n"); - return NULL; + v4l2_warn(&fmd->v4l2_dev, + "Failed to acquire subdev %s, deferring probe\n", + s_info->pdata->board_info->type); + return ERR_PTR(-EPROBE_DEFER); } v4l2_set_subdev_hostdata(sd, s_info); sd->grp_id = SENSOR_GROUP_ID; @@ -269,13 +275,22 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) fmd->num_sensors = num_clients; for (i = 0; i < num_clients; i++) { + struct v4l2_subdev *sd; + fmd->sensor[i].pdata = &pdata->isp_info[i]; ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true); if (ret) break; - fmd->sensor[i].subdev = - fimc_md_register_sensor(fmd, &fmd->sensor[i]); + sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]); ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false); + + if (!IS_ERR(sd)) { + fmd->sensor[i].subdev = sd; + } else { + fmd->sensor[i].subdev = NULL; + ret = PTR_ERR(sd); + break; + } if (ret) break; } @@ -336,22 +351,45 @@ static int csis_register_callback(struct device *dev, void *p) */ static int fimc_md_register_platform_entities(struct fimc_md *fmd) { + struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; struct device_driver *driver; - int ret; + int ret, i; driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type); - if (!driver) - return -ENODEV; + if (!driver) { + v4l2_warn(&fmd->v4l2_dev, + "%s driver not found, deffering probe\n", + FIMC_MODULE_NAME); + return -EPROBE_DEFER; + } + ret = driver_for_each_device(driver, NULL, fmd, fimc_register_callback); if (ret) return ret; + /* + * Check if there is any sensor on the MIPI-CSI2 bus and + * if not skip the s5p-csis module loading. + */ + for (i = 0; i < pdata->num_clients; i++) { + if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) { + ret = 1; + break; + } + } + if (!ret) + return 0; driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); - if (driver) - ret = driver_for_each_device(driver, NULL, fmd, - csis_register_callback); - return ret; + if (!driver || !try_module_get(driver->owner)) { + v4l2_warn(&fmd->v4l2_dev, + "%s driver not found, deffering probe\n", + CSIS_DRIVER_NAME); + return -EPROBE_DEFER; + } + + return driver_for_each_device(driver, NULL, fmd, + csis_register_callback); } static void fimc_md_unregister_entities(struct fimc_md *fmd) @@ -369,6 +407,7 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) if (fmd->csis[i].sd == NULL) continue; v4l2_device_unregister_subdev(fmd->csis[i].sd); + module_put(fmd->csis[i].sd->owner); fmd->csis[i].sd = NULL; } for (i = 0; i < fmd->num_sensors; i++) { @@ -744,7 +783,7 @@ static ssize_t fimc_md_sysfs_store(struct device *dev, static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO, fimc_md_sysfs_show, fimc_md_sysfs_store); -static int __devinit fimc_md_probe(struct platform_device *pdev) +static int fimc_md_probe(struct platform_device *pdev) { struct v4l2_device *v4l2_dev; struct fimc_md *fmd; @@ -841,10 +880,12 @@ static struct platform_driver fimc_md_driver = { int __init fimc_md_init(void) { int ret; + request_module("s5p-csis"); ret = fimc_register_driver(); if (ret) return ret; + return platform_driver_register(&fimc_md_driver); } void __exit fimc_md_exit(void) diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c index 1cd6b6bc6279..2f73d9e3d0b7 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.c +++ b/drivers/media/video/s5p-fimc/mipi-csis.c @@ -715,19 +715,8 @@ static struct platform_driver s5pcsis_driver = { }, }; -static int __init s5pcsis_init(void) -{ - return platform_driver_probe(&s5pcsis_driver, s5pcsis_probe); -} - -static void __exit s5pcsis_exit(void) -{ - platform_driver_unregister(&s5pcsis_driver); -} - -module_init(s5pcsis_init); -module_exit(s5pcsis_exit); +module_platform_driver(s5pcsis_driver); MODULE_AUTHOR("Sylwester Nawrocki "); -MODULE_DESCRIPTION("S5P/EXYNOS4 MIPI CSI receiver driver"); +MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver"); MODULE_LICENSE("GPL");