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