hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/platform/exynos4-is/media-dev.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * S5P/EXYNOS4 SoC series camera host interface media device driver
34 *
45 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
56 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published
9
- * by the Free Software Foundation, either version 2 of the License,
10
- * or (at your option) any later version.
117 */
128
139 #include <linux/bug.h>
....@@ -23,6 +19,7 @@
2319 #include <linux/of_platform.h>
2420 #include <linux/of_device.h>
2521 #include <linux/of_graph.h>
22
+#include <linux/pinctrl/consumer.h>
2623 #include <linux/platform_device.h>
2724 #include <linux/pm_runtime.h>
2825 #include <linux/types.h>
....@@ -96,7 +93,7 @@
9693 switch (sd->grp_id) {
9794 case GRP_ID_SENSOR:
9895 sensor = sd;
99
- /* fall through */
96
+ fallthrough;
10097 case GRP_ID_FIMC_IS_SENSOR:
10198 p->subdevs[IDX_SENSOR] = sd;
10299 break;
....@@ -293,11 +290,26 @@
293290 { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },
294291 };
295292 struct fimc_pipeline *p = to_fimc_pipeline(ep);
296
- struct fimc_md *fmd = entity_to_fimc_mdev(&p->subdevs[IDX_CSIS]->entity);
297293 enum fimc_subdev_index sd_id;
298294 int i, ret = 0;
299295
300296 if (p->subdevs[IDX_SENSOR] == NULL) {
297
+ struct fimc_md *fmd;
298
+ struct v4l2_subdev *sd = p->subdevs[IDX_CSIS];
299
+
300
+ if (!sd)
301
+ sd = p->subdevs[IDX_FIMC];
302
+
303
+ if (!sd) {
304
+ /*
305
+ * If neither CSIS nor FIMC was set up,
306
+ * it's impossible to have any sensors
307
+ */
308
+ return -ENODEV;
309
+ }
310
+
311
+ fmd = entity_to_fimc_mdev(&sd->entity);
312
+
301313 if (!fmd->user_subdev_api) {
302314 /*
303315 * Sensor must be already discovered if we
....@@ -383,20 +395,14 @@
383395 }
384396 }
385397
386
-/* Parse port node and register as a sub-device any sensor specified there. */
387
-static int fimc_md_parse_port_node(struct fimc_md *fmd,
388
- struct device_node *port,
389
- unsigned int index)
398
+static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
399
+ struct device_node *ep)
390400 {
401
+ int index = fmd->num_sensors;
391402 struct fimc_source_info *pd = &fmd->sensor[index].pdata;
392
- struct device_node *rem, *ep, *np;
393
- struct v4l2_fwnode_endpoint endpoint;
403
+ struct device_node *rem, *np;
404
+ struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
394405 int ret;
395
-
396
- /* Assume here a port node can have only one endpoint node. */
397
- ep = of_get_next_child(port, NULL);
398
- if (!ep)
399
- return 0;
400406
401407 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &endpoint);
402408 if (ret) {
....@@ -445,10 +451,11 @@
445451 */
446452 np = of_get_parent(rem);
447453
448
- if (np && !of_node_cmp(np->name, "i2c-isp"))
454
+ if (of_node_name_eq(np, "i2c-isp"))
449455 pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;
450456 else
451457 pd->fimc_bus_type = pd->sensor_bus_type;
458
+ of_node_put(np);
452459
453460 if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) {
454461 of_node_put(rem);
....@@ -457,11 +464,32 @@
457464
458465 fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
459466 fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
460
- fmd->async_subdevs[index] = &fmd->sensor[index].asd;
467
+
468
+ ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier,
469
+ &fmd->sensor[index].asd);
470
+ if (ret) {
471
+ of_node_put(rem);
472
+ return ret;
473
+ }
461474
462475 fmd->num_sensors++;
463476
464
- of_node_put(rem);
477
+ return 0;
478
+}
479
+
480
+/* Parse port node and register as a sub-device any sensor specified there. */
481
+static int fimc_md_parse_port_node(struct fimc_md *fmd,
482
+ struct device_node *port)
483
+{
484
+ struct device_node *ep;
485
+ int ret;
486
+
487
+ for_each_child_of_node(port, ep) {
488
+ ret = fimc_md_parse_one_endpoint(fmd, ep);
489
+ if (ret < 0)
490
+ return ret;
491
+ }
492
+
465493 return 0;
466494 }
467495
....@@ -469,8 +497,8 @@
469497 static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
470498 {
471499 struct device_node *parent = fmd->pdev->dev.of_node;
472
- struct device_node *node, *ports;
473
- int index = 0;
500
+ struct device_node *ports = NULL;
501
+ struct device_node *node;
474502 int ret;
475503
476504 /*
....@@ -480,11 +508,9 @@
480508 if (!fmd->pmf)
481509 return -ENXIO;
482510
483
- ret = pm_runtime_get_sync(fmd->pmf);
484
- if (ret < 0) {
485
- pm_runtime_put(fmd->pmf);
511
+ ret = pm_runtime_resume_and_get(fmd->pmf);
512
+ if (ret < 0)
486513 return ret;
487
- }
488514
489515 fmd->num_sensors = 0;
490516
....@@ -492,20 +518,19 @@
492518 for_each_available_child_of_node(parent, node) {
493519 struct device_node *port;
494520
495
- if (of_node_cmp(node->name, "csis"))
521
+ if (!of_node_name_eq(node, "csis"))
496522 continue;
497523 /* The csis node can have only port subnode. */
498524 port = of_get_next_child(node, NULL);
499525 if (!port)
500526 continue;
501527
502
- ret = fimc_md_parse_port_node(fmd, port, index);
528
+ ret = fimc_md_parse_port_node(fmd, port);
503529 of_node_put(port);
504530 if (ret < 0) {
505531 of_node_put(node);
506
- goto rpm_put;
532
+ goto cleanup;
507533 }
508
- index++;
509534 }
510535
511536 /* Attach sensors listed in the parallel-ports node */
....@@ -514,14 +539,21 @@
514539 goto rpm_put;
515540
516541 for_each_child_of_node(ports, node) {
517
- ret = fimc_md_parse_port_node(fmd, node, index);
542
+ ret = fimc_md_parse_port_node(fmd, node);
518543 if (ret < 0) {
519544 of_node_put(node);
520
- break;
545
+ goto cleanup;
521546 }
522
- index++;
523547 }
548
+ of_node_put(ports);
549
+
524550 rpm_put:
551
+ pm_runtime_put(fmd->pmf);
552
+ return 0;
553
+
554
+cleanup:
555
+ of_node_put(ports);
556
+ v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
525557 pm_runtime_put(fmd->pmf);
526558 return ret;
527559 }
....@@ -713,13 +745,13 @@
713745 continue;
714746
715747 /* If driver of any entity isn't ready try all again later. */
716
- if (!strcmp(node->name, CSIS_OF_NODE_NAME))
748
+ if (of_node_name_eq(node, CSIS_OF_NODE_NAME))
717749 plat_entity = IDX_CSIS;
718
- else if (!strcmp(node->name, FIMC_IS_OF_NODE_NAME))
750
+ else if (of_node_name_eq(node, FIMC_IS_OF_NODE_NAME))
719751 plat_entity = IDX_IS_ISP;
720
- else if (!strcmp(node->name, FIMC_LITE_OF_NODE_NAME))
752
+ else if (of_node_name_eq(node, FIMC_LITE_OF_NODE_NAME))
721753 plat_entity = IDX_FLITE;
722
- else if (!strcmp(node->name, FIMC_OF_NODE_NAME) &&
754
+ else if (of_node_name_eq(node, FIMC_OF_NODE_NAME) &&
723755 !of_property_read_bool(node, "samsung,lcd-wb"))
724756 plat_entity = IDX_FIMC;
725757
....@@ -1208,9 +1240,9 @@
12081240 struct fimc_md *fmd = dev_get_drvdata(dev);
12091241
12101242 if (fmd->user_subdev_api)
1211
- return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
1243
+ return strscpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
12121244
1213
- return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
1245
+ return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
12141246 }
12151247
12161248 static ssize_t fimc_md_sysfs_store(struct device *dev,
....@@ -1245,36 +1277,14 @@
12451277 static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
12461278 fimc_md_sysfs_show, fimc_md_sysfs_store);
12471279
1248
-static int fimc_md_get_pinctrl(struct fimc_md *fmd)
1249
-{
1250
- struct device *dev = &fmd->pdev->dev;
1251
- struct fimc_pinctrl *pctl = &fmd->pinctl;
1252
-
1253
- pctl->pinctrl = devm_pinctrl_get(dev);
1254
- if (IS_ERR(pctl->pinctrl))
1255
- return PTR_ERR(pctl->pinctrl);
1256
-
1257
- pctl->state_default = pinctrl_lookup_state(pctl->pinctrl,
1258
- PINCTRL_STATE_DEFAULT);
1259
- if (IS_ERR(pctl->state_default))
1260
- return PTR_ERR(pctl->state_default);
1261
-
1262
- /* PINCTRL_STATE_IDLE is optional */
1263
- pctl->state_idle = pinctrl_lookup_state(pctl->pinctrl,
1264
- PINCTRL_STATE_IDLE);
1265
- return 0;
1266
-}
1267
-
12681280 static int cam_clk_prepare(struct clk_hw *hw)
12691281 {
12701282 struct cam_clk *camclk = to_cam_clk(hw);
1271
- int ret;
12721283
12731284 if (camclk->fmd->pmf == NULL)
12741285 return -ENODEV;
12751286
1276
- ret = pm_runtime_get_sync(camclk->fmd->pmf);
1277
- return ret < 0 ? ret : 0;
1287
+ return pm_runtime_resume_and_get(camclk->fmd->pmf);
12781288 }
12791289
12801290 static void cam_clk_unprepare(struct clk_hw *hw)
....@@ -1420,6 +1430,7 @@
14201430 {
14211431 struct device *dev = &pdev->dev;
14221432 struct v4l2_device *v4l2_dev;
1433
+ struct pinctrl *pinctrl;
14231434 struct fimc_md *fmd;
14241435 int ret;
14251436
....@@ -1431,7 +1442,7 @@
14311442 INIT_LIST_HEAD(&fmd->pipelines);
14321443 fmd->pdev = pdev;
14331444
1434
- strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
1445
+ strscpy(fmd->media_dev.model, "Samsung S5P FIMC",
14351446 sizeof(fmd->media_dev.model));
14361447 fmd->media_dev.ops = &fimc_md_ops;
14371448 fmd->media_dev.dev = dev;
....@@ -1439,7 +1450,7 @@
14391450 v4l2_dev = &fmd->v4l2_dev;
14401451 v4l2_dev->mdev = &fmd->media_dev;
14411452 v4l2_dev->notify = fimc_sensor_notify;
1442
- strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
1453
+ strscpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
14431454
14441455 fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
14451456 fmd->user_subdev_api = true;
....@@ -1449,21 +1460,24 @@
14491460 ret = v4l2_device_register(dev, &fmd->v4l2_dev);
14501461 if (ret < 0) {
14511462 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
1452
- return ret;
1463
+ goto err_md;
14531464 }
14541465
14551466 ret = fimc_md_get_clocks(fmd);
14561467 if (ret)
1457
- goto err_md;
1468
+ goto err_v4l2dev;
14581469
1459
- ret = fimc_md_get_pinctrl(fmd);
1460
- if (ret < 0) {
1470
+ pinctrl = devm_pinctrl_get(dev);
1471
+ if (IS_ERR(pinctrl)) {
1472
+ ret = PTR_ERR(pinctrl);
14611473 if (ret != EPROBE_DEFER)
14621474 dev_err(dev, "Failed to get pinctrl: %d\n", ret);
14631475 goto err_clk;
14641476 }
14651477
14661478 platform_set_drvdata(pdev, fmd);
1479
+
1480
+ v4l2_async_notifier_init(&fmd->subdev_notifier);
14671481
14681482 ret = fimc_md_register_platform_entities(fmd, dev->of_node);
14691483 if (ret)
....@@ -1475,7 +1489,7 @@
14751489
14761490 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
14771491 if (ret)
1478
- goto err_m_ent;
1492
+ goto err_cleanup;
14791493 /*
14801494 * FIMC platform devices need to be registered before the sclk_cam
14811495 * clocks provider, as one of these devices needs to be activated
....@@ -1488,8 +1502,6 @@
14881502 }
14891503
14901504 if (fmd->num_sensors > 0) {
1491
- fmd->subdev_notifier.subdevs = fmd->async_subdevs;
1492
- fmd->subdev_notifier.num_subdevs = fmd->num_sensors;
14931505 fmd->subdev_notifier.ops = &subdev_notifier_ops;
14941506 fmd->num_sensors = 0;
14951507
....@@ -1505,13 +1517,16 @@
15051517 fimc_md_unregister_clk_provider(fmd);
15061518 err_attr:
15071519 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1508
-err_clk:
1509
- fimc_md_put_clocks(fmd);
1520
+err_cleanup:
1521
+ v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
15101522 err_m_ent:
15111523 fimc_md_unregister_entities(fmd);
1524
+err_clk:
1525
+ fimc_md_put_clocks(fmd);
1526
+err_v4l2dev:
1527
+ v4l2_device_unregister(&fmd->v4l2_dev);
15121528 err_md:
15131529 media_device_cleanup(&fmd->media_dev);
1514
- v4l2_device_unregister(&fmd->v4l2_dev);
15151530 return ret;
15161531 }
15171532
....@@ -1524,6 +1539,7 @@
15241539
15251540 fimc_md_unregister_clk_provider(fmd);
15261541 v4l2_async_notifier_unregister(&fmd->subdev_notifier);
1542
+ v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
15271543
15281544 v4l2_device_unregister(&fmd->v4l2_dev);
15291545 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);