1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Medifield PNW Camera Imaging ISP subsystem.
4  *
5  * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version
9  * 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  *
17  */
18 
19 #include <media/v4l2-event.h>
20 #include <media/v4l2-mediabus.h>
21 #include "atomisp_cmd.h"
22 #include "atomisp_internal.h"
23 #include "atomisp-regs.h"
24 
25 static struct
26 v4l2_mbus_framefmt *__csi2_get_format(struct atomisp_mipi_csi2_device *csi2,
27 				      struct v4l2_subdev_state *sd_state,
28 				      enum v4l2_subdev_format_whence which,
29 				      unsigned int pad)
30 {
31 	if (which == V4L2_SUBDEV_FORMAT_TRY)
32 		return v4l2_subdev_get_try_format(&csi2->subdev, sd_state,
33 						  pad);
34 	else
35 		return &csi2->formats[pad];
36 }
37 
38 /*
39  * csi2_enum_mbus_code - Handle pixel format enumeration
40  * @sd     : pointer to v4l2 subdev structure
41  * @fh     : V4L2 subdev file handle
42  * @code   : pointer to v4l2_subdev_pad_mbus_code_enum structure
43  * return -EINVAL or zero on success
44  */
45 static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
46 			       struct v4l2_subdev_state *sd_state,
47 			       struct v4l2_subdev_mbus_code_enum *code)
48 {
49 	const struct atomisp_in_fmt_conv *ic = atomisp_in_fmt_conv;
50 	unsigned int i = 0;
51 
52 	while (ic->code) {
53 		if (i == code->index) {
54 			code->code = ic->code;
55 			return 0;
56 		}
57 		i++, ic++;
58 	}
59 
60 	return -EINVAL;
61 }
62 
63 /*
64  * csi2_get_format - Handle get format by pads subdev method
65  * @sd : pointer to v4l2 subdev structure
66  * @fh : V4L2 subdev file handle
67  * @pad: pad num
68  * @fmt: pointer to v4l2 format structure
69  * return -EINVAL or zero on success
70  */
71 static int csi2_get_format(struct v4l2_subdev *sd,
72 			   struct v4l2_subdev_state *sd_state,
73 			   struct v4l2_subdev_format *fmt)
74 {
75 	struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
76 	struct v4l2_mbus_framefmt *format;
77 
78 	format = __csi2_get_format(csi2, sd_state, fmt->which, fmt->pad);
79 
80 	fmt->format = *format;
81 
82 	return 0;
83 }
84 
85 int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd,
86 			  struct v4l2_subdev_state *sd_state,
87 			  unsigned int which, uint16_t pad,
88 			  struct v4l2_mbus_framefmt *ffmt)
89 {
90 	struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
91 	struct v4l2_mbus_framefmt *actual_ffmt = __csi2_get_format(csi2,
92 								   sd_state,
93 								   which, pad);
94 
95 	if (pad == CSI2_PAD_SINK) {
96 		const struct atomisp_in_fmt_conv *ic;
97 		struct v4l2_mbus_framefmt tmp_ffmt;
98 
99 		ic = atomisp_find_in_fmt_conv(ffmt->code);
100 		if (ic)
101 			actual_ffmt->code = ic->code;
102 		else
103 			actual_ffmt->code = atomisp_in_fmt_conv[0].code;
104 
105 		actual_ffmt->width = clamp_t(u32, ffmt->width,
106 					     ATOM_ISP_MIN_WIDTH,
107 					     ATOM_ISP_MAX_WIDTH);
108 		actual_ffmt->height = clamp_t(u32, ffmt->height,
109 					      ATOM_ISP_MIN_HEIGHT,
110 					      ATOM_ISP_MAX_HEIGHT);
111 
112 		tmp_ffmt = *ffmt = *actual_ffmt;
113 
114 		return atomisp_csi2_set_ffmt(sd, sd_state, which,
115 					     CSI2_PAD_SOURCE,
116 					     &tmp_ffmt);
117 	}
118 
119 	/* FIXME: DPCM decompression */
120 	*actual_ffmt = *ffmt = *__csi2_get_format(csi2, sd_state, which,
121 						  CSI2_PAD_SINK);
122 
123 	return 0;
124 }
125 
126 /*
127  * csi2_set_format - Handle set format by pads subdev method
128  * @sd : pointer to v4l2 subdev structure
129  * @fh : V4L2 subdev file handle
130  * @pad: pad num
131  * @fmt: pointer to v4l2 format structure
132  * return -EINVAL or zero on success
133  */
134 static int csi2_set_format(struct v4l2_subdev *sd,
135 			   struct v4l2_subdev_state *sd_state,
136 			   struct v4l2_subdev_format *fmt)
137 {
138 	return atomisp_csi2_set_ffmt(sd, sd_state, fmt->which, fmt->pad,
139 				     &fmt->format);
140 }
141 
142 /*
143  * csi2_set_stream - Enable/Disable streaming on the CSI2 module
144  * @sd: ISP CSI2 V4L2 subdevice
145  * @enable: Enable/disable stream (1/0)
146  *
147  * Return 0 on success or a negative error code otherwise.
148  */
149 static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
150 {
151 	return 0;
152 }
153 
154 /* subdev core operations */
155 static const struct v4l2_subdev_core_ops csi2_core_ops = {
156 };
157 
158 /* subdev video operations */
159 static const struct v4l2_subdev_video_ops csi2_video_ops = {
160 	.s_stream = csi2_set_stream,
161 };
162 
163 /* subdev pad operations */
164 static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
165 	.enum_mbus_code = csi2_enum_mbus_code,
166 	.get_fmt = csi2_get_format,
167 	.set_fmt = csi2_set_format,
168 	.link_validate = v4l2_subdev_link_validate_default,
169 };
170 
171 /* subdev operations */
172 static const struct v4l2_subdev_ops csi2_ops = {
173 	.core = &csi2_core_ops,
174 	.video = &csi2_video_ops,
175 	.pad = &csi2_pad_ops,
176 };
177 
178 /* media operations */
179 static const struct media_entity_operations csi2_media_ops = {
180 	.link_validate = v4l2_subdev_link_validate,
181 };
182 
183 /*
184  * ispcsi2_init_entities - Initialize subdev and media entity.
185  * @csi2: Pointer to ispcsi2 structure.
186  * return -ENOMEM or zero on success
187  */
188 static int mipi_csi2_init_entities(struct atomisp_mipi_csi2_device *csi2,
189 				   int port)
190 {
191 	struct v4l2_subdev *sd = &csi2->subdev;
192 	struct media_pad *pads = csi2->pads;
193 	struct media_entity *me = &sd->entity;
194 	int ret;
195 
196 	v4l2_subdev_init(sd, &csi2_ops);
197 	snprintf(sd->name, sizeof(sd->name), "ATOM ISP CSI2-port%d", port);
198 
199 	v4l2_set_subdevdata(sd, csi2);
200 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
201 
202 	pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
203 	pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
204 
205 	me->ops = &csi2_media_ops;
206 	me->function = MEDIA_ENT_F_VID_IF_BRIDGE;
207 	ret = media_entity_pads_init(me, CSI2_PADS_NUM, pads);
208 	if (ret < 0)
209 		return ret;
210 
211 	csi2->formats[CSI2_PAD_SINK].code = atomisp_in_fmt_conv[0].code;
212 	csi2->formats[CSI2_PAD_SOURCE].code = atomisp_in_fmt_conv[0].code;
213 
214 	return 0;
215 }
216 
217 void
218 atomisp_mipi_csi2_unregister_entities(struct atomisp_mipi_csi2_device *csi2)
219 {
220 	media_entity_cleanup(&csi2->subdev.entity);
221 	v4l2_device_unregister_subdev(&csi2->subdev);
222 }
223 
224 int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2,
225 					struct v4l2_device *vdev)
226 {
227 	int ret;
228 
229 	/* Register the subdev and video nodes. */
230 	ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
231 	if (ret < 0)
232 		goto error;
233 
234 	return 0;
235 
236 error:
237 	atomisp_mipi_csi2_unregister_entities(csi2);
238 	return ret;
239 }
240 
241 static const int LIMIT_SHIFT = 6;	/* Limit numeric range into 31 bits */
242 
243 static int
244 atomisp_csi2_configure_calc(const short int coeffs[2], int mipi_freq, int def)
245 {
246 	/* Delay counter accuracy, 1/0.0625 for ANN/CHT, 1/0.125 for BXT */
247 	static const int accinv = 16;		/* 1 / COUNT_ACC */
248 	int r;
249 
250 	if (mipi_freq >> LIMIT_SHIFT <= 0)
251 		return def;
252 
253 	r = accinv * coeffs[1] * (500000000 >> LIMIT_SHIFT);
254 	r /= mipi_freq >> LIMIT_SHIFT;
255 	r += accinv * coeffs[0];
256 
257 	return r;
258 }
259 
260 static void atomisp_csi2_configure_isp2401(struct atomisp_sub_device *asd)
261 {
262 	/*
263 	 * The ISP2401 new input system CSI2+ receiver has several
264 	 * parameters affecting the receiver timings. These depend
265 	 * on the MIPI bus frequency F in Hz (sensor transmitter rate)
266 	 * as follows:
267 	 *	register value = (A/1e9 + B * UI) / COUNT_ACC
268 	 * where
269 	 *	UI = 1 / (2 * F) in seconds
270 	 *	COUNT_ACC = counter accuracy in seconds
271 	 *	For ANN and CHV, COUNT_ACC = 0.0625 ns
272 	 *	For BXT,  COUNT_ACC = 0.125 ns
273 	 * A and B are coefficients from the table below,
274 	 * depending whether the register minimum or maximum value is
275 	 * calculated.
276 	 *				       Minimum     Maximum
277 	 * Clock lane			       A     B     A     B
278 	 * reg_rx_csi_dly_cnt_termen_clane     0     0    38     0
279 	 * reg_rx_csi_dly_cnt_settle_clane    95    -8   300   -16
280 	 * Data lanes
281 	 * reg_rx_csi_dly_cnt_termen_dlane0    0     0    35     4
282 	 * reg_rx_csi_dly_cnt_settle_dlane0   85    -2   145    -6
283 	 * reg_rx_csi_dly_cnt_termen_dlane1    0     0    35     4
284 	 * reg_rx_csi_dly_cnt_settle_dlane1   85    -2   145    -6
285 	 * reg_rx_csi_dly_cnt_termen_dlane2    0     0    35     4
286 	 * reg_rx_csi_dly_cnt_settle_dlane2   85    -2   145    -6
287 	 * reg_rx_csi_dly_cnt_termen_dlane3    0     0    35     4
288 	 * reg_rx_csi_dly_cnt_settle_dlane3   85    -2   145    -6
289 	 *
290 	 * We use the minimum values in the calculations below.
291 	 */
292 	static const short int coeff_clk_termen[] = { 0, 0 };
293 	static const short int coeff_clk_settle[] = { 95, -8 };
294 	static const short int coeff_dat_termen[] = { 0, 0 };
295 	static const short int coeff_dat_settle[] = { 85, -2 };
296 	static const int TERMEN_DEFAULT		  = 0 * 0;
297 	static const int SETTLE_DEFAULT		  = 0x480;
298 
299 	static const hrt_address csi2_port_base[] = {
300 		[ATOMISP_CAMERA_PORT_PRIMARY]     = CSI2_PORT_A_BASE,
301 		[ATOMISP_CAMERA_PORT_SECONDARY]   = CSI2_PORT_B_BASE,
302 		[ATOMISP_CAMERA_PORT_TERTIARY]    = CSI2_PORT_C_BASE,
303 	};
304 	/* Number of lanes on each port, excluding clock lane */
305 	static const unsigned char csi2_port_lanes[] = {
306 		[ATOMISP_CAMERA_PORT_PRIMARY]     = 4,
307 		[ATOMISP_CAMERA_PORT_SECONDARY]   = 2,
308 		[ATOMISP_CAMERA_PORT_TERTIARY]    = 2,
309 	};
310 	static const hrt_address csi2_lane_base[] = {
311 		CSI2_LANE_CL_BASE,
312 		CSI2_LANE_D0_BASE,
313 		CSI2_LANE_D1_BASE,
314 		CSI2_LANE_D2_BASE,
315 		CSI2_LANE_D3_BASE,
316 	};
317 
318 	int clk_termen;
319 	int clk_settle;
320 	int dat_termen;
321 	int dat_settle;
322 
323 	struct v4l2_control ctrl;
324 	struct atomisp_device *isp = asd->isp;
325 	struct camera_mipi_info *mipi_info;
326 	int mipi_freq = 0;
327 	enum atomisp_camera_port port;
328 
329 	int n;
330 
331 	mipi_info = atomisp_to_sensor_mipi_info(
332 			isp->inputs[asd->input_curr].camera);
333 	port = mipi_info->port;
334 
335 	ctrl.id = V4L2_CID_LINK_FREQ;
336 	if (v4l2_g_ctrl
337 	    (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0)
338 		mipi_freq = ctrl.value;
339 
340 	clk_termen = atomisp_csi2_configure_calc(coeff_clk_termen, mipi_freq,
341 						 TERMEN_DEFAULT);
342 	clk_settle = atomisp_csi2_configure_calc(coeff_clk_settle, mipi_freq,
343 						 SETTLE_DEFAULT);
344 	dat_termen = atomisp_csi2_configure_calc(coeff_dat_termen, mipi_freq,
345 						 TERMEN_DEFAULT);
346 	dat_settle = atomisp_csi2_configure_calc(coeff_dat_settle, mipi_freq,
347 						 SETTLE_DEFAULT);
348 
349 	for (n = 0; n < csi2_port_lanes[port] + 1; n++) {
350 		hrt_address base = csi2_port_base[port] + csi2_lane_base[n];
351 
352 		atomisp_css2_hw_store_32(base + CSI2_REG_RX_CSI_DLY_CNT_TERMEN,
353 					 n == 0 ? clk_termen : dat_termen);
354 		atomisp_css2_hw_store_32(base + CSI2_REG_RX_CSI_DLY_CNT_SETTLE,
355 					 n == 0 ? clk_settle : dat_settle);
356 	}
357 }
358 
359 void atomisp_csi2_configure(struct atomisp_sub_device *asd)
360 {
361 	if (IS_HWREVISION(asd->isp, ATOMISP_HW_REVISION_ISP2401))
362 		atomisp_csi2_configure_isp2401(asd);
363 }
364 
365 /*
366  * atomisp_mipi_csi2_cleanup - Routine for module driver cleanup
367  */
368 void atomisp_mipi_csi2_cleanup(struct atomisp_device *isp)
369 {
370 }
371 
372 int atomisp_mipi_csi2_init(struct atomisp_device *isp)
373 {
374 	struct atomisp_mipi_csi2_device *csi2_port;
375 	unsigned int i;
376 	int ret;
377 
378 	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
379 		csi2_port = &isp->csi2_port[i];
380 		csi2_port->isp = isp;
381 		ret = mipi_csi2_init_entities(csi2_port, i);
382 		if (ret < 0)
383 			goto fail;
384 	}
385 
386 	return 0;
387 
388 fail:
389 	atomisp_mipi_csi2_cleanup(isp);
390 	return ret;
391 }
392