aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-core.c1
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-mdevice.c108
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-mdevice.h5
-rw-r--r--include/media/s5p_fimc.h1
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};
1284MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1285 1284
1286static const struct of_device_id fimc_of_match[] = { 1285static 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
273static 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", &reg);
281 return reg - FIMC_INPUT_MIPI_CSI2_0;
282}
283#else
284#define __of_get_csis_id(np) (-ENOSYS)
285#endif
286
267static int fimc_md_register_sensor_entities(struct fimc_md *fmd) 287static 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
482static 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
460static void fimc_md_unregister_entities(struct fimc_md *fmd) 519static 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
930static int fimc_md_probe(struct platform_device *pdev) 989static 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
1085static struct platform_device_id fimc_driver_ids[] __always_unused = {
1086 { .name = "s5p-fimc-md" },
1087 { },
1088};
1089MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1090
1091static const struct of_device_id fimc_md_of_match[] = {
1092 { .compatible = "samsung,fimc" },
1093 { },
1094};
1095MODULE_DEVICE_TABLE(of, fimc_md_of_match);
1096
1022static struct platform_driver fimc_md_driver = { 1097static 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};