diff options
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.c | 1 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-mdevice.c | 108 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-mdevice.h | 5 | ||||
-rw-r--r-- | include/media/s5p_fimc.h | 1 |
4 files changed, 98 insertions, 17 deletions
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c index d39e47abb229..6a8098c42cc8 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.c +++ b/drivers/media/platform/s5p-fimc/fimc-core.c | |||
@@ -1281,7 +1281,6 @@ static const struct platform_device_id fimc_driver_ids[] = { | |||
1281 | }, | 1281 | }, |
1282 | { }, | 1282 | { }, |
1283 | }; | 1283 | }; |
1284 | MODULE_DEVICE_TABLE(platform, fimc_driver_ids); | ||
1285 | 1284 | ||
1286 | static const struct of_device_id fimc_of_match[] = { | 1285 | static const struct of_device_id fimc_of_match[] = { |
1287 | { | 1286 | { |
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index a17fcb2d5d41..d34106c66427 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c | |||
@@ -17,11 +17,16 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_platform.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include <linux/of_i2c.h> | ||
20 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
21 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
22 | #include <linux/types.h> | 26 | #include <linux/types.h> |
23 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
24 | #include <media/v4l2-ctrls.h> | 28 | #include <media/v4l2-ctrls.h> |
29 | #include <media/v4l2-of.h> | ||
25 | #include <media/media-device.h> | 30 | #include <media/media-device.h> |
26 | #include <media/s5p_fimc.h> | 31 | #include <media/s5p_fimc.h> |
27 | 32 | ||
@@ -264,6 +269,21 @@ static void fimc_md_unregister_sensor(struct v4l2_subdev *sd) | |||
264 | i2c_put_adapter(adapter); | 269 | i2c_put_adapter(adapter); |
265 | } | 270 | } |
266 | 271 | ||
272 | #ifdef CONFIG_OF | ||
273 | static int __of_get_csis_id(struct device_node *np) | ||
274 | { | ||
275 | u32 reg = 0; | ||
276 | |||
277 | np = of_get_child_by_name(np, "port"); | ||
278 | if (!np) | ||
279 | return -EINVAL; | ||
280 | of_property_read_u32(np, "reg", ®); | ||
281 | return reg - FIMC_INPUT_MIPI_CSI2_0; | ||
282 | } | ||
283 | #else | ||
284 | #define __of_get_csis_id(np) (-ENOSYS) | ||
285 | #endif | ||
286 | |||
267 | static int fimc_md_register_sensor_entities(struct fimc_md *fmd) | 287 | static int fimc_md_register_sensor_entities(struct fimc_md *fmd) |
268 | { | 288 | { |
269 | struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; | 289 | struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; |
@@ -368,13 +388,13 @@ static int register_csis_entity(struct fimc_md *fmd, | |||
368 | struct device_node *node = pdev->dev.of_node; | 388 | struct device_node *node = pdev->dev.of_node; |
369 | int id, ret; | 389 | int id, ret; |
370 | 390 | ||
371 | id = node ? of_alias_get_id(node, "csis") : max(0, pdev->id); | 391 | id = node ? __of_get_csis_id(node) : max(0, pdev->id); |
372 | 392 | ||
373 | if (WARN_ON(id >= CSIS_MAX_ENTITIES || fmd->csis[id].sd)) | 393 | if (WARN_ON(id < 0 || id >= CSIS_MAX_ENTITIES)) |
374 | return -EBUSY; | 394 | return -ENOENT; |
375 | 395 | ||
376 | if (WARN_ON(id >= CSIS_MAX_ENTITIES)) | 396 | if (WARN_ON(fmd->csis[id].sd)) |
377 | return 0; | 397 | return -EBUSY; |
378 | 398 | ||
379 | sd->grp_id = GRP_ID_CSIS; | 399 | sd->grp_id = GRP_ID_CSIS; |
380 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); | 400 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); |
@@ -457,6 +477,45 @@ static int fimc_md_pdev_match(struct device *dev, void *data) | |||
457 | return 0; | 477 | return 0; |
458 | } | 478 | } |
459 | 479 | ||
480 | /* Register FIMC, FIMC-LITE and CSIS media entities */ | ||
481 | #ifdef CONFIG_OF | ||
482 | static int fimc_md_register_of_platform_entities(struct fimc_md *fmd, | ||
483 | struct device_node *parent) | ||
484 | { | ||
485 | struct device_node *node; | ||
486 | int ret = 0; | ||
487 | |||
488 | for_each_available_child_of_node(parent, node) { | ||
489 | struct platform_device *pdev; | ||
490 | int plat_entity = -1; | ||
491 | |||
492 | pdev = of_find_device_by_node(node); | ||
493 | if (!pdev) | ||
494 | continue; | ||
495 | |||
496 | /* If driver of any entity isn't ready try all again later. */ | ||
497 | if (!strcmp(node->name, CSIS_OF_NODE_NAME)) | ||
498 | plat_entity = IDX_CSIS; | ||
499 | else if (!strcmp(node->name, FIMC_LITE_OF_NODE_NAME)) | ||
500 | plat_entity = IDX_FLITE; | ||
501 | else if (!strcmp(node->name, FIMC_OF_NODE_NAME) && | ||
502 | !of_property_read_bool(node, "samsung,lcd-wb")) | ||
503 | plat_entity = IDX_FIMC; | ||
504 | |||
505 | if (plat_entity >= 0) | ||
506 | ret = fimc_md_register_platform_entity(fmd, pdev, | ||
507 | plat_entity); | ||
508 | put_device(&pdev->dev); | ||
509 | if (ret < 0) | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | return ret; | ||
514 | } | ||
515 | #else | ||
516 | #define fimc_md_register_of_platform_entities(fmd, node) (-ENOSYS) | ||
517 | #endif | ||
518 | |||
460 | static void fimc_md_unregister_entities(struct fimc_md *fmd) | 519 | static void fimc_md_unregister_entities(struct fimc_md *fmd) |
461 | { | 520 | { |
462 | int i; | 521 | int i; |
@@ -929,11 +988,12 @@ static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO, | |||
929 | 988 | ||
930 | static int fimc_md_probe(struct platform_device *pdev) | 989 | static int fimc_md_probe(struct platform_device *pdev) |
931 | { | 990 | { |
991 | struct device *dev = &pdev->dev; | ||
932 | struct v4l2_device *v4l2_dev; | 992 | struct v4l2_device *v4l2_dev; |
933 | struct fimc_md *fmd; | 993 | struct fimc_md *fmd; |
934 | int ret; | 994 | int ret; |
935 | 995 | ||
936 | fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL); | 996 | fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL); |
937 | if (!fmd) | 997 | if (!fmd) |
938 | return -ENOMEM; | 998 | return -ENOMEM; |
939 | 999 | ||
@@ -943,15 +1003,14 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
943 | strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", | 1003 | strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", |
944 | sizeof(fmd->media_dev.model)); | 1004 | sizeof(fmd->media_dev.model)); |
945 | fmd->media_dev.link_notify = fimc_md_link_notify; | 1005 | fmd->media_dev.link_notify = fimc_md_link_notify; |
946 | fmd->media_dev.dev = &pdev->dev; | 1006 | fmd->media_dev.dev = dev; |
947 | 1007 | ||
948 | v4l2_dev = &fmd->v4l2_dev; | 1008 | v4l2_dev = &fmd->v4l2_dev; |
949 | v4l2_dev->mdev = &fmd->media_dev; | 1009 | v4l2_dev->mdev = &fmd->media_dev; |
950 | v4l2_dev->notify = fimc_sensor_notify; | 1010 | v4l2_dev->notify = fimc_sensor_notify; |
951 | snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s", | 1011 | strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name)); |
952 | dev_name(&pdev->dev)); | ||
953 | 1012 | ||
954 | ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); | 1013 | ret = v4l2_device_register(dev, &fmd->v4l2_dev); |
955 | if (ret < 0) { | 1014 | if (ret < 0) { |
956 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); | 1015 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); |
957 | return ret; | 1016 | return ret; |
@@ -965,21 +1024,25 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
965 | if (ret) | 1024 | if (ret) |
966 | goto err_clk; | 1025 | goto err_clk; |
967 | 1026 | ||
968 | fmd->user_subdev_api = false; | 1027 | fmd->user_subdev_api = (dev->of_node != NULL); |
969 | 1028 | ||
970 | /* Protect the media graph while we're registering entities */ | 1029 | /* Protect the media graph while we're registering entities */ |
971 | mutex_lock(&fmd->media_dev.graph_mutex); | 1030 | mutex_lock(&fmd->media_dev.graph_mutex); |
972 | 1031 | ||
973 | ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, | 1032 | if (dev->of_node) |
974 | fimc_md_pdev_match); | 1033 | ret = fimc_md_register_of_platform_entities(fmd, dev->of_node); |
1034 | else | ||
1035 | ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, | ||
1036 | fimc_md_pdev_match); | ||
975 | if (ret) | 1037 | if (ret) |
976 | goto err_unlock; | 1038 | goto err_unlock; |
977 | 1039 | ||
978 | if (pdev->dev.platform_data) { | 1040 | if (dev->platform_data) { |
979 | ret = fimc_md_register_sensor_entities(fmd); | 1041 | ret = fimc_md_register_sensor_entities(fmd); |
980 | if (ret) | 1042 | if (ret) |
981 | goto err_unlock; | 1043 | goto err_unlock; |
982 | } | 1044 | } |
1045 | |||
983 | ret = fimc_md_create_links(fmd); | 1046 | ret = fimc_md_create_links(fmd); |
984 | if (ret) | 1047 | if (ret) |
985 | goto err_unlock; | 1048 | goto err_unlock; |
@@ -1019,12 +1082,25 @@ static int fimc_md_remove(struct platform_device *pdev) | |||
1019 | return 0; | 1082 | return 0; |
1020 | } | 1083 | } |
1021 | 1084 | ||
1085 | static struct platform_device_id fimc_driver_ids[] __always_unused = { | ||
1086 | { .name = "s5p-fimc-md" }, | ||
1087 | { }, | ||
1088 | }; | ||
1089 | MODULE_DEVICE_TABLE(platform, fimc_driver_ids); | ||
1090 | |||
1091 | static const struct of_device_id fimc_md_of_match[] = { | ||
1092 | { .compatible = "samsung,fimc" }, | ||
1093 | { }, | ||
1094 | }; | ||
1095 | MODULE_DEVICE_TABLE(of, fimc_md_of_match); | ||
1096 | |||
1022 | static struct platform_driver fimc_md_driver = { | 1097 | static struct platform_driver fimc_md_driver = { |
1023 | .probe = fimc_md_probe, | 1098 | .probe = fimc_md_probe, |
1024 | .remove = fimc_md_remove, | 1099 | .remove = fimc_md_remove, |
1025 | .driver = { | 1100 | .driver = { |
1026 | .name = "s5p-fimc-md", | 1101 | .of_match_table = of_match_ptr(fimc_md_of_match), |
1027 | .owner = THIS_MODULE, | 1102 | .name = "s5p-fimc-md", |
1103 | .owner = THIS_MODULE, | ||
1028 | } | 1104 | } |
1029 | }; | 1105 | }; |
1030 | 1106 | ||
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h index 06b0d8276fd2..b6ceb5984664 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h | |||
@@ -21,6 +21,11 @@ | |||
21 | #include "fimc-lite.h" | 21 | #include "fimc-lite.h" |
22 | #include "mipi-csis.h" | 22 | #include "mipi-csis.h" |
23 | 23 | ||
24 | #define FIMC_OF_NODE_NAME "fimc" | ||
25 | #define FIMC_LITE_OF_NODE_NAME "fimc-lite" | ||
26 | #define FIMC_IS_OF_NODE_NAME "fimc-is" | ||
27 | #define CSIS_OF_NODE_NAME "csis" | ||
28 | |||
24 | /* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */ | 29 | /* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */ |
25 | #define GRP_ID_SENSOR (1 << 8) | 30 | #define GRP_ID_SENSOR (1 << 8) |
26 | #define GRP_ID_FIMC_IS_SENSOR (1 << 9) | 31 | #define GRP_ID_FIMC_IS_SENSOR (1 << 9) |
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h index d6dbb791f423..e2c598962698 100644 --- a/include/media/s5p_fimc.h +++ b/include/media/s5p_fimc.h | |||
@@ -94,6 +94,7 @@ enum fimc_subdev_index { | |||
94 | IDX_SENSOR, | 94 | IDX_SENSOR, |
95 | IDX_CSIS, | 95 | IDX_CSIS, |
96 | IDX_FLITE, | 96 | IDX_FLITE, |
97 | IDX_IS_ISP, | ||
97 | IDX_FIMC, | 98 | IDX_FIMC, |
98 | IDX_MAX, | 99 | IDX_MAX, |
99 | }; | 100 | }; |