1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * camss-vfe.c
4 *
5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module
6 *
7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
8 * Copyright (C) 2015-2018 Linaro Ltd.
9 */
10 #include <linux/clk.h>
11 #include <linux/completion.h>
12 #include <linux/interrupt.h>
13 #include <linux/iommu.h>
14 #include <linux/mutex.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_domain.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/spinlock_types.h>
20 #include <linux/spinlock.h>
21 #include <media/media-entity.h>
22 #include <media/v4l2-device.h>
23 #include <media/v4l2-subdev.h>
24
25 #include "camss-vfe.h"
26 #include "camss.h"
27
28 #define MSM_VFE_NAME "msm_vfe"
29
30 /* VFE reset timeout */
31 #define VFE_RESET_TIMEOUT_MS 50
32
33 #define SCALER_RATIO_MAX 16
34
35 static const struct camss_format_info formats_rdi_8x16[] = {
36 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
37 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
38 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
39 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
40 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
41 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
42 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
43 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
44 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1,
45 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
46 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1,
47 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
48 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1,
49 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
50 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1,
51 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
52 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1,
53 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
54 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1,
55 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
56 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1,
57 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
58 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1,
59 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
60 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1,
61 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
62 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1,
63 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
64 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1,
65 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
66 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1,
67 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
68 { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1,
69 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
70 };
71
72 static const struct camss_format_info formats_rdi_8x96[] = {
73 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
74 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
75 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
76 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
77 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
78 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
79 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
80 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
81 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1,
82 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
83 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1,
84 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
85 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1,
86 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
87 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1,
88 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
89 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1,
90 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
91 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1,
92 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
93 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1,
94 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
95 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1,
96 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
97 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1,
98 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
99 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1,
100 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
101 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1,
102 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
103 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1,
104 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
105 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1,
106 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
107 { MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1,
108 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
109 { MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1,
110 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
111 { MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1,
112 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
113 { MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1,
114 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
115 { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1,
116 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
117 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1,
118 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
119 };
120
121 static const struct camss_format_info formats_rdi_845[] = {
122 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
123 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
124 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
125 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
126 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
127 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
128 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
129 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
130 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1,
131 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
132 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1,
133 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
134 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1,
135 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
136 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1,
137 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
138 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1,
139 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
140 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1,
141 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
142 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1,
143 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
144 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1,
145 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
146 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1,
147 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
148 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1,
149 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
150 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1,
151 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
152 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1,
153 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
154 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1,
155 PER_PLANE_DATA(0, 1, 1, 1, 1, 12) },
156 { MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1,
157 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
158 { MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1,
159 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
160 { MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1,
161 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
162 { MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1,
163 PER_PLANE_DATA(0, 1, 1, 1, 1, 14) },
164 { MEDIA_BUS_FMT_Y8_1X8, 8, V4L2_PIX_FMT_GREY, 1,
165 PER_PLANE_DATA(0, 1, 1, 1, 1, 8) },
166 { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1,
167 PER_PLANE_DATA(0, 1, 1, 1, 1, 10) },
168 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1,
169 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
170 };
171
172 static const struct camss_format_info formats_pix_8x16[] = {
173 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
174 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
175 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
176 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
177 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
178 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
179 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
180 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
181 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
182 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
183 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
184 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
185 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
186 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
187 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
188 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
189 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
190 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
191 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
192 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
193 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
194 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
195 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
196 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
197 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
198 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
199 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
200 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
201 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
202 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
203 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
204 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
205 };
206
207 static const struct camss_format_info formats_pix_8x96[] = {
208 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
209 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
210 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
211 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
212 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
213 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
214 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1,
215 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
216 { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
217 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
218 { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
219 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
220 { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
221 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
222 { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1,
223 PER_PLANE_DATA(0, 1, 1, 2, 3, 8) },
224 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
225 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
226 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
227 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
228 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
229 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
230 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1,
231 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
232 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
233 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
234 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
235 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
236 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
237 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
238 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1,
239 PER_PLANE_DATA(0, 1, 1, 1, 2, 8) },
240 { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1,
241 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
242 { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1,
243 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
244 { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1,
245 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
246 { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1,
247 PER_PLANE_DATA(0, 1, 1, 1, 1, 16) },
248 };
249
250 const struct camss_formats vfe_formats_rdi_8x16 = {
251 .nformats = ARRAY_SIZE(formats_rdi_8x16),
252 .formats = formats_rdi_8x16
253 };
254
255 const struct camss_formats vfe_formats_pix_8x16 = {
256 .nformats = ARRAY_SIZE(formats_pix_8x16),
257 .formats = formats_pix_8x16
258 };
259
260 const struct camss_formats vfe_formats_rdi_8x96 = {
261 .nformats = ARRAY_SIZE(formats_rdi_8x96),
262 .formats = formats_rdi_8x96
263 };
264
265 const struct camss_formats vfe_formats_pix_8x96 = {
266 .nformats = ARRAY_SIZE(formats_pix_8x96),
267 .formats = formats_pix_8x96
268 };
269
270 const struct camss_formats vfe_formats_rdi_845 = {
271 .nformats = ARRAY_SIZE(formats_rdi_845),
272 .formats = formats_rdi_845
273 };
274
275 /* TODO: Replace with pix formats */
276 const struct camss_formats vfe_formats_pix_845 = {
277 .nformats = ARRAY_SIZE(formats_rdi_845),
278 .formats = formats_rdi_845
279 };
280
vfe_src_pad_code(struct vfe_line * line,u32 sink_code,unsigned int index,u32 src_req_code)281 static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
282 unsigned int index, u32 src_req_code)
283 {
284 struct vfe_device *vfe = to_vfe(line);
285
286 switch (vfe->camss->res->version) {
287 case CAMSS_8x16:
288 switch (sink_code) {
289 case MEDIA_BUS_FMT_YUYV8_1X16:
290 {
291 u32 src_code[] = {
292 MEDIA_BUS_FMT_YUYV8_1X16,
293 MEDIA_BUS_FMT_YUYV8_1_5X8,
294 };
295
296 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
297 index, src_req_code);
298 }
299 case MEDIA_BUS_FMT_YVYU8_1X16:
300 {
301 u32 src_code[] = {
302 MEDIA_BUS_FMT_YVYU8_1X16,
303 MEDIA_BUS_FMT_YVYU8_1_5X8,
304 };
305
306 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
307 index, src_req_code);
308 }
309 case MEDIA_BUS_FMT_UYVY8_1X16:
310 {
311 u32 src_code[] = {
312 MEDIA_BUS_FMT_UYVY8_1X16,
313 MEDIA_BUS_FMT_UYVY8_1_5X8,
314 };
315
316 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
317 index, src_req_code);
318 }
319 case MEDIA_BUS_FMT_VYUY8_1X16:
320 {
321 u32 src_code[] = {
322 MEDIA_BUS_FMT_VYUY8_1X16,
323 MEDIA_BUS_FMT_VYUY8_1_5X8,
324 };
325
326 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
327 index, src_req_code);
328 }
329 default:
330 if (index > 0)
331 return 0;
332
333 return sink_code;
334 }
335 break;
336 case CAMSS_8x96:
337 case CAMSS_660:
338 case CAMSS_845:
339 case CAMSS_8250:
340 case CAMSS_8280XP:
341 switch (sink_code) {
342 case MEDIA_BUS_FMT_YUYV8_1X16:
343 {
344 u32 src_code[] = {
345 MEDIA_BUS_FMT_YUYV8_1X16,
346 MEDIA_BUS_FMT_YVYU8_1X16,
347 MEDIA_BUS_FMT_UYVY8_1X16,
348 MEDIA_BUS_FMT_VYUY8_1X16,
349 MEDIA_BUS_FMT_YUYV8_1_5X8,
350 };
351
352 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
353 index, src_req_code);
354 }
355 case MEDIA_BUS_FMT_YVYU8_1X16:
356 {
357 u32 src_code[] = {
358 MEDIA_BUS_FMT_YVYU8_1X16,
359 MEDIA_BUS_FMT_YUYV8_1X16,
360 MEDIA_BUS_FMT_UYVY8_1X16,
361 MEDIA_BUS_FMT_VYUY8_1X16,
362 MEDIA_BUS_FMT_YVYU8_1_5X8,
363 };
364
365 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
366 index, src_req_code);
367 }
368 case MEDIA_BUS_FMT_UYVY8_1X16:
369 {
370 u32 src_code[] = {
371 MEDIA_BUS_FMT_UYVY8_1X16,
372 MEDIA_BUS_FMT_YUYV8_1X16,
373 MEDIA_BUS_FMT_YVYU8_1X16,
374 MEDIA_BUS_FMT_VYUY8_1X16,
375 MEDIA_BUS_FMT_UYVY8_1_5X8,
376 };
377
378 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
379 index, src_req_code);
380 }
381 case MEDIA_BUS_FMT_VYUY8_1X16:
382 {
383 u32 src_code[] = {
384 MEDIA_BUS_FMT_VYUY8_1X16,
385 MEDIA_BUS_FMT_YUYV8_1X16,
386 MEDIA_BUS_FMT_YVYU8_1X16,
387 MEDIA_BUS_FMT_UYVY8_1X16,
388 MEDIA_BUS_FMT_VYUY8_1_5X8,
389 };
390
391 return camss_format_find_code(src_code, ARRAY_SIZE(src_code),
392 index, src_req_code);
393 }
394 default:
395 if (index > 0)
396 return 0;
397
398 return sink_code;
399 }
400 break;
401 }
402 return 0;
403 }
404
vfe_reset(struct vfe_device * vfe)405 int vfe_reset(struct vfe_device *vfe)
406 {
407 unsigned long time;
408
409 reinit_completion(&vfe->reset_complete);
410
411 vfe->res->hw_ops->global_reset(vfe);
412
413 time = wait_for_completion_timeout(&vfe->reset_complete,
414 msecs_to_jiffies(VFE_RESET_TIMEOUT_MS));
415 if (!time) {
416 dev_err(vfe->camss->dev, "VFE reset timeout\n");
417 return -EIO;
418 }
419
420 return 0;
421 }
422
vfe_init_outputs(struct vfe_device * vfe)423 static void vfe_init_outputs(struct vfe_device *vfe)
424 {
425 int i;
426
427 for (i = 0; i < vfe->res->line_num; i++) {
428 struct vfe_output *output = &vfe->line[i].output;
429
430 output->state = VFE_OUTPUT_OFF;
431 output->buf[0] = NULL;
432 output->buf[1] = NULL;
433 INIT_LIST_HEAD(&output->pending_bufs);
434 }
435 }
436
vfe_reset_output_maps(struct vfe_device * vfe)437 static void vfe_reset_output_maps(struct vfe_device *vfe)
438 {
439 int i;
440
441 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
442 vfe->wm_output_map[i] = VFE_LINE_NONE;
443 }
444
vfe_reserve_wm(struct vfe_device * vfe,enum vfe_line_id line_id)445 int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id)
446 {
447 int ret = -EBUSY;
448 int i;
449
450 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) {
451 if (vfe->wm_output_map[i] == VFE_LINE_NONE) {
452 vfe->wm_output_map[i] = line_id;
453 ret = i;
454 break;
455 }
456 }
457
458 return ret;
459 }
460
vfe_release_wm(struct vfe_device * vfe,u8 wm)461 int vfe_release_wm(struct vfe_device *vfe, u8 wm)
462 {
463 if (wm >= ARRAY_SIZE(vfe->wm_output_map))
464 return -EINVAL;
465
466 vfe->wm_output_map[wm] = VFE_LINE_NONE;
467
468 return 0;
469 }
470
vfe_buf_get_pending(struct vfe_output * output)471 struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output)
472 {
473 struct camss_buffer *buffer = NULL;
474
475 if (!list_empty(&output->pending_bufs)) {
476 buffer = list_first_entry(&output->pending_bufs,
477 struct camss_buffer,
478 queue);
479 list_del(&buffer->queue);
480 }
481
482 return buffer;
483 }
484
vfe_buf_add_pending(struct vfe_output * output,struct camss_buffer * buffer)485 void vfe_buf_add_pending(struct vfe_output *output,
486 struct camss_buffer *buffer)
487 {
488 INIT_LIST_HEAD(&buffer->queue);
489 list_add_tail(&buffer->queue, &output->pending_bufs);
490 }
491
492 /*
493 * vfe_buf_flush_pending - Flush all pending buffers.
494 * @output: VFE output
495 * @state: vb2 buffer state
496 */
vfe_buf_flush_pending(struct vfe_output * output,enum vb2_buffer_state state)497 static void vfe_buf_flush_pending(struct vfe_output *output,
498 enum vb2_buffer_state state)
499 {
500 struct camss_buffer *buf;
501 struct camss_buffer *t;
502
503 list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
504 vb2_buffer_done(&buf->vb.vb2_buf, state);
505 list_del(&buf->queue);
506 }
507 }
508
vfe_put_output(struct vfe_line * line)509 int vfe_put_output(struct vfe_line *line)
510 {
511 struct vfe_device *vfe = to_vfe(line);
512 struct vfe_output *output = &line->output;
513 unsigned long flags;
514 unsigned int i;
515
516 spin_lock_irqsave(&vfe->output_lock, flags);
517
518 for (i = 0; i < output->wm_num; i++)
519 vfe_release_wm(vfe, output->wm_idx[i]);
520
521 output->state = VFE_OUTPUT_OFF;
522
523 spin_unlock_irqrestore(&vfe->output_lock, flags);
524 return 0;
525 }
526
vfe_disable_output(struct vfe_line * line)527 static int vfe_disable_output(struct vfe_line *line)
528 {
529 struct vfe_device *vfe = to_vfe(line);
530 struct vfe_output *output = &line->output;
531 unsigned long flags;
532 unsigned int i;
533
534 spin_lock_irqsave(&vfe->output_lock, flags);
535 for (i = 0; i < output->wm_num; i++)
536 vfe->res->hw_ops->vfe_wm_stop(vfe, output->wm_idx[i]);
537 output->gen2.active_num = 0;
538 spin_unlock_irqrestore(&vfe->output_lock, flags);
539
540 return vfe_reset(vfe);
541 }
542
543 /*
544 * vfe_disable - Disable streaming on VFE line
545 * @line: VFE line
546 *
547 * Return 0 on success or a negative error code otherwise
548 */
vfe_disable(struct vfe_line * line)549 int vfe_disable(struct vfe_line *line)
550 {
551 struct vfe_device *vfe = to_vfe(line);
552 int ret;
553
554 ret = vfe_disable_output(line);
555 if (ret)
556 goto error;
557
558 vfe_put_output(line);
559
560 mutex_lock(&vfe->stream_lock);
561
562 vfe->stream_count--;
563
564 mutex_unlock(&vfe->stream_lock);
565
566 error:
567 return ret;
568 }
569
570 /**
571 * vfe_isr_comp_done() - Process composite image done interrupt
572 * @vfe: VFE Device
573 * @comp: Composite image id
574 */
vfe_isr_comp_done(struct vfe_device * vfe,u8 comp)575 void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp)
576 {
577 unsigned int i;
578
579 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
580 if (vfe->wm_output_map[i] == VFE_LINE_PIX) {
581 vfe->isr_ops.wm_done(vfe, i);
582 break;
583 }
584 }
585
vfe_isr_reset_ack(struct vfe_device * vfe)586 void vfe_isr_reset_ack(struct vfe_device *vfe)
587 {
588 complete(&vfe->reset_complete);
589 }
590
591 /*
592 * vfe_pm_domain_off - Disable power domains specific to this VFE.
593 * @vfe: VFE Device
594 */
vfe_pm_domain_off(struct vfe_device * vfe)595 void vfe_pm_domain_off(struct vfe_device *vfe)
596 {
597 if (!vfe->genpd)
598 return;
599
600 device_link_del(vfe->genpd_link);
601 vfe->genpd_link = NULL;
602 }
603
604 /*
605 * vfe_pm_domain_on - Enable power domains specific to this VFE.
606 * @vfe: VFE Device
607 */
vfe_pm_domain_on(struct vfe_device * vfe)608 int vfe_pm_domain_on(struct vfe_device *vfe)
609 {
610 struct camss *camss = vfe->camss;
611
612 if (!vfe->genpd)
613 return 0;
614
615 vfe->genpd_link = device_link_add(camss->dev, vfe->genpd,
616 DL_FLAG_STATELESS |
617 DL_FLAG_PM_RUNTIME |
618 DL_FLAG_RPM_ACTIVE);
619 if (!vfe->genpd_link)
620 return -EINVAL;
621
622 return 0;
623 }
624
vfe_match_clock_names(struct vfe_device * vfe,struct camss_clock * clock)625 static int vfe_match_clock_names(struct vfe_device *vfe,
626 struct camss_clock *clock)
627 {
628 char vfe_name[7]; /* vfeXXX\0 */
629 char vfe_lite_name[12]; /* vfe_liteXXX\0 */
630
631 snprintf(vfe_name, sizeof(vfe_name), "vfe%d", vfe->id);
632 snprintf(vfe_lite_name, sizeof(vfe_lite_name), "vfe_lite%d", vfe->id);
633
634 return (!strcmp(clock->name, vfe_name) ||
635 !strcmp(clock->name, vfe_lite_name) ||
636 !strcmp(clock->name, "vfe_lite"));
637 }
638
639 /*
640 * vfe_set_clock_rates - Calculate and set clock rates on VFE module
641 * @vfe: VFE device
642 *
643 * Return 0 on success or a negative error code otherwise
644 */
vfe_set_clock_rates(struct vfe_device * vfe)645 static int vfe_set_clock_rates(struct vfe_device *vfe)
646 {
647 struct device *dev = vfe->camss->dev;
648 u64 pixel_clock[VFE_LINE_NUM_MAX];
649 int i, j;
650 int ret;
651
652 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
653 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
654 &pixel_clock[i]);
655 if (ret)
656 pixel_clock[i] = 0;
657 }
658
659 for (i = 0; i < vfe->nclocks; i++) {
660 struct camss_clock *clock = &vfe->clock[i];
661
662 if (vfe_match_clock_names(vfe, clock)) {
663 u64 min_rate = 0;
664 long rate;
665
666 for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) {
667 u32 tmp;
668 u8 bpp;
669
670 if (j == VFE_LINE_PIX) {
671 tmp = pixel_clock[j];
672 } else {
673 struct vfe_line *l = &vfe->line[j];
674
675 bpp = camss_format_get_bpp(l->formats,
676 l->nformats,
677 l->fmt[MSM_VFE_PAD_SINK].code);
678 tmp = pixel_clock[j] * bpp / 64;
679 }
680
681 if (min_rate < tmp)
682 min_rate = tmp;
683 }
684
685 camss_add_clock_margin(&min_rate);
686
687 for (j = 0; j < clock->nfreqs; j++)
688 if (min_rate < clock->freq[j])
689 break;
690
691 if (j == clock->nfreqs) {
692 dev_err(dev,
693 "Pixel clock is too high for VFE");
694 return -EINVAL;
695 }
696
697 /* if sensor pixel clock is not available */
698 /* set highest possible VFE clock rate */
699 if (min_rate == 0)
700 j = clock->nfreqs - 1;
701
702 rate = clk_round_rate(clock->clk, clock->freq[j]);
703 if (rate < 0) {
704 dev_err(dev, "clk round rate failed: %ld\n",
705 rate);
706 return -EINVAL;
707 }
708
709 ret = clk_set_rate(clock->clk, rate);
710 if (ret < 0) {
711 dev_err(dev, "clk set rate failed: %d\n", ret);
712 return ret;
713 }
714 }
715 }
716
717 return 0;
718 }
719
720 /*
721 * vfe_check_clock_rates - Check current clock rates on VFE module
722 * @vfe: VFE device
723 *
724 * Return 0 if current clock rates are suitable for a new pipeline
725 * or a negative error code otherwise
726 */
vfe_check_clock_rates(struct vfe_device * vfe)727 static int vfe_check_clock_rates(struct vfe_device *vfe)
728 {
729 u64 pixel_clock[VFE_LINE_NUM_MAX];
730 int i, j;
731 int ret;
732
733 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
734 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
735 &pixel_clock[i]);
736 if (ret)
737 pixel_clock[i] = 0;
738 }
739
740 for (i = 0; i < vfe->nclocks; i++) {
741 struct camss_clock *clock = &vfe->clock[i];
742
743 if (vfe_match_clock_names(vfe, clock)) {
744 u64 min_rate = 0;
745 unsigned long rate;
746
747 for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) {
748 u32 tmp;
749 u8 bpp;
750
751 if (j == VFE_LINE_PIX) {
752 tmp = pixel_clock[j];
753 } else {
754 struct vfe_line *l = &vfe->line[j];
755
756 bpp = camss_format_get_bpp(l->formats,
757 l->nformats,
758 l->fmt[MSM_VFE_PAD_SINK].code);
759 tmp = pixel_clock[j] * bpp / 64;
760 }
761
762 if (min_rate < tmp)
763 min_rate = tmp;
764 }
765
766 camss_add_clock_margin(&min_rate);
767
768 rate = clk_get_rate(clock->clk);
769 if (rate < min_rate)
770 return -EBUSY;
771 }
772 }
773
774 return 0;
775 }
776
777 /*
778 * vfe_get - Power up and reset VFE module
779 * @vfe: VFE Device
780 *
781 * Return 0 on success or a negative error code otherwise
782 */
vfe_get(struct vfe_device * vfe)783 int vfe_get(struct vfe_device *vfe)
784 {
785 int ret;
786
787 mutex_lock(&vfe->power_lock);
788
789 if (vfe->power_count == 0) {
790 ret = vfe->res->hw_ops->pm_domain_on(vfe);
791 if (ret < 0)
792 goto error_pm_domain;
793
794 ret = pm_runtime_resume_and_get(vfe->camss->dev);
795 if (ret < 0)
796 goto error_domain_off;
797
798 ret = vfe_set_clock_rates(vfe);
799 if (ret < 0)
800 goto error_pm_runtime_get;
801
802 ret = camss_enable_clocks(vfe->nclocks, vfe->clock,
803 vfe->camss->dev);
804 if (ret < 0)
805 goto error_pm_runtime_get;
806
807 ret = vfe_reset(vfe);
808 if (ret < 0)
809 goto error_reset;
810
811 vfe_reset_output_maps(vfe);
812
813 vfe_init_outputs(vfe);
814
815 vfe->res->hw_ops->hw_version(vfe);
816 } else {
817 ret = vfe_check_clock_rates(vfe);
818 if (ret < 0)
819 goto error_pm_domain;
820 }
821 vfe->power_count++;
822
823 mutex_unlock(&vfe->power_lock);
824
825 return 0;
826
827 error_reset:
828 camss_disable_clocks(vfe->nclocks, vfe->clock);
829
830 error_pm_runtime_get:
831 pm_runtime_put_sync(vfe->camss->dev);
832 error_domain_off:
833 vfe->res->hw_ops->pm_domain_off(vfe);
834
835 error_pm_domain:
836 mutex_unlock(&vfe->power_lock);
837
838 return ret;
839 }
840
841 /*
842 * vfe_put - Power down VFE module
843 * @vfe: VFE Device
844 */
vfe_put(struct vfe_device * vfe)845 void vfe_put(struct vfe_device *vfe)
846 {
847 mutex_lock(&vfe->power_lock);
848
849 if (vfe->power_count == 0) {
850 dev_err(vfe->camss->dev, "vfe power off on power_count == 0\n");
851 goto exit;
852 } else if (vfe->power_count == 1) {
853 if (vfe->was_streaming) {
854 vfe->was_streaming = 0;
855 vfe->res->hw_ops->vfe_halt(vfe);
856 }
857 camss_disable_clocks(vfe->nclocks, vfe->clock);
858 pm_runtime_put_sync(vfe->camss->dev);
859 vfe->res->hw_ops->pm_domain_off(vfe);
860 }
861
862 vfe->power_count--;
863
864 exit:
865 mutex_unlock(&vfe->power_lock);
866 }
867
868 /*
869 * vfe_flush_buffers - Return all vb2 buffers
870 * @vid: Video device structure
871 * @state: vb2 buffer state of the returned buffers
872 *
873 * Return all buffers to vb2. This includes queued pending buffers (still
874 * unused) and any buffers given to the hardware but again still not used.
875 *
876 * Return 0 on success or a negative error code otherwise
877 */
vfe_flush_buffers(struct camss_video * vid,enum vb2_buffer_state state)878 int vfe_flush_buffers(struct camss_video *vid,
879 enum vb2_buffer_state state)
880 {
881 struct vfe_line *line = container_of(vid, struct vfe_line, video_out);
882 struct vfe_device *vfe = to_vfe(line);
883 struct vfe_output *output;
884 unsigned long flags;
885
886 output = &line->output;
887
888 spin_lock_irqsave(&vfe->output_lock, flags);
889
890 vfe_buf_flush_pending(output, state);
891
892 if (output->buf[0])
893 vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state);
894
895 if (output->buf[1])
896 vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state);
897
898 if (output->last_buffer) {
899 vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state);
900 output->last_buffer = NULL;
901 }
902
903 spin_unlock_irqrestore(&vfe->output_lock, flags);
904
905 return 0;
906 }
907
908 /*
909 * vfe_set_power - Power on/off VFE module
910 * @sd: VFE V4L2 subdevice
911 * @on: Requested power state
912 *
913 * Return 0 on success or a negative error code otherwise
914 */
vfe_set_power(struct v4l2_subdev * sd,int on)915 static int vfe_set_power(struct v4l2_subdev *sd, int on)
916 {
917 struct vfe_line *line = v4l2_get_subdevdata(sd);
918 struct vfe_device *vfe = to_vfe(line);
919 int ret;
920
921 if (on) {
922 ret = vfe_get(vfe);
923 if (ret < 0)
924 return ret;
925 } else {
926 vfe_put(vfe);
927 }
928
929 return 0;
930 }
931
932 /*
933 * vfe_set_stream - Enable/disable streaming on VFE module
934 * @sd: VFE V4L2 subdevice
935 * @enable: Requested streaming state
936 *
937 * Main configuration of VFE module is triggered here.
938 *
939 * Return 0 on success or a negative error code otherwise
940 */
vfe_set_stream(struct v4l2_subdev * sd,int enable)941 static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
942 {
943 struct vfe_line *line = v4l2_get_subdevdata(sd);
944 struct vfe_device *vfe = to_vfe(line);
945 int ret;
946
947 if (enable) {
948 line->output.state = VFE_OUTPUT_RESERVED;
949 ret = vfe->res->hw_ops->vfe_enable(line);
950 if (ret < 0)
951 dev_err(vfe->camss->dev,
952 "Failed to enable vfe outputs\n");
953 } else {
954 ret = vfe->res->hw_ops->vfe_disable(line);
955 if (ret < 0)
956 dev_err(vfe->camss->dev,
957 "Failed to disable vfe outputs\n");
958 }
959
960 return ret;
961 }
962
963 /*
964 * __vfe_get_format - Get pointer to format structure
965 * @line: VFE line
966 * @sd_state: V4L2 subdev state
967 * @pad: pad from which format is requested
968 * @which: TRY or ACTIVE format
969 *
970 * Return pointer to TRY or ACTIVE format structure
971 */
972 static struct v4l2_mbus_framefmt *
__vfe_get_format(struct vfe_line * line,struct v4l2_subdev_state * sd_state,unsigned int pad,enum v4l2_subdev_format_whence which)973 __vfe_get_format(struct vfe_line *line,
974 struct v4l2_subdev_state *sd_state,
975 unsigned int pad,
976 enum v4l2_subdev_format_whence which)
977 {
978 if (which == V4L2_SUBDEV_FORMAT_TRY)
979 return v4l2_subdev_state_get_format(sd_state, pad);
980
981 return &line->fmt[pad];
982 }
983
984 /*
985 * __vfe_get_compose - Get pointer to compose selection structure
986 * @line: VFE line
987 * @sd_state: V4L2 subdev state
988 * @which: TRY or ACTIVE format
989 *
990 * Return pointer to TRY or ACTIVE compose rectangle structure
991 */
992 static struct v4l2_rect *
__vfe_get_compose(struct vfe_line * line,struct v4l2_subdev_state * sd_state,enum v4l2_subdev_format_whence which)993 __vfe_get_compose(struct vfe_line *line,
994 struct v4l2_subdev_state *sd_state,
995 enum v4l2_subdev_format_whence which)
996 {
997 if (which == V4L2_SUBDEV_FORMAT_TRY)
998 return v4l2_subdev_state_get_compose(sd_state,
999 MSM_VFE_PAD_SINK);
1000
1001 return &line->compose;
1002 }
1003
1004 /*
1005 * __vfe_get_crop - Get pointer to crop selection structure
1006 * @line: VFE line
1007 * @sd_state: V4L2 subdev state
1008 * @which: TRY or ACTIVE format
1009 *
1010 * Return pointer to TRY or ACTIVE crop rectangle structure
1011 */
1012 static struct v4l2_rect *
__vfe_get_crop(struct vfe_line * line,struct v4l2_subdev_state * sd_state,enum v4l2_subdev_format_whence which)1013 __vfe_get_crop(struct vfe_line *line,
1014 struct v4l2_subdev_state *sd_state,
1015 enum v4l2_subdev_format_whence which)
1016 {
1017 if (which == V4L2_SUBDEV_FORMAT_TRY)
1018 return v4l2_subdev_state_get_crop(sd_state, MSM_VFE_PAD_SRC);
1019
1020 return &line->crop;
1021 }
1022
1023 /*
1024 * vfe_try_format - Handle try format by pad subdev method
1025 * @line: VFE line
1026 * @sd_state: V4L2 subdev state
1027 * @pad: pad on which format is requested
1028 * @fmt: pointer to v4l2 format structure
1029 * @which: wanted subdev format
1030 */
vfe_try_format(struct vfe_line * line,struct v4l2_subdev_state * sd_state,unsigned int pad,struct v4l2_mbus_framefmt * fmt,enum v4l2_subdev_format_whence which)1031 static void vfe_try_format(struct vfe_line *line,
1032 struct v4l2_subdev_state *sd_state,
1033 unsigned int pad,
1034 struct v4l2_mbus_framefmt *fmt,
1035 enum v4l2_subdev_format_whence which)
1036 {
1037 unsigned int i;
1038 u32 code;
1039
1040 switch (pad) {
1041 case MSM_VFE_PAD_SINK:
1042 /* Set format on sink pad */
1043
1044 for (i = 0; i < line->nformats; i++)
1045 if (fmt->code == line->formats[i].code)
1046 break;
1047
1048 /* If not found, use UYVY as default */
1049 if (i >= line->nformats)
1050 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
1051
1052 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
1053 fmt->height = clamp_t(u32, fmt->height, 1, 8191);
1054
1055 fmt->field = V4L2_FIELD_NONE;
1056 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1057
1058 break;
1059
1060 case MSM_VFE_PAD_SRC:
1061 /* Set and return a format same as sink pad */
1062 code = fmt->code;
1063
1064 *fmt = *__vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK,
1065 which);
1066
1067 fmt->code = vfe_src_pad_code(line, fmt->code, 0, code);
1068
1069 if (line->id == VFE_LINE_PIX) {
1070 struct v4l2_rect *rect;
1071
1072 rect = __vfe_get_crop(line, sd_state, which);
1073
1074 fmt->width = rect->width;
1075 fmt->height = rect->height;
1076 }
1077
1078 break;
1079 }
1080
1081 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1082 }
1083
1084 /*
1085 * vfe_try_compose - Handle try compose selection by pad subdev method
1086 * @line: VFE line
1087 * @sd_state: V4L2 subdev state
1088 * @rect: pointer to v4l2 rect structure
1089 * @which: wanted subdev format
1090 */
vfe_try_compose(struct vfe_line * line,struct v4l2_subdev_state * sd_state,struct v4l2_rect * rect,enum v4l2_subdev_format_whence which)1091 static void vfe_try_compose(struct vfe_line *line,
1092 struct v4l2_subdev_state *sd_state,
1093 struct v4l2_rect *rect,
1094 enum v4l2_subdev_format_whence which)
1095 {
1096 struct v4l2_mbus_framefmt *fmt;
1097
1098 fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK, which);
1099
1100 if (rect->width > fmt->width)
1101 rect->width = fmt->width;
1102
1103 if (rect->height > fmt->height)
1104 rect->height = fmt->height;
1105
1106 if (fmt->width > rect->width * SCALER_RATIO_MAX)
1107 rect->width = (fmt->width + SCALER_RATIO_MAX - 1) /
1108 SCALER_RATIO_MAX;
1109
1110 rect->width &= ~0x1;
1111
1112 if (fmt->height > rect->height * SCALER_RATIO_MAX)
1113 rect->height = (fmt->height + SCALER_RATIO_MAX - 1) /
1114 SCALER_RATIO_MAX;
1115
1116 if (rect->width < 16)
1117 rect->width = 16;
1118
1119 if (rect->height < 4)
1120 rect->height = 4;
1121 }
1122
1123 /*
1124 * vfe_try_crop - Handle try crop selection by pad subdev method
1125 * @line: VFE line
1126 * @sd_state: V4L2 subdev state
1127 * @rect: pointer to v4l2 rect structure
1128 * @which: wanted subdev format
1129 */
vfe_try_crop(struct vfe_line * line,struct v4l2_subdev_state * sd_state,struct v4l2_rect * rect,enum v4l2_subdev_format_whence which)1130 static void vfe_try_crop(struct vfe_line *line,
1131 struct v4l2_subdev_state *sd_state,
1132 struct v4l2_rect *rect,
1133 enum v4l2_subdev_format_whence which)
1134 {
1135 struct v4l2_rect *compose;
1136
1137 compose = __vfe_get_compose(line, sd_state, which);
1138
1139 if (rect->width > compose->width)
1140 rect->width = compose->width;
1141
1142 if (rect->width + rect->left > compose->width)
1143 rect->left = compose->width - rect->width;
1144
1145 if (rect->height > compose->height)
1146 rect->height = compose->height;
1147
1148 if (rect->height + rect->top > compose->height)
1149 rect->top = compose->height - rect->height;
1150
1151 /* wm in line based mode writes multiple of 16 horizontally */
1152 rect->left += (rect->width & 0xf) >> 1;
1153 rect->width &= ~0xf;
1154
1155 if (rect->width < 16) {
1156 rect->left = 0;
1157 rect->width = 16;
1158 }
1159
1160 if (rect->height < 4) {
1161 rect->top = 0;
1162 rect->height = 4;
1163 }
1164 }
1165
1166 /*
1167 * vfe_enum_mbus_code - Handle pixel format enumeration
1168 * @sd: VFE V4L2 subdevice
1169 * @sd_state: V4L2 subdev state
1170 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1171 *
1172 * return -EINVAL or zero on success
1173 */
vfe_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)1174 static int vfe_enum_mbus_code(struct v4l2_subdev *sd,
1175 struct v4l2_subdev_state *sd_state,
1176 struct v4l2_subdev_mbus_code_enum *code)
1177 {
1178 struct vfe_line *line = v4l2_get_subdevdata(sd);
1179
1180 if (code->pad == MSM_VFE_PAD_SINK) {
1181 if (code->index >= line->nformats)
1182 return -EINVAL;
1183
1184 code->code = line->formats[code->index].code;
1185 } else {
1186 struct v4l2_mbus_framefmt *sink_fmt;
1187
1188 sink_fmt = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SINK,
1189 code->which);
1190
1191 code->code = vfe_src_pad_code(line, sink_fmt->code,
1192 code->index, 0);
1193 if (!code->code)
1194 return -EINVAL;
1195 }
1196
1197 return 0;
1198 }
1199
1200 /*
1201 * vfe_enum_frame_size - Handle frame size enumeration
1202 * @sd: VFE V4L2 subdevice
1203 * @sd_state: V4L2 subdev state
1204 * @fse: pointer to v4l2_subdev_frame_size_enum structure
1205 *
1206 * Return -EINVAL or zero on success
1207 */
vfe_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)1208 static int vfe_enum_frame_size(struct v4l2_subdev *sd,
1209 struct v4l2_subdev_state *sd_state,
1210 struct v4l2_subdev_frame_size_enum *fse)
1211 {
1212 struct vfe_line *line = v4l2_get_subdevdata(sd);
1213 struct v4l2_mbus_framefmt format;
1214
1215 if (fse->index != 0)
1216 return -EINVAL;
1217
1218 format.code = fse->code;
1219 format.width = 1;
1220 format.height = 1;
1221 vfe_try_format(line, sd_state, fse->pad, &format, fse->which);
1222 fse->min_width = format.width;
1223 fse->min_height = format.height;
1224
1225 if (format.code != fse->code)
1226 return -EINVAL;
1227
1228 format.code = fse->code;
1229 format.width = -1;
1230 format.height = -1;
1231 vfe_try_format(line, sd_state, fse->pad, &format, fse->which);
1232 fse->max_width = format.width;
1233 fse->max_height = format.height;
1234
1235 return 0;
1236 }
1237
1238 /*
1239 * vfe_get_format - Handle get format by pads subdev method
1240 * @sd: VFE V4L2 subdevice
1241 * @sd_state: V4L2 subdev state
1242 * @fmt: pointer to v4l2 subdev format structure
1243 *
1244 * Return -EINVAL or zero on success
1245 */
vfe_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)1246 static int vfe_get_format(struct v4l2_subdev *sd,
1247 struct v4l2_subdev_state *sd_state,
1248 struct v4l2_subdev_format *fmt)
1249 {
1250 struct vfe_line *line = v4l2_get_subdevdata(sd);
1251 struct v4l2_mbus_framefmt *format;
1252
1253 format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which);
1254 if (format == NULL)
1255 return -EINVAL;
1256
1257 fmt->format = *format;
1258
1259 return 0;
1260 }
1261
1262 static int vfe_set_selection(struct v4l2_subdev *sd,
1263 struct v4l2_subdev_state *sd_state,
1264 struct v4l2_subdev_selection *sel);
1265
1266 /*
1267 * vfe_set_format - Handle set format by pads subdev method
1268 * @sd: VFE V4L2 subdevice
1269 * @sd_state: V4L2 subdev state
1270 * @fmt: pointer to v4l2 subdev format structure
1271 *
1272 * Return -EINVAL or zero on success
1273 */
vfe_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)1274 static int vfe_set_format(struct v4l2_subdev *sd,
1275 struct v4l2_subdev_state *sd_state,
1276 struct v4l2_subdev_format *fmt)
1277 {
1278 struct vfe_line *line = v4l2_get_subdevdata(sd);
1279 struct v4l2_mbus_framefmt *format;
1280
1281 format = __vfe_get_format(line, sd_state, fmt->pad, fmt->which);
1282 if (format == NULL)
1283 return -EINVAL;
1284
1285 vfe_try_format(line, sd_state, fmt->pad, &fmt->format, fmt->which);
1286 *format = fmt->format;
1287
1288 if (fmt->pad == MSM_VFE_PAD_SINK) {
1289 struct v4l2_subdev_selection sel = { 0 };
1290 int ret;
1291
1292 /* Propagate the format from sink to source */
1293 format = __vfe_get_format(line, sd_state, MSM_VFE_PAD_SRC,
1294 fmt->which);
1295
1296 *format = fmt->format;
1297 vfe_try_format(line, sd_state, MSM_VFE_PAD_SRC, format,
1298 fmt->which);
1299
1300 if (line->id != VFE_LINE_PIX)
1301 return 0;
1302
1303 /* Reset sink pad compose selection */
1304 sel.which = fmt->which;
1305 sel.pad = MSM_VFE_PAD_SINK;
1306 sel.target = V4L2_SEL_TGT_COMPOSE;
1307 sel.r.width = fmt->format.width;
1308 sel.r.height = fmt->format.height;
1309 ret = vfe_set_selection(sd, sd_state, &sel);
1310 if (ret < 0)
1311 return ret;
1312 }
1313
1314 return 0;
1315 }
1316
1317 /*
1318 * vfe_get_selection - Handle get selection by pads subdev method
1319 * @sd: VFE V4L2 subdevice
1320 * @sd_state: V4L2 subdev state
1321 * @sel: pointer to v4l2 subdev selection structure
1322 *
1323 * Return -EINVAL or zero on success
1324 */
vfe_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)1325 static int vfe_get_selection(struct v4l2_subdev *sd,
1326 struct v4l2_subdev_state *sd_state,
1327 struct v4l2_subdev_selection *sel)
1328 {
1329 struct vfe_line *line = v4l2_get_subdevdata(sd);
1330 struct v4l2_subdev_format fmt = { 0 };
1331 struct v4l2_rect *rect;
1332 int ret;
1333
1334 if (line->id != VFE_LINE_PIX)
1335 return -EINVAL;
1336
1337 if (sel->pad == MSM_VFE_PAD_SINK)
1338 switch (sel->target) {
1339 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1340 fmt.pad = sel->pad;
1341 fmt.which = sel->which;
1342 ret = vfe_get_format(sd, sd_state, &fmt);
1343 if (ret < 0)
1344 return ret;
1345
1346 sel->r.left = 0;
1347 sel->r.top = 0;
1348 sel->r.width = fmt.format.width;
1349 sel->r.height = fmt.format.height;
1350 break;
1351 case V4L2_SEL_TGT_COMPOSE:
1352 rect = __vfe_get_compose(line, sd_state, sel->which);
1353 if (rect == NULL)
1354 return -EINVAL;
1355
1356 sel->r = *rect;
1357 break;
1358 default:
1359 return -EINVAL;
1360 }
1361 else if (sel->pad == MSM_VFE_PAD_SRC)
1362 switch (sel->target) {
1363 case V4L2_SEL_TGT_CROP_BOUNDS:
1364 rect = __vfe_get_compose(line, sd_state, sel->which);
1365 if (rect == NULL)
1366 return -EINVAL;
1367
1368 sel->r.left = rect->left;
1369 sel->r.top = rect->top;
1370 sel->r.width = rect->width;
1371 sel->r.height = rect->height;
1372 break;
1373 case V4L2_SEL_TGT_CROP:
1374 rect = __vfe_get_crop(line, sd_state, sel->which);
1375 if (rect == NULL)
1376 return -EINVAL;
1377
1378 sel->r = *rect;
1379 break;
1380 default:
1381 return -EINVAL;
1382 }
1383
1384 return 0;
1385 }
1386
1387 /*
1388 * vfe_set_selection - Handle set selection by pads subdev method
1389 * @sd: VFE V4L2 subdevice
1390 * @sd_state: V4L2 subdev state
1391 * @sel: pointer to v4l2 subdev selection structure
1392 *
1393 * Return -EINVAL or zero on success
1394 */
vfe_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)1395 static int vfe_set_selection(struct v4l2_subdev *sd,
1396 struct v4l2_subdev_state *sd_state,
1397 struct v4l2_subdev_selection *sel)
1398 {
1399 struct vfe_line *line = v4l2_get_subdevdata(sd);
1400 struct v4l2_rect *rect;
1401 int ret;
1402
1403 if (line->id != VFE_LINE_PIX)
1404 return -EINVAL;
1405
1406 if (sel->target == V4L2_SEL_TGT_COMPOSE &&
1407 sel->pad == MSM_VFE_PAD_SINK) {
1408 struct v4l2_subdev_selection crop = { 0 };
1409
1410 rect = __vfe_get_compose(line, sd_state, sel->which);
1411 if (rect == NULL)
1412 return -EINVAL;
1413
1414 vfe_try_compose(line, sd_state, &sel->r, sel->which);
1415 *rect = sel->r;
1416
1417 /* Reset source crop selection */
1418 crop.which = sel->which;
1419 crop.pad = MSM_VFE_PAD_SRC;
1420 crop.target = V4L2_SEL_TGT_CROP;
1421 crop.r = *rect;
1422 ret = vfe_set_selection(sd, sd_state, &crop);
1423 } else if (sel->target == V4L2_SEL_TGT_CROP &&
1424 sel->pad == MSM_VFE_PAD_SRC) {
1425 struct v4l2_subdev_format fmt = { 0 };
1426
1427 rect = __vfe_get_crop(line, sd_state, sel->which);
1428 if (rect == NULL)
1429 return -EINVAL;
1430
1431 vfe_try_crop(line, sd_state, &sel->r, sel->which);
1432 *rect = sel->r;
1433
1434 /* Reset source pad format width and height */
1435 fmt.which = sel->which;
1436 fmt.pad = MSM_VFE_PAD_SRC;
1437 ret = vfe_get_format(sd, sd_state, &fmt);
1438 if (ret < 0)
1439 return ret;
1440
1441 fmt.format.width = rect->width;
1442 fmt.format.height = rect->height;
1443 ret = vfe_set_format(sd, sd_state, &fmt);
1444 } else {
1445 ret = -EINVAL;
1446 }
1447
1448 return ret;
1449 }
1450
1451 /*
1452 * vfe_init_formats - Initialize formats on all pads
1453 * @sd: VFE V4L2 subdevice
1454 * @fh: V4L2 subdev file handle
1455 *
1456 * Initialize all pad formats with default values.
1457 *
1458 * Return 0 on success or a negative error code otherwise
1459 */
vfe_init_formats(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)1460 static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1461 {
1462 struct v4l2_subdev_format format = {
1463 .pad = MSM_VFE_PAD_SINK,
1464 .which = fh ? V4L2_SUBDEV_FORMAT_TRY :
1465 V4L2_SUBDEV_FORMAT_ACTIVE,
1466 .format = {
1467 .code = MEDIA_BUS_FMT_UYVY8_1X16,
1468 .width = 1920,
1469 .height = 1080
1470 }
1471 };
1472
1473 return vfe_set_format(sd, fh ? fh->state : NULL, &format);
1474 }
1475
1476 /*
1477 * msm_vfe_subdev_init - Initialize VFE device structure and resources
1478 * @vfe: VFE device
1479 * @res: VFE module resources table
1480 *
1481 * Return 0 on success or a negative error code otherwise
1482 */
msm_vfe_subdev_init(struct camss * camss,struct vfe_device * vfe,const struct camss_subdev_resources * res,u8 id)1483 int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
1484 const struct camss_subdev_resources *res, u8 id)
1485 {
1486 struct device *dev = camss->dev;
1487 struct platform_device *pdev = to_platform_device(dev);
1488 int i, j;
1489 int ret;
1490
1491 if (!res->vfe.line_num)
1492 return -EINVAL;
1493
1494 vfe->res = &res->vfe;
1495 vfe->res->hw_ops->subdev_init(dev, vfe);
1496
1497 /* Power domain */
1498
1499 if (res->vfe.pd_name) {
1500 vfe->genpd = dev_pm_domain_attach_by_name(camss->dev,
1501 res->vfe.pd_name);
1502 if (IS_ERR(vfe->genpd)) {
1503 ret = PTR_ERR(vfe->genpd);
1504 return ret;
1505 }
1506 }
1507
1508 if (!vfe->genpd && res->vfe.has_pd) {
1509 /*
1510 * Legacy magic index.
1511 * Requires
1512 * power-domain = <VFE_X>,
1513 * <VFE_Y>,
1514 * <TITAN_TOP>
1515 * id must correspondng to the index of the VFE which must
1516 * come before the TOP GDSC. VFE Lite has no individually
1517 * collapasible domain which is why id < vfe_num is a valid
1518 * check.
1519 */
1520 vfe->genpd = dev_pm_domain_attach_by_id(camss->dev, id);
1521 if (IS_ERR(vfe->genpd))
1522 return PTR_ERR(vfe->genpd);
1523 }
1524
1525 /* Memory */
1526
1527 vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);
1528 if (IS_ERR(vfe->base)) {
1529 dev_err(dev, "could not map memory\n");
1530 return PTR_ERR(vfe->base);
1531 }
1532
1533 /* Interrupt */
1534
1535 ret = platform_get_irq_byname(pdev, res->interrupt[0]);
1536 if (ret < 0)
1537 return ret;
1538
1539 vfe->irq = ret;
1540 snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d",
1541 dev_name(dev), MSM_VFE_NAME, id);
1542 ret = devm_request_irq(dev, vfe->irq, vfe->res->hw_ops->isr,
1543 IRQF_TRIGGER_RISING, vfe->irq_name, vfe);
1544 if (ret < 0) {
1545 dev_err(dev, "request_irq failed: %d\n", ret);
1546 return ret;
1547 }
1548
1549 /* Clocks */
1550
1551 vfe->nclocks = 0;
1552 while (res->clock[vfe->nclocks])
1553 vfe->nclocks++;
1554
1555 vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock),
1556 GFP_KERNEL);
1557 if (!vfe->clock)
1558 return -ENOMEM;
1559
1560 for (i = 0; i < vfe->nclocks; i++) {
1561 struct camss_clock *clock = &vfe->clock[i];
1562
1563 clock->clk = devm_clk_get(dev, res->clock[i]);
1564 if (IS_ERR(clock->clk))
1565 return PTR_ERR(clock->clk);
1566
1567 clock->name = res->clock[i];
1568
1569 clock->nfreqs = 0;
1570 while (res->clock_rate[i][clock->nfreqs])
1571 clock->nfreqs++;
1572
1573 if (!clock->nfreqs) {
1574 clock->freq = NULL;
1575 continue;
1576 }
1577
1578 clock->freq = devm_kcalloc(dev,
1579 clock->nfreqs,
1580 sizeof(*clock->freq),
1581 GFP_KERNEL);
1582 if (!clock->freq)
1583 return -ENOMEM;
1584
1585 for (j = 0; j < clock->nfreqs; j++)
1586 clock->freq[j] = res->clock_rate[i][j];
1587 }
1588
1589 mutex_init(&vfe->power_lock);
1590 vfe->power_count = 0;
1591
1592 mutex_init(&vfe->stream_lock);
1593 vfe->stream_count = 0;
1594
1595 spin_lock_init(&vfe->output_lock);
1596
1597 vfe->camss = camss;
1598 vfe->id = id;
1599 vfe->reg_update = 0;
1600
1601 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
1602 struct vfe_line *l = &vfe->line[i];
1603
1604 l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1605 l->video_out.camss = camss;
1606 l->id = i;
1607 init_completion(&l->output.sof);
1608 init_completion(&l->output.reg_update);
1609
1610 if (i == VFE_LINE_PIX) {
1611 l->nformats = res->vfe.formats_pix->nformats;
1612 l->formats = res->vfe.formats_pix->formats;
1613 } else {
1614 l->nformats = res->vfe.formats_rdi->nformats;
1615 l->formats = res->vfe.formats_rdi->formats;
1616 }
1617 }
1618
1619 init_completion(&vfe->reset_complete);
1620 init_completion(&vfe->halt_complete);
1621
1622 return 0;
1623 }
1624
1625 /*
1626 * msm_vfe_genpd_cleanup - Cleanup VFE genpd linkages
1627 * @vfe: VFE device
1628 */
msm_vfe_genpd_cleanup(struct vfe_device * vfe)1629 void msm_vfe_genpd_cleanup(struct vfe_device *vfe)
1630 {
1631 if (vfe->genpd_link)
1632 device_link_del(vfe->genpd_link);
1633
1634 if (vfe->genpd)
1635 dev_pm_domain_detach(vfe->genpd, true);
1636 }
1637
1638 /*
1639 * vfe_link_setup - Setup VFE connections
1640 * @entity: Pointer to media entity structure
1641 * @local: Pointer to local pad
1642 * @remote: Pointer to remote pad
1643 * @flags: Link flags
1644 *
1645 * Return 0 on success
1646 */
vfe_link_setup(struct media_entity * entity,const struct media_pad * local,const struct media_pad * remote,u32 flags)1647 static int vfe_link_setup(struct media_entity *entity,
1648 const struct media_pad *local,
1649 const struct media_pad *remote, u32 flags)
1650 {
1651 if (flags & MEDIA_LNK_FL_ENABLED)
1652 if (media_pad_remote_pad_first(local))
1653 return -EBUSY;
1654
1655 return 0;
1656 }
1657
1658 static const struct v4l2_subdev_core_ops vfe_core_ops = {
1659 .s_power = vfe_set_power,
1660 };
1661
1662 static const struct v4l2_subdev_video_ops vfe_video_ops = {
1663 .s_stream = vfe_set_stream,
1664 };
1665
1666 static const struct v4l2_subdev_pad_ops vfe_pad_ops = {
1667 .enum_mbus_code = vfe_enum_mbus_code,
1668 .enum_frame_size = vfe_enum_frame_size,
1669 .get_fmt = vfe_get_format,
1670 .set_fmt = vfe_set_format,
1671 .get_selection = vfe_get_selection,
1672 .set_selection = vfe_set_selection,
1673 };
1674
1675 static const struct v4l2_subdev_ops vfe_v4l2_ops = {
1676 .core = &vfe_core_ops,
1677 .video = &vfe_video_ops,
1678 .pad = &vfe_pad_ops,
1679 };
1680
1681 static const struct v4l2_subdev_internal_ops vfe_v4l2_internal_ops = {
1682 .open = vfe_init_formats,
1683 };
1684
1685 static const struct media_entity_operations vfe_media_ops = {
1686 .link_setup = vfe_link_setup,
1687 .link_validate = v4l2_subdev_link_validate,
1688 };
1689
vfe_bpl_align(struct vfe_device * vfe)1690 static int vfe_bpl_align(struct vfe_device *vfe)
1691 {
1692 int ret = 8;
1693
1694 switch (vfe->camss->res->version) {
1695 case CAMSS_845:
1696 case CAMSS_8250:
1697 case CAMSS_8280XP:
1698 ret = 16;
1699 break;
1700 default:
1701 break;
1702 }
1703
1704 return ret;
1705 }
1706
1707 /*
1708 * msm_vfe_register_entities - Register subdev node for VFE module
1709 * @vfe: VFE device
1710 * @v4l2_dev: V4L2 device
1711 *
1712 * Initialize and register a subdev node for the VFE module. Then
1713 * call msm_video_register() to register the video device node which
1714 * will be connected to this subdev node. Then actually create the
1715 * media link between them.
1716 *
1717 * Return 0 on success or a negative error code otherwise
1718 */
msm_vfe_register_entities(struct vfe_device * vfe,struct v4l2_device * v4l2_dev)1719 int msm_vfe_register_entities(struct vfe_device *vfe,
1720 struct v4l2_device *v4l2_dev)
1721 {
1722 struct device *dev = vfe->camss->dev;
1723 struct v4l2_subdev *sd;
1724 struct media_pad *pads;
1725 struct camss_video *video_out;
1726 int ret;
1727 int i;
1728
1729 for (i = 0; i < vfe->res->line_num; i++) {
1730 char name[32];
1731
1732 sd = &vfe->line[i].subdev;
1733 pads = vfe->line[i].pads;
1734 video_out = &vfe->line[i].video_out;
1735
1736 v4l2_subdev_init(sd, &vfe_v4l2_ops);
1737 sd->internal_ops = &vfe_v4l2_internal_ops;
1738 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1739 if (i == VFE_LINE_PIX)
1740 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s",
1741 MSM_VFE_NAME, vfe->id, "pix");
1742 else
1743 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s%d",
1744 MSM_VFE_NAME, vfe->id, "rdi", i);
1745
1746 v4l2_set_subdevdata(sd, &vfe->line[i]);
1747
1748 ret = vfe_init_formats(sd, NULL);
1749 if (ret < 0) {
1750 dev_err(dev, "Failed to init format: %d\n", ret);
1751 goto error_init;
1752 }
1753
1754 pads[MSM_VFE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1755 pads[MSM_VFE_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
1756
1757 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1758 sd->entity.ops = &vfe_media_ops;
1759 ret = media_entity_pads_init(&sd->entity, MSM_VFE_PADS_NUM,
1760 pads);
1761 if (ret < 0) {
1762 dev_err(dev, "Failed to init media entity: %d\n", ret);
1763 goto error_init;
1764 }
1765
1766 ret = v4l2_device_register_subdev(v4l2_dev, sd);
1767 if (ret < 0) {
1768 dev_err(dev, "Failed to register subdev: %d\n", ret);
1769 goto error_reg_subdev;
1770 }
1771
1772 video_out->ops = &vfe->video_ops;
1773 video_out->bpl_alignment = vfe_bpl_align(vfe);
1774 video_out->line_based = 0;
1775 if (i == VFE_LINE_PIX) {
1776 video_out->bpl_alignment = 16;
1777 video_out->line_based = 1;
1778 }
1779
1780 video_out->nformats = vfe->line[i].nformats;
1781 video_out->formats = vfe->line[i].formats;
1782
1783 snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d",
1784 MSM_VFE_NAME, vfe->id, "video", i);
1785 ret = msm_video_register(video_out, v4l2_dev, name);
1786 if (ret < 0) {
1787 dev_err(dev, "Failed to register video node: %d\n",
1788 ret);
1789 goto error_reg_video;
1790 }
1791
1792 ret = media_create_pad_link(
1793 &sd->entity, MSM_VFE_PAD_SRC,
1794 &video_out->vdev.entity, 0,
1795 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1796 if (ret < 0) {
1797 dev_err(dev, "Failed to link %s->%s entities: %d\n",
1798 sd->entity.name, video_out->vdev.entity.name,
1799 ret);
1800 goto error_link;
1801 }
1802 }
1803
1804 return 0;
1805
1806 error_link:
1807 msm_video_unregister(video_out);
1808
1809 error_reg_video:
1810 v4l2_device_unregister_subdev(sd);
1811
1812 error_reg_subdev:
1813 media_entity_cleanup(&sd->entity);
1814
1815 error_init:
1816 for (i--; i >= 0; i--) {
1817 sd = &vfe->line[i].subdev;
1818 video_out = &vfe->line[i].video_out;
1819
1820 msm_video_unregister(video_out);
1821 v4l2_device_unregister_subdev(sd);
1822 media_entity_cleanup(&sd->entity);
1823 }
1824
1825 return ret;
1826 }
1827
1828 /*
1829 * msm_vfe_unregister_entities - Unregister VFE module subdev node
1830 * @vfe: VFE device
1831 */
msm_vfe_unregister_entities(struct vfe_device * vfe)1832 void msm_vfe_unregister_entities(struct vfe_device *vfe)
1833 {
1834 int i;
1835
1836 mutex_destroy(&vfe->power_lock);
1837 mutex_destroy(&vfe->stream_lock);
1838
1839 for (i = 0; i < vfe->res->line_num; i++) {
1840 struct v4l2_subdev *sd = &vfe->line[i].subdev;
1841 struct camss_video *video_out = &vfe->line[i].video_out;
1842
1843 msm_video_unregister(video_out);
1844 v4l2_device_unregister_subdev(sd);
1845 media_entity_cleanup(&sd->entity);
1846 }
1847 }
1848
vfe_is_lite(struct vfe_device * vfe)1849 bool vfe_is_lite(struct vfe_device *vfe)
1850 {
1851 return vfe->camss->res->vfe_res[vfe->id].vfe.is_lite;
1852 }
1853