.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2011 Atmel Corporation |
---|
3 | 4 | * Josh Wu, <josh.wu@atmel.com> |
---|
.. | .. |
---|
5 | 6 | * Based on previous work by Lars Haring, <lars.haring@atmel.com> |
---|
6 | 7 | * and Sedji Gaouaou |
---|
7 | 8 | * Based on the bttv driver for Bt848 with respective copyright holders |
---|
8 | | - * |
---|
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 as |
---|
11 | | - * published by the Free Software Foundation. |
---|
12 | 9 | */ |
---|
13 | 10 | |
---|
14 | 11 | #include <linux/clk.h> |
---|
.. | .. |
---|
110 | 107 | bool enable_preview_path; |
---|
111 | 108 | |
---|
112 | 109 | struct completion complete; |
---|
113 | | - /* ISI peripherial clock */ |
---|
| 110 | + /* ISI peripheral clock */ |
---|
114 | 111 | struct clk *pclk; |
---|
115 | 112 | unsigned int irq; |
---|
116 | 113 | |
---|
.. | .. |
---|
151 | 148 | u32 fourcc = isi->current_fmt->fourcc; |
---|
152 | 149 | |
---|
153 | 150 | isi->enable_preview_path = fourcc == V4L2_PIX_FMT_RGB565 || |
---|
154 | | - fourcc == V4L2_PIX_FMT_RGB32; |
---|
| 151 | + fourcc == V4L2_PIX_FMT_RGB32 || |
---|
| 152 | + fourcc == V4L2_PIX_FMT_Y16; |
---|
155 | 153 | |
---|
156 | 154 | /* According to sensor's output format to set cfg2 */ |
---|
157 | 155 | cfg2 = isi->current_fmt->swap; |
---|
.. | .. |
---|
557 | 555 | return NULL; |
---|
558 | 556 | } |
---|
559 | 557 | |
---|
| 558 | +static void isi_try_fse(struct atmel_isi *isi, const struct isi_format *isi_fmt, |
---|
| 559 | + struct v4l2_subdev_pad_config *pad_cfg) |
---|
| 560 | +{ |
---|
| 561 | + int ret; |
---|
| 562 | + struct v4l2_subdev_frame_size_enum fse = { |
---|
| 563 | + .code = isi_fmt->mbus_code, |
---|
| 564 | + .which = V4L2_SUBDEV_FORMAT_TRY, |
---|
| 565 | + }; |
---|
| 566 | + |
---|
| 567 | + ret = v4l2_subdev_call(isi->entity.subdev, pad, enum_frame_size, |
---|
| 568 | + pad_cfg, &fse); |
---|
| 569 | + /* |
---|
| 570 | + * Attempt to obtain format size from subdev. If not available, |
---|
| 571 | + * just use the maximum ISI can receive. |
---|
| 572 | + */ |
---|
| 573 | + if (ret) { |
---|
| 574 | + pad_cfg->try_crop.width = MAX_SUPPORT_WIDTH; |
---|
| 575 | + pad_cfg->try_crop.height = MAX_SUPPORT_HEIGHT; |
---|
| 576 | + } else { |
---|
| 577 | + pad_cfg->try_crop.width = fse.max_width; |
---|
| 578 | + pad_cfg->try_crop.height = fse.max_height; |
---|
| 579 | + } |
---|
| 580 | +} |
---|
| 581 | + |
---|
560 | 582 | static int isi_try_fmt(struct atmel_isi *isi, struct v4l2_format *f, |
---|
561 | 583 | const struct isi_format **current_fmt) |
---|
562 | 584 | { |
---|
563 | 585 | const struct isi_format *isi_fmt; |
---|
564 | 586 | struct v4l2_pix_format *pixfmt = &f->fmt.pix; |
---|
565 | | - struct v4l2_subdev_pad_config pad_cfg; |
---|
| 587 | + struct v4l2_subdev_pad_config pad_cfg = {}; |
---|
566 | 588 | struct v4l2_subdev_format format = { |
---|
567 | 589 | .which = V4L2_SUBDEV_FORMAT_TRY, |
---|
568 | 590 | }; |
---|
.. | .. |
---|
579 | 601 | pixfmt->height = clamp(pixfmt->height, 0U, MAX_SUPPORT_HEIGHT); |
---|
580 | 602 | |
---|
581 | 603 | v4l2_fill_mbus_format(&format.format, pixfmt, isi_fmt->mbus_code); |
---|
| 604 | + |
---|
| 605 | + isi_try_fse(isi, isi_fmt, &pad_cfg); |
---|
| 606 | + |
---|
582 | 607 | ret = v4l2_subdev_call(isi->entity.subdev, pad, set_fmt, |
---|
583 | 608 | &pad_cfg, &format); |
---|
584 | 609 | if (ret < 0) |
---|
.. | .. |
---|
655 | 680 | static int isi_querycap(struct file *file, void *priv, |
---|
656 | 681 | struct v4l2_capability *cap) |
---|
657 | 682 | { |
---|
658 | | - strlcpy(cap->driver, "atmel-isi", sizeof(cap->driver)); |
---|
659 | | - strlcpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card)); |
---|
660 | | - strlcpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info)); |
---|
| 683 | + strscpy(cap->driver, "atmel-isi", sizeof(cap->driver)); |
---|
| 684 | + strscpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card)); |
---|
| 685 | + strscpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info)); |
---|
661 | 686 | return 0; |
---|
662 | 687 | } |
---|
663 | 688 | |
---|
.. | .. |
---|
668 | 693 | return -EINVAL; |
---|
669 | 694 | |
---|
670 | 695 | i->type = V4L2_INPUT_TYPE_CAMERA; |
---|
671 | | - strlcpy(i->name, "Camera", sizeof(i->name)); |
---|
| 696 | + strscpy(i->name, "Camera", sizeof(i->name)); |
---|
672 | 697 | return 0; |
---|
673 | 698 | } |
---|
674 | 699 | |
---|
.. | .. |
---|
790 | 815 | struct platform_device *pdev) |
---|
791 | 816 | { |
---|
792 | 817 | struct device_node *np = pdev->dev.of_node; |
---|
793 | | - struct v4l2_fwnode_endpoint ep; |
---|
| 818 | + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; |
---|
794 | 819 | int err; |
---|
795 | 820 | |
---|
796 | 821 | /* Default settings for ISI */ |
---|
.. | .. |
---|
993 | 1018 | .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8, |
---|
994 | 1019 | .bpp = 2, |
---|
995 | 1020 | .swap = ISI_CFG2_YCC_SWAP_MODE_1, |
---|
| 1021 | + }, { |
---|
| 1022 | + .fourcc = V4L2_PIX_FMT_GREY, |
---|
| 1023 | + .mbus_code = MEDIA_BUS_FMT_Y10_1X10, |
---|
| 1024 | + .bpp = 1, |
---|
| 1025 | + .swap = ISI_CFG2_GS_MODE_2_PIXEL | ISI_CFG2_GRAYSCALE, |
---|
| 1026 | + }, { |
---|
| 1027 | + .fourcc = V4L2_PIX_FMT_Y16, |
---|
| 1028 | + .mbus_code = MEDIA_BUS_FMT_Y10_1X10, |
---|
| 1029 | + .bpp = 2, |
---|
| 1030 | + .swap = ISI_CFG2_GS_MODE_2_PIXEL | ISI_CFG2_GRAYSCALE, |
---|
996 | 1031 | }, |
---|
997 | 1032 | }; |
---|
998 | 1033 | |
---|
.. | .. |
---|
1059 | 1094 | return ret; |
---|
1060 | 1095 | } |
---|
1061 | 1096 | |
---|
1062 | | - ret = video_register_device(isi->vdev, VFL_TYPE_GRABBER, -1); |
---|
| 1097 | + ret = video_register_device(isi->vdev, VFL_TYPE_VIDEO, -1); |
---|
1063 | 1098 | if (ret) { |
---|
1064 | 1099 | dev_err(isi->dev, "Failed to register video device\n"); |
---|
1065 | 1100 | return ret; |
---|
.. | .. |
---|
1078 | 1113 | |
---|
1079 | 1114 | dev_dbg(isi->dev, "Removing %s\n", video_device_node_name(isi->vdev)); |
---|
1080 | 1115 | |
---|
1081 | | - /* Checks internaly if vdev have been init or not */ |
---|
| 1116 | + /* Checks internally if vdev have been init or not */ |
---|
1082 | 1117 | video_unregister_device(isi->vdev); |
---|
1083 | 1118 | } |
---|
1084 | 1119 | |
---|
.. | .. |
---|
1124 | 1159 | |
---|
1125 | 1160 | static int isi_graph_init(struct atmel_isi *isi) |
---|
1126 | 1161 | { |
---|
1127 | | - struct v4l2_async_subdev **subdevs = NULL; |
---|
1128 | 1162 | int ret; |
---|
1129 | 1163 | |
---|
1130 | 1164 | /* Parse the graph to extract a list of subdevice DT nodes. */ |
---|
.. | .. |
---|
1134 | 1168 | return ret; |
---|
1135 | 1169 | } |
---|
1136 | 1170 | |
---|
1137 | | - /* Register the subdevices notifier. */ |
---|
1138 | | - subdevs = devm_kzalloc(isi->dev, sizeof(*subdevs), GFP_KERNEL); |
---|
1139 | | - if (!subdevs) { |
---|
| 1171 | + v4l2_async_notifier_init(&isi->notifier); |
---|
| 1172 | + |
---|
| 1173 | + ret = v4l2_async_notifier_add_subdev(&isi->notifier, &isi->entity.asd); |
---|
| 1174 | + if (ret) { |
---|
1140 | 1175 | of_node_put(isi->entity.node); |
---|
1141 | | - return -ENOMEM; |
---|
| 1176 | + return ret; |
---|
1142 | 1177 | } |
---|
1143 | 1178 | |
---|
1144 | | - subdevs[0] = &isi->entity.asd; |
---|
1145 | | - |
---|
1146 | | - isi->notifier.subdevs = subdevs; |
---|
1147 | | - isi->notifier.num_subdevs = 1; |
---|
1148 | 1179 | isi->notifier.ops = &isi_graph_notify_ops; |
---|
1149 | 1180 | |
---|
1150 | 1181 | ret = v4l2_async_notifier_register(&isi->v4l2_dev, &isi->notifier); |
---|
1151 | 1182 | if (ret < 0) { |
---|
1152 | 1183 | dev_err(isi->dev, "Notifier registration failed\n"); |
---|
1153 | | - of_node_put(isi->entity.node); |
---|
| 1184 | + v4l2_async_notifier_cleanup(&isi->notifier); |
---|
1154 | 1185 | return ret; |
---|
1155 | 1186 | } |
---|
1156 | 1187 | |
---|
.. | .. |
---|
1202 | 1233 | isi->vdev->fops = &isi_fops; |
---|
1203 | 1234 | isi->vdev->v4l2_dev = &isi->v4l2_dev; |
---|
1204 | 1235 | isi->vdev->queue = &isi->queue; |
---|
1205 | | - strlcpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name)); |
---|
| 1236 | + strscpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name)); |
---|
1206 | 1237 | isi->vdev->release = video_device_release; |
---|
1207 | 1238 | isi->vdev->ioctl_ops = &isi_ioctl_ops; |
---|
1208 | 1239 | isi->vdev->lock = &isi->lock; |
---|
.. | .. |
---|
1303 | 1334 | isi->fb_descriptors_phys); |
---|
1304 | 1335 | pm_runtime_disable(&pdev->dev); |
---|
1305 | 1336 | v4l2_async_notifier_unregister(&isi->notifier); |
---|
| 1337 | + v4l2_async_notifier_cleanup(&isi->notifier); |
---|
1306 | 1338 | v4l2_device_unregister(&isi->v4l2_dev); |
---|
1307 | 1339 | |
---|
1308 | 1340 | return 0; |
---|