4 * Qualcomm MSM Camera Subsystem - Core
6 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
7 * Copyright (C) 2015-2017 Linaro Ltd.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 and
11 * only version 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 #include <linux/clk.h>
19 #include <linux/media-bus-format.h>
20 #include <linux/media.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
24 #include <linux/of_graph.h>
25 #include <linux/slab.h>
26 #include <linux/videodev2.h>
28 #include <media/media-device.h>
29 #include <media/v4l2-async.h>
30 #include <media/v4l2-device.h>
31 #include <media/v4l2-mc.h>
32 #include <media/v4l2-fwnode.h>
36 #define CAMSS_CLOCK_MARGIN_NUMERATOR 105
37 #define CAMSS_CLOCK_MARGIN_DENOMINATOR 100
39 static const struct resources csiphy_res
[] = {
42 .regulator
= { NULL
},
43 .clock
= { "camss_top_ahb", "ispif_ahb",
44 "camss_ahb", "csiphy0_timer" },
45 .clock_rate
= { { 0 },
48 { 100000000, 200000000 } },
49 .reg
= { "csiphy0", "csiphy0_clk_mux" },
50 .interrupt
= { "csiphy0" }
55 .regulator
= { NULL
},
56 .clock
= { "camss_top_ahb", "ispif_ahb",
57 "camss_ahb", "csiphy1_timer" },
58 .clock_rate
= { { 0 },
61 { 100000000, 200000000 } },
62 .reg
= { "csiphy1", "csiphy1_clk_mux" },
63 .interrupt
= { "csiphy1" }
67 static const struct resources csid_res
[] = {
70 .regulator
= { "vdda" },
71 .clock
= { "camss_top_ahb", "ispif_ahb",
72 "csi0_ahb", "camss_ahb",
73 "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" },
74 .clock_rate
= { { 0 },
78 { 100000000, 200000000 },
83 .interrupt
= { "csid0" }
88 .regulator
= { "vdda" },
89 .clock
= { "camss_top_ahb", "ispif_ahb",
90 "csi1_ahb", "camss_ahb",
91 "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" },
92 .clock_rate
= { { 0 },
96 { 100000000, 200000000 },
101 .interrupt
= { "csid1" }
105 static const struct resources_ispif ispif_res
= {
107 .clock
= { "camss_top_ahb", "camss_ahb", "ispif_ahb",
108 "csi0", "csi0_pix", "csi0_rdi",
109 "csi1", "csi1_pix", "csi1_rdi" },
110 .clock_for_reset
= { "camss_vfe_vfe", "camss_csi_vfe" },
111 .reg
= { "ispif", "csi_clk_mux" },
116 static const struct resources vfe_res
= {
118 .regulator
= { NULL
},
119 .clock
= { "camss_top_ahb", "camss_vfe_vfe", "camss_csi_vfe",
120 "iface", "bus", "camss_ahb" },
121 .clock_rate
= { { 0 },
122 { 50000000, 80000000, 100000000, 160000000,
123 177780000, 200000000, 266670000, 320000000,
124 400000000, 465000000 },
133 .interrupt
= { "vfe0" }
137 * camss_add_clock_margin - Add margin to clock frequency rate
138 * @rate: Clock frequency rate
140 * When making calculations with physical clock frequency values
141 * some safety margin must be added. Add it.
143 inline void camss_add_clock_margin(u64
*rate
)
145 *rate
*= CAMSS_CLOCK_MARGIN_NUMERATOR
;
146 *rate
= div_u64(*rate
, CAMSS_CLOCK_MARGIN_DENOMINATOR
);
150 * camss_enable_clocks - Enable multiple clocks
151 * @nclocks: Number of clocks in clock array
152 * @clock: Clock array
155 * Return 0 on success or a negative error code otherwise
157 int camss_enable_clocks(int nclocks
, struct camss_clock
*clock
,
163 for (i
= 0; i
< nclocks
; i
++) {
164 ret
= clk_prepare_enable(clock
[i
].clk
);
166 dev_err(dev
, "clock enable failed: %d\n", ret
);
174 for (i
--; i
>= 0; i
--)
175 clk_disable_unprepare(clock
[i
].clk
);
181 * camss_disable_clocks - Disable multiple clocks
182 * @nclocks: Number of clocks in clock array
183 * @clock: Clock array
185 void camss_disable_clocks(int nclocks
, struct camss_clock
*clock
)
189 for (i
= nclocks
- 1; i
>= 0; i
--)
190 clk_disable_unprepare(clock
[i
].clk
);
194 * camss_find_sensor - Find a linked media entity which represents a sensor
195 * @entity: Media entity to start searching from
197 * Return a pointer to sensor media entity or NULL if not found
199 static struct media_entity
*camss_find_sensor(struct media_entity
*entity
)
201 struct media_pad
*pad
;
204 pad
= &entity
->pads
[0];
205 if (!(pad
->flags
& MEDIA_PAD_FL_SINK
))
208 pad
= media_entity_remote_pad(pad
);
209 if (!pad
|| !is_media_entity_v4l2_subdev(pad
->entity
))
212 entity
= pad
->entity
;
214 if (entity
->function
== MEDIA_ENT_F_CAM_SENSOR
)
220 * camss_get_pixel_clock - Get pixel clock rate from sensor
221 * @entity: Media entity in the current pipeline
222 * @pixel_clock: Received pixel clock value
224 * Return 0 on success or a negative error code otherwise
226 int camss_get_pixel_clock(struct media_entity
*entity
, u32
*pixel_clock
)
228 struct media_entity
*sensor
;
229 struct v4l2_subdev
*subdev
;
230 struct v4l2_ctrl
*ctrl
;
232 sensor
= camss_find_sensor(entity
);
236 subdev
= media_entity_to_v4l2_subdev(sensor
);
238 ctrl
= v4l2_ctrl_find(subdev
->ctrl_handler
, V4L2_CID_PIXEL_RATE
);
243 *pixel_clock
= v4l2_ctrl_g_ctrl_int64(ctrl
);
249 * camss_of_parse_endpoint_node - Parse port endpoint node
251 * @node: Device node to be parsed
252 * @csd: Parsed data from port endpoint node
254 * Return 0 on success or a negative error code on failure
256 static int camss_of_parse_endpoint_node(struct device
*dev
,
257 struct device_node
*node
,
258 struct camss_async_subdev
*csd
)
260 struct csiphy_lanes_cfg
*lncfg
= &csd
->interface
.csi2
.lane_cfg
;
261 struct v4l2_fwnode_bus_mipi_csi2
*mipi_csi2
;
262 struct v4l2_fwnode_endpoint vep
= { { 0 } };
265 v4l2_fwnode_endpoint_parse(of_fwnode_handle(node
), &vep
);
267 csd
->interface
.csiphy_id
= vep
.base
.port
;
269 mipi_csi2
= &vep
.bus
.mipi_csi2
;
270 lncfg
->clk
.pos
= mipi_csi2
->clock_lane
;
271 lncfg
->clk
.pol
= mipi_csi2
->lane_polarities
[0];
272 lncfg
->num_data
= mipi_csi2
->num_data_lanes
;
274 lncfg
->data
= devm_kzalloc(dev
, lncfg
->num_data
* sizeof(*lncfg
->data
),
279 for (i
= 0; i
< lncfg
->num_data
; i
++) {
280 lncfg
->data
[i
].pos
= mipi_csi2
->data_lanes
[i
];
281 lncfg
->data
[i
].pol
= mipi_csi2
->lane_polarities
[i
+ 1];
288 * camss_of_parse_ports - Parse ports node
290 * @notifier: v4l2_device notifier data
292 * Return number of "port" nodes found in "ports" node
294 static int camss_of_parse_ports(struct device
*dev
,
295 struct v4l2_async_notifier
*notifier
)
297 struct device_node
*node
= NULL
;
298 struct device_node
*remote
= NULL
;
299 unsigned int size
, i
;
302 while ((node
= of_graph_get_next_endpoint(dev
->of_node
, node
)))
303 if (of_device_is_available(node
))
304 notifier
->num_subdevs
++;
306 size
= sizeof(*notifier
->subdevs
) * notifier
->num_subdevs
;
307 notifier
->subdevs
= devm_kzalloc(dev
, size
, GFP_KERNEL
);
308 if (!notifier
->subdevs
) {
309 dev_err(dev
, "Failed to allocate memory\n");
314 while ((node
= of_graph_get_next_endpoint(dev
->of_node
, node
))) {
315 struct camss_async_subdev
*csd
;
317 if (!of_device_is_available(node
))
320 csd
= devm_kzalloc(dev
, sizeof(*csd
), GFP_KERNEL
);
323 dev_err(dev
, "Failed to allocate memory\n");
327 notifier
->subdevs
[i
++] = &csd
->asd
;
329 ret
= camss_of_parse_endpoint_node(dev
, node
, csd
);
335 remote
= of_graph_get_remote_port_parent(node
);
339 dev_err(dev
, "Cannot get remote parent\n");
343 csd
->asd
.match_type
= V4L2_ASYNC_MATCH_FWNODE
;
344 csd
->asd
.match
.fwnode
= of_fwnode_handle(remote
);
347 return notifier
->num_subdevs
;
351 * camss_init_subdevices - Initialize subdev structures and resources
352 * @camss: CAMSS device
354 * Return 0 on success or a negative error code on failure
356 static int camss_init_subdevices(struct camss
*camss
)
361 for (i
= 0; i
< ARRAY_SIZE(camss
->csiphy
); i
++) {
362 ret
= msm_csiphy_subdev_init(&camss
->csiphy
[i
],
366 "Failed to init csiphy%d sub-device: %d\n",
372 for (i
= 0; i
< ARRAY_SIZE(camss
->csid
); i
++) {
373 ret
= msm_csid_subdev_init(&camss
->csid
[i
],
377 "Failed to init csid%d sub-device: %d\n",
383 ret
= msm_ispif_subdev_init(&camss
->ispif
, &ispif_res
);
385 dev_err(camss
->dev
, "Failed to init ispif sub-device: %d\n",
390 ret
= msm_vfe_subdev_init(&camss
->vfe
, &vfe_res
);
392 dev_err(camss
->dev
, "Fail to init vfe sub-device: %d\n", ret
);
400 * camss_register_entities - Register subdev nodes and create links
401 * @camss: CAMSS device
403 * Return 0 on success or a negative error code on failure
405 static int camss_register_entities(struct camss
*camss
)
410 for (i
= 0; i
< ARRAY_SIZE(camss
->csiphy
); i
++) {
411 ret
= msm_csiphy_register_entity(&camss
->csiphy
[i
],
415 "Failed to register csiphy%d entity: %d\n",
421 for (i
= 0; i
< ARRAY_SIZE(camss
->csid
); i
++) {
422 ret
= msm_csid_register_entity(&camss
->csid
[i
],
426 "Failed to register csid%d entity: %d\n",
432 ret
= msm_ispif_register_entities(&camss
->ispif
, &camss
->v4l2_dev
);
434 dev_err(camss
->dev
, "Failed to register ispif entities: %d\n",
439 ret
= msm_vfe_register_entities(&camss
->vfe
, &camss
->v4l2_dev
);
441 dev_err(camss
->dev
, "Failed to register vfe entities: %d\n",
446 for (i
= 0; i
< ARRAY_SIZE(camss
->csiphy
); i
++) {
447 for (j
= 0; j
< ARRAY_SIZE(camss
->csid
); j
++) {
448 ret
= media_create_pad_link(
449 &camss
->csiphy
[i
].subdev
.entity
,
451 &camss
->csid
[j
].subdev
.entity
,
456 "Failed to link %s->%s entities: %d\n",
457 camss
->csiphy
[i
].subdev
.entity
.name
,
458 camss
->csid
[j
].subdev
.entity
.name
,
465 for (i
= 0; i
< ARRAY_SIZE(camss
->csid
); i
++) {
466 for (j
= 0; j
< ARRAY_SIZE(camss
->ispif
.line
); j
++) {
467 ret
= media_create_pad_link(
468 &camss
->csid
[i
].subdev
.entity
,
470 &camss
->ispif
.line
[j
].subdev
.entity
,
475 "Failed to link %s->%s entities: %d\n",
476 camss
->csid
[i
].subdev
.entity
.name
,
477 camss
->ispif
.line
[j
].subdev
.entity
.name
,
484 for (i
= 0; i
< ARRAY_SIZE(camss
->ispif
.line
); i
++) {
485 for (j
= 0; j
< ARRAY_SIZE(camss
->vfe
.line
); j
++) {
486 ret
= media_create_pad_link(
487 &camss
->ispif
.line
[i
].subdev
.entity
,
489 &camss
->vfe
.line
[j
].subdev
.entity
,
494 "Failed to link %s->%s entities: %d\n",
495 camss
->ispif
.line
[i
].subdev
.entity
.name
,
496 camss
->vfe
.line
[j
].subdev
.entity
.name
,
506 msm_vfe_unregister_entities(&camss
->vfe
);
508 msm_ispif_unregister_entities(&camss
->ispif
);
511 i
= ARRAY_SIZE(camss
->csid
);
513 for (i
--; i
>= 0; i
--)
514 msm_csid_unregister_entity(&camss
->csid
[i
]);
516 i
= ARRAY_SIZE(camss
->csiphy
);
518 for (i
--; i
>= 0; i
--)
519 msm_csiphy_unregister_entity(&camss
->csiphy
[i
]);
525 * camss_unregister_entities - Unregister subdev nodes
526 * @camss: CAMSS device
528 * Return 0 on success or a negative error code on failure
530 static void camss_unregister_entities(struct camss
*camss
)
534 for (i
= 0; i
< ARRAY_SIZE(camss
->csiphy
); i
++)
535 msm_csiphy_unregister_entity(&camss
->csiphy
[i
]);
537 for (i
= 0; i
< ARRAY_SIZE(camss
->csid
); i
++)
538 msm_csid_unregister_entity(&camss
->csid
[i
]);
540 msm_ispif_unregister_entities(&camss
->ispif
);
541 msm_vfe_unregister_entities(&camss
->vfe
);
544 static int camss_subdev_notifier_bound(struct v4l2_async_notifier
*async
,
545 struct v4l2_subdev
*subdev
,
546 struct v4l2_async_subdev
*asd
)
548 struct camss
*camss
= container_of(async
, struct camss
, notifier
);
549 struct camss_async_subdev
*csd
=
550 container_of(asd
, struct camss_async_subdev
, asd
);
551 u8 id
= csd
->interface
.csiphy_id
;
552 struct csiphy_device
*csiphy
= &camss
->csiphy
[id
];
554 csiphy
->cfg
.csi2
= &csd
->interface
.csi2
;
555 subdev
->host_priv
= csiphy
;
560 static int camss_subdev_notifier_complete(struct v4l2_async_notifier
*async
)
562 struct camss
*camss
= container_of(async
, struct camss
, notifier
);
563 struct v4l2_device
*v4l2_dev
= &camss
->v4l2_dev
;
564 struct v4l2_subdev
*sd
;
567 list_for_each_entry(sd
, &v4l2_dev
->subdevs
, list
) {
569 struct media_entity
*sensor
= &sd
->entity
;
570 struct csiphy_device
*csiphy
=
571 (struct csiphy_device
*) sd
->host_priv
;
572 struct media_entity
*input
= &csiphy
->subdev
.entity
;
575 for (i
= 0; i
< sensor
->num_pads
; i
++) {
576 if (sensor
->pads
[i
].flags
& MEDIA_PAD_FL_SOURCE
)
579 if (i
== sensor
->num_pads
) {
581 "No source pad in external entity\n");
585 ret
= media_create_pad_link(sensor
, i
,
586 input
, MSM_CSIPHY_PAD_SINK
,
587 MEDIA_LNK_FL_IMMUTABLE
| MEDIA_LNK_FL_ENABLED
);
590 "Failed to link %s->%s entities: %d\n",
591 sensor
->name
, input
->name
, ret
);
597 ret
= v4l2_device_register_subdev_nodes(&camss
->v4l2_dev
);
601 return media_device_register(&camss
->media_dev
);
604 static const struct v4l2_async_notifier_operations camss_subdev_notifier_ops
= {
605 .bound
= camss_subdev_notifier_bound
,
606 .complete
= camss_subdev_notifier_complete
,
609 static const struct media_device_ops camss_media_ops
= {
610 .link_notify
= v4l2_pipeline_link_notify
,
614 * camss_probe - Probe CAMSS platform device
615 * @pdev: Pointer to CAMSS platform device
617 * Return 0 on success or a negative error code on failure
619 static int camss_probe(struct platform_device
*pdev
)
621 struct device
*dev
= &pdev
->dev
;
625 camss
= kzalloc(sizeof(*camss
), GFP_KERNEL
);
629 atomic_set(&camss
->ref_count
, 0);
631 platform_set_drvdata(pdev
, camss
);
633 ret
= camss_of_parse_ports(dev
, &camss
->notifier
);
637 ret
= camss_init_subdevices(camss
);
641 ret
= dma_set_mask_and_coherent(dev
, 0xffffffff);
645 camss
->media_dev
.dev
= camss
->dev
;
646 strlcpy(camss
->media_dev
.model
, "Qualcomm Camera Subsystem",
647 sizeof(camss
->media_dev
.model
));
648 camss
->media_dev
.ops
= &camss_media_ops
;
649 media_device_init(&camss
->media_dev
);
651 camss
->v4l2_dev
.mdev
= &camss
->media_dev
;
652 ret
= v4l2_device_register(camss
->dev
, &camss
->v4l2_dev
);
654 dev_err(dev
, "Failed to register V4L2 device: %d\n", ret
);
658 ret
= camss_register_entities(camss
);
660 goto err_register_entities
;
662 if (camss
->notifier
.num_subdevs
) {
663 camss
->notifier
.ops
= &camss_subdev_notifier_ops
;
665 ret
= v4l2_async_notifier_register(&camss
->v4l2_dev
,
669 "Failed to register async subdev nodes: %d\n",
671 goto err_register_subdevs
;
674 ret
= v4l2_device_register_subdev_nodes(&camss
->v4l2_dev
);
676 dev_err(dev
, "Failed to register subdev nodes: %d\n",
678 goto err_register_subdevs
;
681 ret
= media_device_register(&camss
->media_dev
);
683 dev_err(dev
, "Failed to register media device: %d\n",
685 goto err_register_subdevs
;
691 err_register_subdevs
:
692 camss_unregister_entities(camss
);
693 err_register_entities
:
694 v4l2_device_unregister(&camss
->v4l2_dev
);
699 void camss_delete(struct camss
*camss
)
701 v4l2_device_unregister(&camss
->v4l2_dev
);
702 media_device_unregister(&camss
->media_dev
);
703 media_device_cleanup(&camss
->media_dev
);
709 * camss_remove - Remove CAMSS platform device
710 * @pdev: Pointer to CAMSS platform device
714 static int camss_remove(struct platform_device
*pdev
)
716 struct camss
*camss
= platform_get_drvdata(pdev
);
718 msm_vfe_stop_streaming(&camss
->vfe
);
720 v4l2_async_notifier_unregister(&camss
->notifier
);
721 camss_unregister_entities(camss
);
723 if (atomic_read(&camss
->ref_count
) == 0)
729 static const struct of_device_id camss_dt_match
[] = {
730 { .compatible
= "qcom,msm8916-camss" },
734 MODULE_DEVICE_TABLE(of
, camss_dt_match
);
736 static struct platform_driver qcom_camss_driver
= {
737 .probe
= camss_probe
,
738 .remove
= camss_remove
,
740 .name
= "qcom-camss",
741 .of_match_table
= camss_dt_match
,
745 module_platform_driver(qcom_camss_driver
);
747 MODULE_ALIAS("platform:qcom-camss");
748 MODULE_DESCRIPTION("Qualcomm Camera Subsystem driver");
749 MODULE_AUTHOR("Todor Tomov <todor.tomov@linaro.org>");
750 MODULE_LICENSE("GPL v2");