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