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