1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 StarFive Technology Co., Ltd.
5 #include <linux/completion.h>
6 #include <linux/delay.h>
7 #include <linux/dmaengine.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/of_reserved_mem.h>
15 #include <linux/of_graph.h>
16 #include <linux/of_address.h>
17 #include <linux/pinctrl/consumer.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm_runtime.h>
21 #include <linux/dma-mapping.h>
22 #include <linux/uaccess.h>
24 #include <linux/videodev2.h>
26 #include <media/media-device.h>
27 #include <media/v4l2-async.h>
28 #include <media/v4l2-device.h>
29 #include <media/v4l2-mc.h>
30 #include <media/v4l2-fwnode.h>
31 #include <linux/debugfs.h>
36 unsigned int stdbg_level = ST_DEBUG;
37 unsigned int stdbg_mask = 0x7F;
39 unsigned int stdbg_level = ST_ERR;
40 unsigned int stdbg_mask = 0x7F;
43 static const struct reg_name mem_reg_name[] = {
44 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
58 static struct clk_bulk_data stfcamss_clocks[] = {
59 { .id = "clk_ispcore_2x" },
60 { .id = "clk_isp_axi" },
63 static struct reset_control_bulk_data stfcamss_resets[] = {
64 { .id = "rst_isp_top_n" },
65 { .id = "rst_isp_top_axi" },
66 { .id = "rst_wrapper_p" },
67 { .id = "rst_wrapper_c" },
69 { .id = "rst_sys_clk" },
70 { .id = "rst_axird" },
71 { .id = "rst_axiwr" },
72 { .id = "rst_pixel_clk_if0" },
73 { .id = "rst_pixel_clk_if1" },
74 { .id = "rst_pixel_clk_if2" },
75 { .id = "rst_pixel_clk_if3" },
78 int stfcamss_get_mem_res(struct platform_device *pdev, struct stf_vin_dev *vin)
80 struct device *dev = &pdev->dev;
86 for (i = 0; i < ARRAY_SIZE(mem_reg_name); i++) {
87 name = (char *)(&mem_reg_name[i]);
88 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
92 if (!strcmp(name, "mipi0")) {
93 vin->mipi0_base = devm_ioremap_resource(dev, res);
94 if (IS_ERR(vin->mipi0_base))
95 return PTR_ERR(vin->mipi0_base);
96 } else if (!strcmp(name, "vclk")) {
97 vin->clkgen_base = ioremap(res->start, resource_size(res));
98 if (!vin->clkgen_base)
100 } else if (!strcmp(name, "vrst")) {
101 vin->rstgen_base = devm_ioremap_resource(dev, res);
102 if (IS_ERR(vin->rstgen_base))
103 return PTR_ERR(vin->rstgen_base);
104 } else if (!strcmp(name, "mipi1")) {
105 vin->mipi1_base = devm_ioremap_resource(dev, res);
106 if (IS_ERR(vin->mipi1_base))
107 return PTR_ERR(vin->mipi1_base);
108 } else if (!strcmp(name, "sctrl")) {
109 vin->sysctrl_base = devm_ioremap_resource(dev, res);
110 if (IS_ERR(vin->sysctrl_base))
111 return PTR_ERR(vin->sysctrl_base);
112 } else if (!strcmp(name, "isp0")) {
113 vin->isp_isp0_base = devm_ioremap_resource(dev, res);
114 if (IS_ERR(vin->isp_isp0_base))
115 return PTR_ERR(vin->isp_isp0_base);
116 } else if (!strcmp(name, "isp1")) {
117 vin->isp_isp1_base = devm_ioremap_resource(dev, res);
118 if (IS_ERR(vin->isp_isp1_base))
119 return PTR_ERR(vin->isp_isp1_base);
120 } else if (!strcmp(name, "trst")) {
121 vin->vin_top_rstgen_base = devm_ioremap_resource(dev, res);
122 if (IS_ERR(vin->vin_top_rstgen_base))
123 return PTR_ERR(vin->vin_top_rstgen_base);
124 } else if (!strcmp(name, "pmu")) {
125 vin->pmu_test = ioremap(res->start, resource_size(res));
128 } else if (!strcmp(name, "syscrg")) {
129 vin->sys_crg = ioremap(res->start, resource_size(res));
133 st_err(ST_CAMSS, "Could not match resource name\n");
140 int vin_parse_dt(struct device *dev, struct stf_vin_dev *vin)
143 struct device_node *np = dev->of_node;
151 struct media_entity *stfcamss_find_sensor(struct media_entity *entity)
153 struct media_pad *pad;
156 pad = &entity->pads[0];
157 if (!(pad->flags & MEDIA_PAD_FL_SINK))
160 pad = media_entity_remote_pad(pad);
161 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
164 entity = pad->entity;
166 if (entity->function == MEDIA_ENT_F_CAM_SENSOR)
171 static int stfcamss_of_parse_endpoint_node(struct device *dev,
172 struct device_node *node,
173 struct stfcamss_async_subdev *csd)
175 struct v4l2_fwnode_endpoint vep = { { 0 } };
176 struct v4l2_fwnode_bus_parallel *parallel_bus = &vep.bus.parallel;
177 struct v4l2_fwnode_bus_mipi_csi2 *csi2_bus = &vep.bus.mipi_csi2;
178 struct dvp_cfg *dvp = &csd->interface.dvp;
179 struct csi2phy_cfg *csiphy = &csd->interface.csiphy;
182 v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
183 st_debug(ST_CAMSS, "%s: vep.base.port = 0x%x, id = 0x%x\n",
184 __func__, vep.base.port, vep.base.id);
186 csd->port = vep.base.port;
188 case CSI2RX0_PORT_NUMBER:
189 case CSI2RX1_PORT_NUMBER:
191 case DVP_SENSOR_PORT_NUMBER:
192 st_debug(ST_CAMSS, "%s, flags = 0x%x\n", __func__,
193 parallel_bus->flags);
194 dvp->flags = parallel_bus->flags;
195 dvp->bus_width = parallel_bus->bus_width;
196 dvp->data_shift = parallel_bus->data_shift;
198 case CSI2RX0_SENSOR_PORT_NUMBER:
199 case CSI2RX1_SENSOR_PORT_NUMBER:
200 st_debug(ST_CAMSS, "%s, CSI2 flags = 0x%x\n",
201 __func__, parallel_bus->flags);
202 csiphy->flags = csi2_bus->flags;
203 memcpy(csiphy->data_lanes,
204 csi2_bus->data_lanes, csi2_bus->num_data_lanes);
205 csiphy->clock_lane = csi2_bus->clock_lane;
206 csiphy->num_data_lanes = csi2_bus->num_data_lanes;
207 memcpy(csiphy->lane_polarities,
208 csi2_bus->lane_polarities,
209 csi2_bus->num_data_lanes + 1);
218 static int stfcamss_of_parse_ports(struct stfcamss *stfcamss)
220 struct device *dev = stfcamss->dev;
221 struct device_node *node = NULL;
222 struct device_node *remote = NULL;
223 int ret, num_subdevs = 0;
225 for_each_endpoint_of_node(dev->of_node, node) {
226 struct stfcamss_async_subdev *csd;
228 if (!of_device_is_available(node))
231 remote = of_graph_get_remote_port_parent(node);
233 st_err(ST_CAMSS, "Cannot get remote parent\n");
238 csd = v4l2_async_notifier_add_fwnode_subdev(
239 &stfcamss->notifier, of_fwnode_handle(remote),
240 struct stfcamss_async_subdev);
247 ret = stfcamss_of_parse_endpoint_node(dev, node, csd);
261 static int stfcamss_init_subdevices(struct stfcamss *stfcamss)
265 ret = stf_dvp_subdev_init(stfcamss);
268 "Failed to init stf_dvp sub-device: %d\n",
273 for (i = 0; i < stfcamss->csiphy_num; i++) {
274 ret = stf_csiphy_subdev_init(stfcamss, i);
277 "Failed to init stf_csiphy sub-device: %d\n",
283 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
284 for (i = 0; i < stfcamss->csi_num; i++) {
285 ret = stf_csi_subdev_init(stfcamss, i);
288 "Failed to init stf_csi sub-device: %d\n",
295 for (i = 0; i < stfcamss->isp_num; i++) {
296 ret = stf_isp_subdev_init(stfcamss, i);
299 "Failed to init stf_isp sub-device: %d\n",
305 ret = stf_vin_subdev_init(stfcamss);
308 "Failed to init stf_vin sub-device: %d\n",
315 static int stfcamss_register_subdevices(struct stfcamss *stfcamss)
318 struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
319 struct stf_dvp_dev *dvp_dev = stfcamss->dvp_dev;
320 struct stf_csiphy_dev *csiphy_dev = stfcamss->csiphy_dev;
321 struct stf_csi_dev *csi_dev = stfcamss->csi_dev;
322 struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
324 ret = stf_dvp_register(dvp_dev, &stfcamss->v4l2_dev);
327 "Failed to register stf dvp entity: %d\n",
332 for (i = 0; i < stfcamss->csiphy_num; i++) {
333 ret = stf_csiphy_register(&csiphy_dev[i],
334 &stfcamss->v4l2_dev);
337 "Failed to register stf csiphy%d entity: %d\n",
343 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
344 for (i = 0; i < stfcamss->csi_num; i++) {
345 ret = stf_csi_register(&csi_dev[i],
346 &stfcamss->v4l2_dev);
349 "Failed to register stf csi%d entity: %d\n",
356 for (i = 0; i < stfcamss->isp_num; i++) {
357 ret = stf_isp_register(&isp_dev[i],
358 &stfcamss->v4l2_dev);
361 "Failed to register stf isp%d entity: %d\n",
367 ret = stf_vin_register(vin_dev, &stfcamss->v4l2_dev);
370 "Failed to register vin entity: %d\n",
375 ret = media_create_pad_link(
376 &dvp_dev->subdev.entity,
378 &vin_dev->line[VIN_LINE_WR].subdev.entity,
383 "Failed to link %s->vin entities: %d\n",
384 dvp_dev->subdev.entity.name,
389 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
390 for (i = 0; i < stfcamss->csi_num; i++) {
391 ret = media_create_pad_link(
392 &csi_dev[i].subdev.entity,
394 &vin_dev->line[VIN_LINE_WR].subdev.entity,
399 "Failed to link %s->vin entities: %d\n",
400 csi_dev[i].subdev.entity.name,
406 for (j = 0; j < stfcamss->csi_num; j++) {
407 ret = media_create_pad_link(
408 &csiphy_dev[j].subdev.entity,
410 &csi_dev[j].subdev.entity,
415 "Failed to link %s->%s entities: %d\n",
416 csiphy_dev[j].subdev.entity.name,
417 csi_dev[j].subdev.entity.name,
423 for (i = 0; i < stfcamss->isp_num; i++) {
424 ret = media_create_pad_link(
425 &isp_dev[i].subdev.entity,
427 &vin_dev->line[i + VIN_LINE_ISP0].subdev.entity,
432 "Failed to link %s->%s entities: %d\n",
433 isp_dev[i].subdev.entity.name,
434 vin_dev->line[i + VIN_LINE_ISP0]
440 ret = media_create_pad_link(
441 &isp_dev[i].subdev.entity,
443 &vin_dev->line[i + VIN_LINE_ISP0_RAW].subdev.entity,
448 "Failed to link %s->%s entities: %d\n",
449 isp_dev[i].subdev.entity.name,
450 vin_dev->line[i + VIN_LINE_ISP0_RAW]
456 ret = media_create_pad_link(
457 &dvp_dev->subdev.entity,
459 &isp_dev[i].subdev.entity,
464 "Failed to link %s->%s entities: %d\n",
465 dvp_dev->subdev.entity.name,
466 isp_dev[i].subdev.entity.name,
470 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
471 for (j = 0; j < stfcamss->csi_num; j++) {
472 ret = media_create_pad_link(
473 &csi_dev[j].subdev.entity,
475 &isp_dev[i].subdev.entity,
480 "Failed to link %s->%s entities: %d\n",
481 csi_dev[j].subdev.entity.name,
482 isp_dev[i].subdev.entity.name,
493 stf_vin_unregister(stfcamss->vin_dev);
495 i = stfcamss->isp_num;
497 for (i--; i >= 0; i--)
498 stf_isp_unregister(&stfcamss->isp_dev[i]);
500 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
501 i = stfcamss->csi_num;
503 for (i--; i >= 0; i--)
504 stf_csi_unregister(&stfcamss->csi_dev[i]);
507 i = stfcamss->csiphy_num;
509 for (i--; i >= 0; i--)
510 stf_csiphy_unregister(&stfcamss->csiphy_dev[i]);
512 stf_dvp_unregister(stfcamss->dvp_dev);
517 static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss)
521 stf_dvp_unregister(stfcamss->dvp_dev);
523 i = stfcamss->csiphy_num;
524 for (i--; i >= 0; i--)
525 stf_csiphy_unregister(&stfcamss->csiphy_dev[i]);
527 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
528 i = stfcamss->csi_num;
529 for (i--; i >= 0; i--)
530 stf_csi_unregister(&stfcamss->csi_dev[i]);
533 i = stfcamss->isp_num;
534 for (i--; i >= 0; i--)
535 stf_isp_unregister(&stfcamss->isp_dev[i]);
537 stf_vin_unregister(stfcamss->vin_dev);
540 static int stfcamss_register_mediadevice_subdevnodes(
541 struct v4l2_async_notifier *async,
542 struct v4l2_subdev *sd)
544 struct stfcamss *stfcamss =
545 container_of(async, struct stfcamss, notifier);
546 struct v4l2_device *v4l2_dev = &stfcamss->v4l2_dev;
550 struct media_entity *sensor = &sd->entity;
551 struct media_entity *input = sd->host_priv;
554 for (i = 0; i < sensor->num_pads; i++) {
555 if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE)
558 if (i == sensor->num_pads) {
560 "No source pad in external entity\n");
564 ret = media_create_pad_link(sensor, i,
566 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
569 "Failed to link %s->%s entities: %d\n",
570 sensor->name, input->name, ret);
575 ret = v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
579 if (stfcamss->media_dev.devnode)
582 st_debug(ST_CAMSS, "stfcamss register media device\n");
583 return media_device_register(&stfcamss->media_dev);
586 static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
587 struct v4l2_subdev *subdev,
588 struct v4l2_async_subdev *asd)
590 struct stfcamss *stfcamss =
591 container_of(async, struct stfcamss, notifier);
592 struct stfcamss_async_subdev *csd =
593 container_of(asd, struct stfcamss_async_subdev, asd);
594 enum port_num port = csd->port;
595 struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
596 struct stf_dvp_dev *dvp_dev = stfcamss->dvp_dev;
597 struct stf_csiphy_dev *csiphy_dev = stfcamss->csiphy_dev;
598 struct stf_csi_dev *csi_dev = stfcamss->csi_dev;
599 struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
604 case CSI2RX0_PORT_NUMBER:
605 case CSI2RX1_PORT_NUMBER:
606 id = port - CSI2RX0_PORT_NUMBER;
607 isp_dev = &isp_dev[id];
608 subdev->host_priv = &isp_dev->subdev.entity;
610 case DVP_SENSOR_PORT_NUMBER:
611 dvp_dev->dvp = &csd->interface.dvp;
612 subdev->host_priv = &dvp_dev->subdev.entity;
614 case CSI2RX0_SENSOR_PORT_NUMBER:
615 case CSI2RX1_SENSOR_PORT_NUMBER:
616 id = port - CSI2RX0_SENSOR_PORT_NUMBER;
617 csiphy_dev = &csiphy_dev[id];
618 csiphy_dev->csiphy = &csd->interface.csiphy;
619 subdev->host_priv = &csiphy_dev->subdev.entity;
625 stfcamss_register_mediadevice_subdevnodes(async, subdev);
630 static int stfcamss_subdev_notifier_complete(
631 struct v4l2_async_notifier *async)
633 struct stfcamss *stfcamss =
634 container_of(async, struct stfcamss, notifier);
635 struct v4l2_device *v4l2_dev = &stfcamss->v4l2_dev;
636 struct v4l2_subdev *sd;
639 list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
641 struct media_entity *sensor = &sd->entity;
642 struct media_entity *input = sd->host_priv;
645 for (i = 0; i < sensor->num_pads; i++) {
646 if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE)
649 if (i == sensor->num_pads) {
651 "No source pad in external entity\n");
655 ret = media_create_pad_link(sensor, i,
657 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
660 "Failed to link %s->%s entities: %d\n",
661 sensor->name, input->name, ret);
667 ret = v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
671 return media_device_register(&stfcamss->media_dev);
674 static const struct v4l2_async_notifier_operations
675 stfcamss_subdev_notifier_ops = {
676 .bound = stfcamss_subdev_notifier_bound,
677 // .complete = stfcamss_subdev_notifier_complete,
680 static const struct media_device_ops stfcamss_media_ops = {
681 .link_notify = v4l2_pipeline_link_notify,
684 #ifdef CONFIG_DEBUG_FS
696 static enum module_id id_num = ISP0_MODULE;
698 void dump_clk_reg(void __iomem *reg_base)
702 st_info(ST_CAMSS, "DUMP Clk register:\n");
703 for (i = 0; i <= CLK_C_ISP1_CTRL; i += 4)
704 print_reg(ST_CAMSS, reg_base, i);
707 static ssize_t vin_debug_read(struct file *file, char __user *user_buf,
708 size_t count, loff_t *ppos)
712 struct device *dev = file->private_data;
714 void __iomem *reg_base;
715 struct stfcamss *stfcamss = dev_get_drvdata(dev);
716 struct stf_vin_dev *vin = stfcamss->vin;
717 struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
718 struct stf_isp_dev *isp0_dev = &stfcamss->isp_dev[0];
719 struct stf_isp_dev *isp1_dev = &stfcamss->isp_dev[1];
720 struct stf_csi_dev *csi0_dev = &stfcamss->csi_dev[0];
721 struct stf_csi_dev *csi1_dev = &stfcamss->csi_dev[1];
727 mutex_lock(&vin_dev->power_lock);
728 if (vin_dev->power_count > 0) {
729 reg_base = vin->sysctrl_base;
730 dump_vin_reg(reg_base);
732 mutex_unlock(&vin_dev->power_lock);
735 mutex_lock(&isp0_dev->stream_lock);
736 if (isp0_dev->stream_count > 0) {
737 reg_base = vin->isp_isp0_base;
738 dump_isp_reg(reg_base, 0);
740 mutex_unlock(&isp0_dev->stream_lock);
743 mutex_lock(&isp1_dev->stream_lock);
744 if (isp1_dev->stream_count > 0) {
745 reg_base = vin->isp_isp1_base;
746 dump_isp_reg(reg_base, 1);
748 mutex_unlock(&isp1_dev->stream_lock);
751 mutex_lock(&csi0_dev->stream_lock);
752 if (csi0_dev->stream_count > 0) {
753 reg_base = vin->mipi0_base;
754 dump_csi_reg(reg_base, 0);
756 mutex_unlock(&csi0_dev->stream_lock);
759 mutex_lock(&csi1_dev->stream_lock);
760 if (csi1_dev->stream_count > 0) {
761 reg_base = vin->mipi1_base;
762 dump_csi_reg(reg_base, 1);
764 mutex_unlock(&csi1_dev->stream_lock);
767 mutex_lock(&vin_dev->power_lock);
768 if (vin_dev->power_count > 0) {
769 reg_base = vin->clkgen_base;
770 dump_clk_reg(reg_base);
772 mutex_unlock(&vin_dev->power_lock);
781 static void set_reg_val(struct stfcamss *stfcamss, int id, u32 offset, u32 val)
783 struct stf_vin_dev *vin = stfcamss->vin;
784 struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
785 struct stf_isp_dev *isp0_dev = &stfcamss->isp_dev[0];
786 struct stf_isp_dev *isp1_dev = &stfcamss->isp_dev[1];
787 struct stf_csi_dev *csi0_dev = &stfcamss->csi_dev[0];
788 struct stf_csi_dev *csi1_dev = &stfcamss->csi_dev[1];
789 void __iomem *reg_base;
795 mutex_lock(&vin_dev->power_lock);
796 if (vin_dev->power_count > 0) {
797 reg_base = vin->sysctrl_base;
798 print_reg(ST_VIN, reg_base, offset);
799 reg_write(reg_base, offset, val);
800 print_reg(ST_VIN, reg_base, offset);
802 mutex_unlock(&vin_dev->power_lock);
805 mutex_lock(&isp0_dev->stream_lock);
806 if (isp0_dev->stream_count > 0) {
807 reg_base = vin->isp_isp0_base;
808 print_reg(ST_ISP, reg_base, offset);
809 reg_write(reg_base, offset, val);
810 print_reg(ST_ISP, reg_base, offset);
812 mutex_unlock(&isp0_dev->stream_lock);
815 mutex_lock(&isp1_dev->stream_lock);
816 if (isp1_dev->stream_count > 0) {
817 reg_base = vin->isp_isp1_base;
818 print_reg(ST_ISP, reg_base, offset);
819 reg_write(reg_base, offset, val);
820 print_reg(ST_ISP, reg_base, offset);
822 mutex_unlock(&isp1_dev->stream_lock);
825 mutex_lock(&csi0_dev->stream_lock);
826 if (csi0_dev->stream_count > 0) {
827 reg_base = vin->mipi0_base;
828 print_reg(ST_CSI, reg_base, offset);
829 reg_write(reg_base, offset, val);
830 print_reg(ST_CSI, reg_base, offset);
832 mutex_unlock(&csi0_dev->stream_lock);
835 mutex_lock(&csi1_dev->stream_lock);
836 if (csi1_dev->stream_count > 0) {
837 reg_base = vin->mipi1_base;
838 print_reg(ST_CSI, reg_base, offset);
839 reg_write(reg_base, offset, val);
840 print_reg(ST_CSI, reg_base, offset);
842 mutex_unlock(&csi1_dev->stream_lock);
845 mutex_lock(&vin_dev->power_lock);
846 if (vin_dev->power_count > 0) {
847 reg_base = vin->clkgen_base;
848 print_reg(ST_CAMSS, reg_base, offset);
849 reg_write(reg_base, offset, val);
850 print_reg(ST_CAMSS, reg_base, offset);
852 mutex_unlock(&vin_dev->power_lock);
860 static u32 atoi(const char *s)
866 if ((*s == '0') && (*(s+1) == 'x')) {
882 else if (islower(ch))
896 static ssize_t vin_debug_write(struct file *file, const char __user *user_buf,
897 size_t count, loff_t *ppos)
899 struct device *dev = file->private_data;
900 struct stfcamss *stfcamss = dev_get_drvdata(dev);
901 struct stf_vin_dev *vin = stfcamss->vin;
905 static const char *delims = " \t\r";
909 buf = memdup_user_nul(user_buf, min_t(size_t, PAGE_SIZE, count));
913 st_debug(ST_CAMSS, "dup buf: %s, len: %d, count: %d\n", p, strlen(p), count);
916 line = strsep(&p, "\n");
917 if (!*line || *line == '#')
919 token = strsep(&line, delims);
922 id_num = atoi(token);
923 token = strsep(&line, delims);
926 offset = atoi(token);
927 token = strsep(&line, delims);
932 set_reg_val(stfcamss, id_num, offset, val);
935 st_info(ST_CAMSS, "id_num = %d, offset = 0x%x, 0x%x\n", id_num, offset, val);
939 static const struct file_operations vin_debug_fops = {
941 .read = vin_debug_read,
942 .write = vin_debug_write,
944 #endif /* CONFIG_DEBUG_FS */
947 static int stfcamss_probe(struct platform_device *pdev)
949 struct stfcamss *stfcamss;
950 struct stf_vin_dev *vin;
951 struct device_node *node;
952 struct resource res_mem;
953 struct device *dev = &pdev->dev;
954 int ret = 0, i, num_subdevs;
956 printk("stfcamss probe enter!\n");
958 stfcamss = devm_kzalloc(dev, sizeof(struct stfcamss), GFP_KERNEL);
962 stfcamss->isp_num = 2;
963 stfcamss->csi_num = 2;
964 #ifndef CONFIG_VIDEO_CADENCE_CSI2RX
965 stfcamss->csiphy_num = 2;
967 stfcamss->csiphy_num = 1;
970 stfcamss->dvp_dev = devm_kzalloc(dev,
971 sizeof(*stfcamss->dvp_dev), GFP_KERNEL);
972 if (!stfcamss->dvp_dev) {
977 stfcamss->csiphy_dev = devm_kzalloc(dev,
978 stfcamss->csiphy_num * sizeof(*stfcamss->csiphy_dev),
980 if (!stfcamss->csiphy_dev) {
985 stfcamss->csi_dev = devm_kzalloc(dev,
986 stfcamss->csi_num * sizeof(*stfcamss->csi_dev),
988 if (!stfcamss->csi_dev) {
993 stfcamss->isp_dev = devm_kzalloc(dev,
994 stfcamss->isp_num * sizeof(*stfcamss->isp_dev),
996 if (!stfcamss->isp_dev) {
1001 stfcamss->vin_dev = devm_kzalloc(dev,
1002 sizeof(*stfcamss->vin_dev),
1004 if (!stfcamss->vin_dev) {
1009 stfcamss->vin = devm_kzalloc(dev,
1010 sizeof(struct stf_vin_dev),
1012 if (!stfcamss->vin) {
1017 vin = stfcamss->vin;
1019 vin->irq = platform_get_irq(pdev, 0);
1020 if (vin->irq <= 0) {
1021 st_err(ST_CAMSS, "Could not get irq\n");
1025 vin->isp0_irq = platform_get_irq(pdev, 1);
1026 if (vin->isp0_irq <= 0) {
1027 st_err(ST_CAMSS, "Could not get isp0 irq\n");
1031 vin->isp1_irq = platform_get_irq(pdev, 2);
1032 if (vin->isp1_irq <= 0) {
1033 st_err(ST_CAMSS, "Could not get isp1 irq\n");
1037 #ifdef CONFIG_CLK_STARFIVE_JH7110
1038 stfcamss->nclks = ARRAY_SIZE(stfcamss_clocks);
1039 stfcamss->sys_clk = stfcamss_clocks;
1041 ret = devm_clk_bulk_get(dev, stfcamss->nclks, stfcamss->sys_clk);
1043 st_err(ST_CAMSS, "faied to get clk controls\n");
1046 #ifdef CONFIG_RESET_STARFIVE_JH7110
1047 stfcamss->nrsts = ARRAY_SIZE(stfcamss_resets);
1048 stfcamss->sys_rst = stfcamss_resets;
1050 ret = devm_reset_control_bulk_get_exclusive(dev, stfcamss->nrsts,
1053 st_err(ST_CAMSS, "faied to get reset controls\n");
1056 ret = stfcamss_get_mem_res(pdev, vin);
1058 st_err(ST_CAMSS, "Could not map registers\n");
1062 ret = vin_parse_dt(dev, vin);
1067 stfcamss->dev = dev;
1068 platform_set_drvdata(pdev, stfcamss);
1070 v4l2_async_notifier_init(&stfcamss->notifier);
1072 num_subdevs = stfcamss_of_parse_ports(stfcamss);
1073 if (num_subdevs < 0) {
1078 ret = stfcamss_init_subdevices(stfcamss);
1080 st_err(ST_CAMSS, "Failed to init subdevice: %d\n", ret);
1084 stfcamss->media_dev.dev = stfcamss->dev;
1085 strscpy(stfcamss->media_dev.model, "Starfive Camera Subsystem",
1086 sizeof(stfcamss->media_dev.model));
1087 stfcamss->media_dev.ops = &stfcamss_media_ops;
1088 media_device_init(&stfcamss->media_dev);
1090 stfcamss->v4l2_dev.mdev = &stfcamss->media_dev;
1092 ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
1094 st_err(ST_CAMSS, "Failed to register V4L2 device: %d\n", ret);
1095 goto err_cam_noti_med;
1098 ret = stfcamss_register_subdevices(stfcamss);
1100 st_err(ST_CAMSS, "Failed to register subdevice: %d\n", ret);
1101 goto err_cam_noti_med_vreg;
1105 stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
1106 ret = v4l2_async_notifier_register(&stfcamss->v4l2_dev,
1107 &stfcamss->notifier);
1110 "Failed to register async subdev nodes: %d\n",
1112 goto err_cam_noti_med_vreg_sub;
1115 ret = v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
1118 "Failed to register subdev nodes: %d\n",
1120 goto err_cam_noti_med_vreg_sub;
1123 ret = media_device_register(&stfcamss->media_dev);
1125 st_err(ST_CAMSS, "Failed to register media device: %d\n",
1127 goto err_cam_noti_med_vreg_sub_medreg;
1131 #ifdef CONFIG_DEBUG_FS
1132 stfcamss->debugfs_entry = debugfs_create_dir("stfcamss", NULL);
1133 stfcamss->vin_debugfs = debugfs_create_file("stf_vin",
1134 S_IRUGO | S_IWUSR, stfcamss->debugfs_entry,
1135 (void *)dev, &vin_debug_fops);
1136 debugfs_create_u32("dbg_level",
1137 S_IRUGO | S_IWUSR, stfcamss->debugfs_entry,
1139 debugfs_create_u32("dbg_mask",
1140 S_IRUGO | S_IWUSR, stfcamss->debugfs_entry,
1143 printk("stfcamss probe out!\n");
1147 #ifdef CONFIG_DEBUG_FS
1148 debugfs_remove(stfcamss->vin_debugfs);
1149 debugfs_remove_recursive(stfcamss->debugfs_entry);
1150 stfcamss->debugfs_entry = NULL;
1153 err_cam_noti_med_vreg_sub_medreg:
1154 err_cam_noti_med_vreg_sub:
1155 stfcamss_unregister_subdevices(stfcamss);
1156 err_cam_noti_med_vreg:
1157 v4l2_device_unregister(&stfcamss->v4l2_dev);
1159 media_device_cleanup(&stfcamss->media_dev);
1161 v4l2_async_notifier_cleanup(&stfcamss->notifier);
1167 static int stfcamss_remove(struct platform_device *pdev)
1169 struct stfcamss *stfcamss = platform_get_drvdata(pdev);
1171 dev_info(&pdev->dev, "remove done\n");
1173 #ifdef CONFIG_DEBUG_FS
1174 debugfs_remove(stfcamss->vin_debugfs);
1175 debugfs_remove_recursive(stfcamss->debugfs_entry);
1176 stfcamss->debugfs_entry = NULL;
1179 stfcamss_unregister_subdevices(stfcamss);
1180 v4l2_device_unregister(&stfcamss->v4l2_dev);
1181 media_device_cleanup(&stfcamss->media_dev);
1188 static const struct of_device_id stfcamss_of_match[] = {
1189 {.compatible = "starfive,stf-vin"},
1193 MODULE_DEVICE_TABLE(of, stfcamss_of_match);
1195 static struct platform_driver stfcamss_driver = {
1196 .probe = stfcamss_probe,
1197 .remove = stfcamss_remove,
1200 .of_match_table = of_match_ptr(stfcamss_of_match),
1204 static int __init stfcamss_init(void)
1206 return platform_driver_register(&stfcamss_driver);
1209 static void __exit stfcamss_cleanup(void)
1211 platform_driver_unregister(&stfcamss_driver);
1214 module_init(stfcamss_init);
1215 //fs_initcall(stfcamss_init);
1216 module_exit(stfcamss_cleanup);
1218 MODULE_LICENSE("GPL");