staging: media: omap4iss: Fixes missing blank line warning.
[deliverable/linux.git] / drivers / staging / media / omap4iss / iss_csi2.c
CommitLineData
b4a0477c
SA
1/*
2 * TI OMAP4 ISS V4L2 Driver - CSI PHY module
3 *
4 * Copyright (C) 2012 Texas Instruments, Inc.
5 *
6 * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/delay.h>
15#include <media/v4l2-common.h>
16#include <linux/v4l2-mediabus.h>
17#include <linux/mm.h>
18
19#include "iss.h"
20#include "iss_regs.h"
21#include "iss_csi2.h"
22
23/*
24 * csi2_if_enable - Enable CSI2 Receiver interface.
25 * @enable: enable flag
26 *
27 */
28static void csi2_if_enable(struct iss_csi2_device *csi2, u8 enable)
29{
30 struct iss_csi2_ctrl_cfg *currctrl = &csi2->ctrl;
31
97059524
LP
32 iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTRL, CSI2_CTRL_IF_EN,
33 enable ? CSI2_CTRL_IF_EN : 0);
b4a0477c
SA
34
35 currctrl->if_enable = enable;
36}
37
38/*
39 * csi2_recv_config - CSI2 receiver module configuration.
40 * @currctrl: iss_csi2_ctrl_cfg structure
41 *
42 */
43static void csi2_recv_config(struct iss_csi2_device *csi2,
44 struct iss_csi2_ctrl_cfg *currctrl)
45{
46 u32 reg = 0;
47
48 if (currctrl->frame_mode)
49 reg |= CSI2_CTRL_FRAME;
50 else
51 reg &= ~CSI2_CTRL_FRAME;
52
53 if (currctrl->vp_clk_enable)
54 reg |= CSI2_CTRL_VP_CLK_EN;
55 else
56 reg &= ~CSI2_CTRL_VP_CLK_EN;
57
58 if (currctrl->vp_only_enable)
59 reg |= CSI2_CTRL_VP_ONLY_EN;
60 else
61 reg &= ~CSI2_CTRL_VP_ONLY_EN;
62
63 reg &= ~CSI2_CTRL_VP_OUT_CTRL_MASK;
64 reg |= currctrl->vp_out_ctrl << CSI2_CTRL_VP_OUT_CTRL_SHIFT;
65
66 if (currctrl->ecc_enable)
67 reg |= CSI2_CTRL_ECC_EN;
68 else
69 reg &= ~CSI2_CTRL_ECC_EN;
70
71 /*
72 * Set MFlag assertion boundaries to:
73 * Low: 4/8 of FIFO size
74 * High: 6/8 of FIFO size
75 */
76 reg &= ~(CSI2_CTRL_MFLAG_LEVH_MASK | CSI2_CTRL_MFLAG_LEVL_MASK);
77 reg |= (2 << CSI2_CTRL_MFLAG_LEVH_SHIFT) |
78 (4 << CSI2_CTRL_MFLAG_LEVL_SHIFT);
79
80 /* Generation of 16x64-bit bursts (Recommended) */
81 reg |= CSI2_CTRL_BURST_SIZE_EXPAND;
82
83 /* Do Non-Posted writes (Recommended) */
84 reg |= CSI2_CTRL_NON_POSTED_WRITE;
85
86 /*
87 * Enforce Little endian for all formats, including:
88 * YUV4:2:2 8-bit and YUV4:2:0 Legacy
89 */
90 reg |= CSI2_CTRL_ENDIANNESS;
91
97059524 92 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTRL, reg);
b4a0477c
SA
93}
94
95static const unsigned int csi2_input_fmts[] = {
96 V4L2_MBUS_FMT_SGRBG10_1X10,
97 V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
98 V4L2_MBUS_FMT_SRGGB10_1X10,
99 V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
100 V4L2_MBUS_FMT_SBGGR10_1X10,
101 V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
102 V4L2_MBUS_FMT_SGBRG10_1X10,
103 V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
104 V4L2_MBUS_FMT_SBGGR8_1X8,
105 V4L2_MBUS_FMT_SGBRG8_1X8,
106 V4L2_MBUS_FMT_SGRBG8_1X8,
107 V4L2_MBUS_FMT_SRGGB8_1X8,
108 V4L2_MBUS_FMT_UYVY8_1X16,
109 V4L2_MBUS_FMT_YUYV8_1X16,
110};
111
112/* To set the format on the CSI2 requires a mapping function that takes
113 * the following inputs:
114 * - 3 different formats (at this time)
115 * - 2 destinations (mem, vp+mem) (vp only handled separately)
116 * - 2 decompression options (on, off)
117 * Output should be CSI2 frame format code
118 * Array indices as follows: [format][dest][decompr]
119 * Not all combinations are valid. 0 means invalid.
120 */
121static const u16 __csi2_fmt_map[][2][2] = {
122 /* RAW10 formats */
123 {
124 /* Output to memory */
125 {
126 /* No DPCM decompression */
127 CSI2_PIX_FMT_RAW10_EXP16,
128 /* DPCM decompression */
129 0,
130 },
131 /* Output to both */
132 {
133 /* No DPCM decompression */
134 CSI2_PIX_FMT_RAW10_EXP16_VP,
135 /* DPCM decompression */
136 0,
137 },
138 },
139 /* RAW10 DPCM8 formats */
140 {
141 /* Output to memory */
142 {
143 /* No DPCM decompression */
144 CSI2_USERDEF_8BIT_DATA1,
145 /* DPCM decompression */
146 CSI2_USERDEF_8BIT_DATA1_DPCM10,
147 },
148 /* Output to both */
149 {
150 /* No DPCM decompression */
151 CSI2_PIX_FMT_RAW8_VP,
152 /* DPCM decompression */
153 CSI2_USERDEF_8BIT_DATA1_DPCM10_VP,
154 },
155 },
156 /* RAW8 formats */
157 {
158 /* Output to memory */
159 {
160 /* No DPCM decompression */
161 CSI2_PIX_FMT_RAW8,
162 /* DPCM decompression */
163 0,
164 },
165 /* Output to both */
166 {
167 /* No DPCM decompression */
168 CSI2_PIX_FMT_RAW8_VP,
169 /* DPCM decompression */
170 0,
171 },
172 },
173 /* YUV422 formats */
174 {
175 /* Output to memory */
176 {
177 /* No DPCM decompression */
178 CSI2_PIX_FMT_YUV422_8BIT,
179 /* DPCM decompression */
180 0,
181 },
182 /* Output to both */
183 {
184 /* No DPCM decompression */
185 CSI2_PIX_FMT_YUV422_8BIT_VP16,
186 /* DPCM decompression */
187 0,
188 },
189 },
190};
191
192/*
193 * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID
194 * @csi2: ISS CSI2 device
195 *
196 * Returns CSI2 physical format id
197 */
198static u16 csi2_ctx_map_format(struct iss_csi2_device *csi2)
199{
200 const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK];
201 int fmtidx, destidx;
202
203 switch (fmt->code) {
204 case V4L2_MBUS_FMT_SGRBG10_1X10:
205 case V4L2_MBUS_FMT_SRGGB10_1X10:
206 case V4L2_MBUS_FMT_SBGGR10_1X10:
207 case V4L2_MBUS_FMT_SGBRG10_1X10:
208 fmtidx = 0;
209 break;
210 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
211 case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
212 case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
213 case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
214 fmtidx = 1;
215 break;
216 case V4L2_MBUS_FMT_SBGGR8_1X8:
217 case V4L2_MBUS_FMT_SGBRG8_1X8:
218 case V4L2_MBUS_FMT_SGRBG8_1X8:
219 case V4L2_MBUS_FMT_SRGGB8_1X8:
220 fmtidx = 2;
221 break;
222 case V4L2_MBUS_FMT_UYVY8_1X16:
223 case V4L2_MBUS_FMT_YUYV8_1X16:
224 fmtidx = 3;
225 break;
226 default:
227 WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
228 fmt->code);
229 return 0;
230 }
231
232 if (!(csi2->output & CSI2_OUTPUT_IPIPEIF) &&
233 !(csi2->output & CSI2_OUTPUT_MEMORY)) {
234 /* Neither output enabled is a valid combination */
235 return CSI2_PIX_FMT_OTHERS;
236 }
237
238 /* If we need to skip frames at the beginning of the stream disable the
239 * video port to avoid sending the skipped frames to the IPIPEIF.
240 */
241 destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_IPIPEIF);
242
243 return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress];
244}
245
246/*
247 * csi2_set_outaddr - Set memory address to save output image
248 * @csi2: Pointer to ISS CSI2a device.
249 * @addr: 32-bit memory address aligned on 32 byte boundary.
250 *
251 * Sets the memory address where the output will be saved.
252 *
253 * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
254 * boundary.
255 */
256static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr)
257{
258 struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[0];
259
260 ctx->ping_addr = addr;
261 ctx->pong_addr = addr;
97059524
LP
262 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum),
263 ctx->ping_addr);
264 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum),
265 ctx->pong_addr);
b4a0477c
SA
266}
267
268/*
269 * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should
270 * be enabled by CSI2.
271 * @format_id: mapped format id
272 *
273 */
274static inline int is_usr_def_mapping(u32 format_id)
275{
3c4ee96b 276 return (format_id & 0xf0) == 0x40 ? 1 : 0;
b4a0477c
SA
277}
278
279/*
280 * csi2_ctx_enable - Enable specified CSI2 context
281 * @ctxnum: Context number, valid between 0 and 7 values.
282 * @enable: enable
283 *
284 */
285static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable)
286{
287 struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
288 u32 reg;
289
97059524 290 reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum));
b4a0477c
SA
291
292 if (enable) {
293 unsigned int skip = 0;
294
295 if (csi2->frame_skip)
296 skip = csi2->frame_skip;
297 else if (csi2->output & CSI2_OUTPUT_MEMORY)
298 skip = 1;
299
300 reg &= ~CSI2_CTX_CTRL1_COUNT_MASK;
301 reg |= CSI2_CTX_CTRL1_COUNT_UNLOCK
302 | (skip << CSI2_CTX_CTRL1_COUNT_SHIFT)
303 | CSI2_CTX_CTRL1_CTX_EN;
304 } else {
305 reg &= ~CSI2_CTX_CTRL1_CTX_EN;
306 }
307
97059524 308 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum), reg);
b4a0477c
SA
309 ctx->enabled = enable;
310}
311
312/*
313 * csi2_ctx_config - CSI2 context configuration.
314 * @ctx: context configuration
315 *
316 */
317static void csi2_ctx_config(struct iss_csi2_device *csi2,
318 struct iss_csi2_ctx_cfg *ctx)
319{
aecfa5af 320 u32 reg = 0;
b4a0477c
SA
321
322 /* Set up CSI2_CTx_CTRL1 */
323 if (ctx->eof_enabled)
324 reg = CSI2_CTX_CTRL1_EOF_EN;
325
326 if (ctx->eol_enabled)
327 reg |= CSI2_CTX_CTRL1_EOL_EN;
328
329 if (ctx->checksum_enabled)
330 reg |= CSI2_CTX_CTRL1_CS_EN;
331
97059524 332 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctx->ctxnum), reg);
b4a0477c
SA
333
334 /* Set up CSI2_CTx_CTRL2 */
335 reg = ctx->virtual_id << CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
336 reg |= ctx->format_id << CSI2_CTX_CTRL2_FORMAT_SHIFT;
337
338 if (ctx->dpcm_decompress && ctx->dpcm_predictor)
339 reg |= CSI2_CTX_CTRL2_DPCM_PRED;
340
341 if (is_usr_def_mapping(ctx->format_id))
342 reg |= 2 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT;
343
97059524 344 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL2(ctx->ctxnum), reg);
b4a0477c
SA
345
346 /* Set up CSI2_CTx_CTRL3 */
97059524
LP
347 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL3(ctx->ctxnum),
348 ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT);
b4a0477c
SA
349
350 /* Set up CSI2_CTx_DAT_OFST */
97059524
LP
351 iss_reg_update(csi2->iss, csi2->regs1, CSI2_CTX_DAT_OFST(ctx->ctxnum),
352 CSI2_CTX_DAT_OFST_MASK, ctx->data_offset);
b4a0477c 353
97059524
LP
354 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PING_ADDR(ctx->ctxnum),
355 ctx->ping_addr);
356 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_PONG_ADDR(ctx->ctxnum),
357 ctx->pong_addr);
b4a0477c
SA
358}
359
360/*
361 * csi2_timing_config - CSI2 timing configuration.
362 * @timing: csi2_timing_cfg structure
363 */
364static void csi2_timing_config(struct iss_csi2_device *csi2,
365 struct iss_csi2_timing_cfg *timing)
366{
367 u32 reg;
368
97059524 369 reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_TIMING);
b4a0477c
SA
370
371 if (timing->force_rx_mode)
372 reg |= CSI2_TIMING_FORCE_RX_MODE_IO1;
373 else
374 reg &= ~CSI2_TIMING_FORCE_RX_MODE_IO1;
375
376 if (timing->stop_state_16x)
377 reg |= CSI2_TIMING_STOP_STATE_X16_IO1;
378 else
379 reg &= ~CSI2_TIMING_STOP_STATE_X16_IO1;
380
381 if (timing->stop_state_4x)
382 reg |= CSI2_TIMING_STOP_STATE_X4_IO1;
383 else
384 reg &= ~CSI2_TIMING_STOP_STATE_X4_IO1;
385
386 reg &= ~CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK;
387 reg |= timing->stop_state_counter <<
388 CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT;
389
97059524 390 iss_reg_write(csi2->iss, csi2->regs1, CSI2_TIMING, reg);
b4a0477c
SA
391}
392
393/*
394 * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
395 * @enable: Enable/disable CSI2 Context interrupts
396 */
397static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable)
398{
399 u32 reg = CSI2_CTX_IRQ_FE;
400 int i;
401
402 if (csi2->use_fs_irq)
403 reg |= CSI2_CTX_IRQ_FS;
404
405 for (i = 0; i < 8; i++) {
97059524
LP
406 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i),
407 reg);
b4a0477c 408 if (enable)
97059524
LP
409 iss_reg_set(csi2->iss, csi2->regs1,
410 CSI2_CTX_IRQENABLE(i), reg);
b4a0477c 411 else
97059524
LP
412 iss_reg_clr(csi2->iss, csi2->regs1,
413 CSI2_CTX_IRQENABLE(i), reg);
b4a0477c
SA
414 }
415}
416
417/*
418 * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
419 * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
420 */
421static void csi2_irq_complexio1_set(struct iss_csi2_device *csi2, int enable)
422{
423 u32 reg;
9d374b2c 424
b4a0477c
SA
425 reg = CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT |
426 CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER |
427 CSI2_COMPLEXIO_IRQ_STATEULPM5 |
428 CSI2_COMPLEXIO_IRQ_ERRCONTROL5 |
429 CSI2_COMPLEXIO_IRQ_ERRESC5 |
430 CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 |
431 CSI2_COMPLEXIO_IRQ_ERRSOTHS5 |
432 CSI2_COMPLEXIO_IRQ_STATEULPM4 |
433 CSI2_COMPLEXIO_IRQ_ERRCONTROL4 |
434 CSI2_COMPLEXIO_IRQ_ERRESC4 |
435 CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 |
436 CSI2_COMPLEXIO_IRQ_ERRSOTHS4 |
437 CSI2_COMPLEXIO_IRQ_STATEULPM3 |
438 CSI2_COMPLEXIO_IRQ_ERRCONTROL3 |
439 CSI2_COMPLEXIO_IRQ_ERRESC3 |
440 CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 |
441 CSI2_COMPLEXIO_IRQ_ERRSOTHS3 |
442 CSI2_COMPLEXIO_IRQ_STATEULPM2 |
443 CSI2_COMPLEXIO_IRQ_ERRCONTROL2 |
444 CSI2_COMPLEXIO_IRQ_ERRESC2 |
445 CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 |
446 CSI2_COMPLEXIO_IRQ_ERRSOTHS2 |
447 CSI2_COMPLEXIO_IRQ_STATEULPM1 |
448 CSI2_COMPLEXIO_IRQ_ERRCONTROL1 |
449 CSI2_COMPLEXIO_IRQ_ERRESC1 |
450 CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 |
451 CSI2_COMPLEXIO_IRQ_ERRSOTHS1;
97059524 452 iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS, reg);
b4a0477c 453 if (enable)
97059524
LP
454 iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE,
455 reg);
b4a0477c 456 else
97059524
LP
457 iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQENABLE,
458 0);
b4a0477c
SA
459}
460
461/*
462 * csi2_irq_status_set - Enables CSI2 Status IRQs.
463 * @enable: Enable/disable CSI2 Status interrupts
464 */
465static void csi2_irq_status_set(struct iss_csi2_device *csi2, int enable)
466{
467 u32 reg;
9d374b2c 468
b4a0477c
SA
469 reg = CSI2_IRQ_OCP_ERR |
470 CSI2_IRQ_SHORT_PACKET |
471 CSI2_IRQ_ECC_CORRECTION |
472 CSI2_IRQ_ECC_NO_CORRECTION |
473 CSI2_IRQ_COMPLEXIO_ERR |
474 CSI2_IRQ_FIFO_OVF |
475 CSI2_IRQ_CONTEXT0;
97059524 476 iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, reg);
b4a0477c 477 if (enable)
97059524 478 iss_reg_set(csi2->iss, csi2->regs1, CSI2_IRQENABLE, reg);
b4a0477c 479 else
97059524 480 iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQENABLE, 0);
b4a0477c
SA
481}
482
483/*
484 * omap4iss_csi2_reset - Resets the CSI2 module.
485 *
486 * Must be called with the phy lock held.
487 *
488 * Returns 0 if successful, or -EBUSY if power command didn't respond.
489 */
490int omap4iss_csi2_reset(struct iss_csi2_device *csi2)
491{
05b1b986 492 unsigned int timeout;
b4a0477c
SA
493
494 if (!csi2->available)
495 return -ENODEV;
496
497 if (csi2->phy->phy_in_use)
498 return -EBUSY;
499
97059524
LP
500 iss_reg_set(csi2->iss, csi2->regs1, CSI2_SYSCONFIG,
501 CSI2_SYSCONFIG_SOFT_RESET);
b4a0477c 502
05b1b986
LP
503 timeout = iss_poll_condition_timeout(
504 iss_reg_read(csi2->iss, csi2->regs1, CSI2_SYSSTATUS) &
fa7014f5 505 CSI2_SYSSTATUS_RESET_DONE, 500, 100, 200);
05b1b986
LP
506 if (timeout) {
507 dev_err(csi2->iss->dev, "CSI2: Soft reset timeout!\n");
b4a0477c
SA
508 return -EBUSY;
509 }
510
97059524
LP
511 iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_CFG,
512 CSI2_COMPLEXIO_CFG_RESET_CTRL);
b4a0477c 513
05b1b986
LP
514 timeout = iss_poll_condition_timeout(
515 iss_reg_read(csi2->iss, csi2->phy->phy_regs, REGISTER1) &
fa7014f5 516 REGISTER1_RESET_DONE_CTRLCLK, 10000, 100, 500);
05b1b986
LP
517 if (timeout) {
518 dev_err(csi2->iss->dev, "CSI2: CSI2_96M_FCLK reset timeout!\n");
b4a0477c
SA
519 return -EBUSY;
520 }
521
97059524
LP
522 iss_reg_update(csi2->iss, csi2->regs1, CSI2_SYSCONFIG,
523 CSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
524 CSI2_SYSCONFIG_AUTO_IDLE,
525 CSI2_SYSCONFIG_MSTANDBY_MODE_NO);
b4a0477c
SA
526
527 return 0;
528}
529
530static int csi2_configure(struct iss_csi2_device *csi2)
531{
532 const struct iss_v4l2_subdevs_group *pdata;
533 struct iss_csi2_timing_cfg *timing = &csi2->timing[0];
534 struct v4l2_subdev *sensor;
535 struct media_pad *pad;
536
537 /*
538 * CSI2 fields that can be updated while the context has
539 * been enabled or the interface has been enabled are not
540 * updated dynamically currently. So we do not allow to
541 * reconfigure if either has been enabled
542 */
543 if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
544 return -EBUSY;
545
546 pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]);
547 sensor = media_entity_to_v4l2_subdev(pad->entity);
548 pdata = sensor->host_priv;
549
550 csi2->frame_skip = 0;
551 v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
552
553 csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
554 csi2->ctrl.frame_mode = ISS_CSI2_FRAME_IMMEDIATE;
555 csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
556
557 timing->force_rx_mode = 1;
558 timing->stop_state_16x = 1;
559 timing->stop_state_4x = 1;
3c4ee96b 560 timing->stop_state_counter = 0x1ff;
b4a0477c
SA
561
562 /*
563 * The CSI2 receiver can't do any format conversion except DPCM
564 * decompression, so every set_format call configures both pads
565 * and enables DPCM decompression as a special case:
566 */
567 if (csi2->formats[CSI2_PAD_SINK].code !=
568 csi2->formats[CSI2_PAD_SOURCE].code)
569 csi2->dpcm_decompress = true;
570 else
571 csi2->dpcm_decompress = false;
572
573 csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);
574
575 if (csi2->video_out.bpl_padding == 0)
576 csi2->contexts[0].data_offset = 0;
577 else
578 csi2->contexts[0].data_offset = csi2->video_out.bpl_value;
579
580 /*
581 * Enable end of frame and end of line signals generation for
582 * context 0. These signals are generated from CSI2 receiver to
583 * qualify the last pixel of a frame and the last pixel of a line.
584 * Without enabling the signals CSI2 receiver writes data to memory
585 * beyond buffer size and/or data line offset is not handled correctly.
586 */
587 csi2->contexts[0].eof_enabled = 1;
588 csi2->contexts[0].eol_enabled = 1;
589
590 csi2_irq_complexio1_set(csi2, 1);
591 csi2_irq_ctx_set(csi2, 1);
592 csi2_irq_status_set(csi2, 1);
593
594 /* Set configuration (timings, format and links) */
595 csi2_timing_config(csi2, timing);
596 csi2_recv_config(csi2, &csi2->ctrl);
597 csi2_ctx_config(csi2, &csi2->contexts[0]);
598
599 return 0;
600}
601
602/*
603 * csi2_print_status - Prints CSI2 debug information.
604 */
605#define CSI2_PRINT_REGISTER(iss, regs, name)\
606 dev_dbg(iss->dev, "###CSI2 " #name "=0x%08x\n", \
97059524 607 iss_reg_read(iss, regs, CSI2_##name))
b4a0477c
SA
608
609static void csi2_print_status(struct iss_csi2_device *csi2)
610{
611 struct iss_device *iss = csi2->iss;
612
613 if (!csi2->available)
614 return;
615
616 dev_dbg(iss->dev, "-------------CSI2 Register dump-------------\n");
617
618 CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSCONFIG);
619 CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSSTATUS);
620 CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQENABLE);
621 CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQSTATUS);
622 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTRL);
623 CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_H);
624 CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_CFG);
625 CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQSTATUS);
626 CSI2_PRINT_REGISTER(iss, csi2->regs1, SHORT_PACKET);
627 CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQENABLE);
628 CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_P);
629 CSI2_PRINT_REGISTER(iss, csi2->regs1, TIMING);
630 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL1(0));
631 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL2(0));
632 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_DAT_OFST(0));
633 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PING_ADDR(0));
634 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PONG_ADDR(0));
635 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQENABLE(0));
636 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQSTATUS(0));
637 CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL3(0));
638
639 dev_dbg(iss->dev, "--------------------------------------------\n");
640}
641
642/* -----------------------------------------------------------------------------
643 * Interrupt handling
644 */
645
646/*
647 * csi2_isr_buffer - Does buffer handling at end-of-frame
648 * when writing to memory.
649 */
650static void csi2_isr_buffer(struct iss_csi2_device *csi2)
651{
652 struct iss_buffer *buffer;
653
654 csi2_ctx_enable(csi2, 0, 0);
655
656 buffer = omap4iss_video_buffer_next(&csi2->video_out);
657
658 /*
659 * Let video queue operation restart engine if there is an underrun
660 * condition.
661 */
662 if (buffer == NULL)
663 return;
664
665 csi2_set_outaddr(csi2, buffer->iss_addr);
666 csi2_ctx_enable(csi2, 0, 1);
667}
668
669static void csi2_isr_ctx(struct iss_csi2_device *csi2,
670 struct iss_csi2_ctx_cfg *ctx)
671{
672 unsigned int n = ctx->ctxnum;
673 u32 status;
674
97059524
LP
675 status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n));
676 iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status);
b4a0477c
SA
677
678 /* Propagate frame number */
679 if (status & CSI2_CTX_IRQ_FS) {
680 struct iss_pipeline *pipe =
681 to_iss_pipeline(&csi2->subdev.entity);
682 if (pipe->do_propagation)
683 atomic_inc(&pipe->frame_number);
684 }
685
686 if (!(status & CSI2_CTX_IRQ_FE))
687 return;
688
689 /* Skip interrupts until we reach the frame skip count. The CSI2 will be
690 * automatically disabled, as the frame skip count has been programmed
691 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
692 *
693 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
694 * but it turned out that the interrupt is only generated when the CSI2
695 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
696 * correctly and reaches 0 when data is forwarded to the video port only
697 * but no interrupt arrives). Maybe a CSI2 hardware bug.
698 */
699 if (csi2->frame_skip) {
700 csi2->frame_skip--;
701 if (csi2->frame_skip == 0) {
702 ctx->format_id = csi2_ctx_map_format(csi2);
703 csi2_ctx_config(csi2, ctx);
704 csi2_ctx_enable(csi2, n, 1);
705 }
706 return;
707 }
708
709 if (csi2->output & CSI2_OUTPUT_MEMORY)
710 csi2_isr_buffer(csi2);
711}
712
713/*
714 * omap4iss_csi2_isr - CSI2 interrupt handling.
715 */
716void omap4iss_csi2_isr(struct iss_csi2_device *csi2)
717{
718 struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
719 u32 csi2_irqstatus, cpxio1_irqstatus;
720 struct iss_device *iss = csi2->iss;
721
722 if (!csi2->available)
723 return;
724
97059524
LP
725 csi2_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, CSI2_IRQSTATUS);
726 iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, csi2_irqstatus);
b4a0477c
SA
727
728 /* Failure Cases */
729 if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) {
97059524
LP
730 cpxio1_irqstatus = iss_reg_read(csi2->iss, csi2->regs1,
731 CSI2_COMPLEXIO_IRQSTATUS);
732 iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS,
733 cpxio1_irqstatus);
499226fb
LP
734 dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ %x\n",
735 cpxio1_irqstatus);
b4a0477c
SA
736 pipe->error = true;
737 }
738
739 if (csi2_irqstatus & (CSI2_IRQ_OCP_ERR |
740 CSI2_IRQ_SHORT_PACKET |
741 CSI2_IRQ_ECC_NO_CORRECTION |
742 CSI2_IRQ_COMPLEXIO_ERR |
743 CSI2_IRQ_FIFO_OVF)) {
499226fb
LP
744 dev_dbg(iss->dev,
745 "CSI2 Err: OCP:%d SHORT:%d ECC:%d CPXIO:%d OVF:%d\n",
cd782f9d
LP
746 csi2_irqstatus & CSI2_IRQ_OCP_ERR ? 1 : 0,
747 csi2_irqstatus & CSI2_IRQ_SHORT_PACKET ? 1 : 0,
748 csi2_irqstatus & CSI2_IRQ_ECC_NO_CORRECTION ? 1 : 0,
749 csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR ? 1 : 0,
750 csi2_irqstatus & CSI2_IRQ_FIFO_OVF ? 1 : 0);
b4a0477c
SA
751 pipe->error = true;
752 }
753
754 if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
755 return;
756
757 /* Successful cases */
758 if (csi2_irqstatus & CSI2_IRQ_CONTEXT0)
759 csi2_isr_ctx(csi2, &csi2->contexts[0]);
760
761 if (csi2_irqstatus & CSI2_IRQ_ECC_CORRECTION)
762 dev_dbg(iss->dev, "CSI2: ECC correction done\n");
763}
764
765/* -----------------------------------------------------------------------------
766 * ISS video operations
767 */
768
769/*
770 * csi2_queue - Queues the first buffer when using memory output
771 * @video: The video node
772 * @buffer: buffer to queue
773 */
774static int csi2_queue(struct iss_video *video, struct iss_buffer *buffer)
775{
776 struct iss_csi2_device *csi2 = container_of(video,
777 struct iss_csi2_device, video_out);
778
779 csi2_set_outaddr(csi2, buffer->iss_addr);
780
781 /*
782 * If streaming was enabled before there was a buffer queued
783 * or underrun happened in the ISR, the hardware was not enabled
784 * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
785 * Enable it now.
786 */
787 if (csi2->video_out.dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
788 /* Enable / disable context 0 and IRQs */
789 csi2_if_enable(csi2, 1);
790 csi2_ctx_enable(csi2, 0, 1);
791 iss_video_dmaqueue_flags_clr(&csi2->video_out);
792 }
793
794 return 0;
795}
796
797static const struct iss_video_operations csi2_issvideo_ops = {
798 .queue = csi2_queue,
799};
800
801/* -----------------------------------------------------------------------------
802 * V4L2 subdev operations
803 */
804
805static struct v4l2_mbus_framefmt *
806__csi2_get_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
807 unsigned int pad, enum v4l2_subdev_format_whence which)
808{
809 if (which == V4L2_SUBDEV_FORMAT_TRY)
810 return v4l2_subdev_get_try_format(fh, pad);
811 else
812 return &csi2->formats[pad];
813}
814
815static void
816csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
817 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
818 enum v4l2_subdev_format_whence which)
819{
820 enum v4l2_mbus_pixelcode pixelcode;
821 struct v4l2_mbus_framefmt *format;
822 const struct iss_format_info *info;
823 unsigned int i;
824
825 switch (pad) {
826 case CSI2_PAD_SINK:
827 /* Clamp the width and height to valid range (1-8191). */
828 for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
829 if (fmt->code == csi2_input_fmts[i])
830 break;
831 }
832
833 /* If not found, use SGRBG10 as default */
834 if (i >= ARRAY_SIZE(csi2_input_fmts))
835 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
836
837 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
838 fmt->height = clamp_t(u32, fmt->height, 1, 8191);
839 break;
840
841 case CSI2_PAD_SOURCE:
842 /* Source format same as sink format, except for DPCM
843 * compression.
844 */
845 pixelcode = fmt->code;
846 format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
847 memcpy(fmt, format, sizeof(*fmt));
848
849 /*
850 * Only Allow DPCM decompression, and check that the
851 * pattern is preserved
852 */
853 info = omap4iss_video_format_info(fmt->code);
854 if (info->uncompressed == pixelcode)
855 fmt->code = pixelcode;
856 break;
857 }
858
859 /* RGB, non-interlaced */
860 fmt->colorspace = V4L2_COLORSPACE_SRGB;
861 fmt->field = V4L2_FIELD_NONE;
862}
863
864/*
865 * csi2_enum_mbus_code - Handle pixel format enumeration
866 * @sd : pointer to v4l2 subdev structure
867 * @fh : V4L2 subdev file handle
868 * @code : pointer to v4l2_subdev_mbus_code_enum structure
869 * return -EINVAL or zero on success
870 */
871static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
872 struct v4l2_subdev_fh *fh,
873 struct v4l2_subdev_mbus_code_enum *code)
874{
875 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
876 struct v4l2_mbus_framefmt *format;
877 const struct iss_format_info *info;
878
879 if (code->pad == CSI2_PAD_SINK) {
880 if (code->index >= ARRAY_SIZE(csi2_input_fmts))
881 return -EINVAL;
882
883 code->code = csi2_input_fmts[code->index];
884 } else {
885 format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
886 V4L2_SUBDEV_FORMAT_TRY);
887 switch (code->index) {
888 case 0:
889 /* Passthrough sink pad code */
890 code->code = format->code;
891 break;
892 case 1:
893 /* Uncompressed code */
894 info = omap4iss_video_format_info(format->code);
895 if (info->uncompressed == format->code)
896 return -EINVAL;
897
898 code->code = info->uncompressed;
899 break;
900 default:
901 return -EINVAL;
902 }
903 }
904
905 return 0;
906}
907
908static int csi2_enum_frame_size(struct v4l2_subdev *sd,
909 struct v4l2_subdev_fh *fh,
910 struct v4l2_subdev_frame_size_enum *fse)
911{
912 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
913 struct v4l2_mbus_framefmt format;
914
915 if (fse->index != 0)
916 return -EINVAL;
917
918 format.code = fse->code;
919 format.width = 1;
920 format.height = 1;
921 csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
922 fse->min_width = format.width;
923 fse->min_height = format.height;
924
925 if (format.code != fse->code)
926 return -EINVAL;
927
928 format.code = fse->code;
929 format.width = -1;
930 format.height = -1;
931 csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
932 fse->max_width = format.width;
933 fse->max_height = format.height;
934
935 return 0;
936}
937
938/*
939 * csi2_get_format - Handle get format by pads subdev method
940 * @sd : pointer to v4l2 subdev structure
941 * @fh : V4L2 subdev file handle
942 * @fmt: pointer to v4l2 subdev format structure
943 * return -EINVAL or zero on success
944 */
945static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
946 struct v4l2_subdev_format *fmt)
947{
948 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
949 struct v4l2_mbus_framefmt *format;
950
951 format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
952 if (format == NULL)
953 return -EINVAL;
954
955 fmt->format = *format;
956 return 0;
957}
958
959/*
960 * csi2_set_format - Handle set format by pads subdev method
961 * @sd : pointer to v4l2 subdev structure
962 * @fh : V4L2 subdev file handle
963 * @fmt: pointer to v4l2 subdev format structure
964 * return -EINVAL or zero on success
965 */
966static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
967 struct v4l2_subdev_format *fmt)
968{
969 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
970 struct v4l2_mbus_framefmt *format;
971
972 format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
973 if (format == NULL)
974 return -EINVAL;
975
976 csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
977 *format = fmt->format;
978
979 /* Propagate the format from sink to source */
980 if (fmt->pad == CSI2_PAD_SINK) {
981 format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
982 fmt->which);
983 *format = fmt->format;
984 csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
985 }
986
987 return 0;
988}
989
990static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link,
991 struct v4l2_subdev_format *source_fmt,
992 struct v4l2_subdev_format *sink_fmt)
993{
994 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
995 struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
996 int rval;
997
998 pipe->external = media_entity_to_v4l2_subdev(link->source->entity);
999 rval = omap4iss_get_external_info(pipe, link);
1000 if (rval < 0)
1001 return rval;
1002
1003 return v4l2_subdev_link_validate_default(sd, link, source_fmt,
1004 sink_fmt);
1005}
1006
1007/*
1008 * csi2_init_formats - Initialize formats on all pads
1009 * @sd: ISS CSI2 V4L2 subdevice
1010 * @fh: V4L2 subdev file handle
1011 *
1012 * Initialize all pad formats with default values. If fh is not NULL, try
1013 * formats are initialized on the file handle. Otherwise active formats are
1014 * initialized on the device.
1015 */
1016static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1017{
1018 struct v4l2_subdev_format format;
1019
1020 memset(&format, 0, sizeof(format));
1021 format.pad = CSI2_PAD_SINK;
1022 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1023 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
1024 format.format.width = 4096;
1025 format.format.height = 4096;
1026 csi2_set_format(sd, fh, &format);
1027
1028 return 0;
1029}
1030
1031/*
1032 * csi2_set_stream - Enable/Disable streaming on the CSI2 module
1033 * @sd: ISS CSI2 V4L2 subdevice
1034 * @enable: ISS pipeline stream state
1035 *
1036 * Return 0 on success or a negative error code otherwise.
1037 */
1038static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
1039{
1040 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1041 struct iss_device *iss = csi2->iss;
1042 struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
1043 struct iss_video *video_out = &csi2->video_out;
6016498f 1044 int ret = 0;
b4a0477c
SA
1045
1046 if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) {
1047 if (enable == ISS_PIPELINE_STREAM_STOPPED)
1048 return 0;
1049
216814fb 1050 omap4iss_subclk_enable(iss, csi2->subclk);
b4a0477c
SA
1051 }
1052
1053 switch (enable) {
1054 case ISS_PIPELINE_STREAM_CONTINUOUS: {
b4a0477c
SA
1055 ret = omap4iss_csiphy_config(iss, sd);
1056 if (ret < 0)
1057 return ret;
1058
1059 if (omap4iss_csiphy_acquire(csi2->phy) < 0)
1060 return -ENODEV;
1061 csi2->use_fs_irq = pipe->do_propagation;
1062 csi2_configure(csi2);
1063 csi2_print_status(csi2);
1064
1065 /*
1066 * When outputting to memory with no buffer available, let the
1067 * buffer queue handler start the hardware. A DMA queue flag
1068 * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
1069 * a buffer available.
1070 */
1071 if (csi2->output & CSI2_OUTPUT_MEMORY &&
1072 !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
1073 break;
1074 /* Enable context 0 and IRQs */
1075 atomic_set(&csi2->stopping, 0);
1076 csi2_ctx_enable(csi2, 0, 1);
1077 csi2_if_enable(csi2, 1);
1078 iss_video_dmaqueue_flags_clr(video_out);
1079 break;
1080 }
1081 case ISS_PIPELINE_STREAM_STOPPED:
1082 if (csi2->state == ISS_PIPELINE_STREAM_STOPPED)
1083 return 0;
1084 if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait,
1085 &csi2->stopping))
6016498f 1086 ret = -ETIMEDOUT;
b4a0477c
SA
1087 csi2_ctx_enable(csi2, 0, 0);
1088 csi2_if_enable(csi2, 0);
1089 csi2_irq_ctx_set(csi2, 0);
1090 omap4iss_csiphy_release(csi2->phy);
216814fb 1091 omap4iss_subclk_disable(iss, csi2->subclk);
b4a0477c
SA
1092 iss_video_dmaqueue_flags_clr(video_out);
1093 break;
1094 }
1095
1096 csi2->state = enable;
6016498f 1097 return ret;
b4a0477c
SA
1098}
1099
1100/* subdev video operations */
1101static const struct v4l2_subdev_video_ops csi2_video_ops = {
1102 .s_stream = csi2_set_stream,
1103};
1104
1105/* subdev pad operations */
1106static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
1107 .enum_mbus_code = csi2_enum_mbus_code,
1108 .enum_frame_size = csi2_enum_frame_size,
1109 .get_fmt = csi2_get_format,
1110 .set_fmt = csi2_set_format,
1111 .link_validate = csi2_link_validate,
1112};
1113
1114/* subdev operations */
1115static const struct v4l2_subdev_ops csi2_ops = {
1116 .video = &csi2_video_ops,
1117 .pad = &csi2_pad_ops,
1118};
1119
1120/* subdev internal operations */
1121static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
1122 .open = csi2_init_formats,
1123};
1124
1125/* -----------------------------------------------------------------------------
1126 * Media entity operations
1127 */
1128
1129/*
1130 * csi2_link_setup - Setup CSI2 connections.
1131 * @entity : Pointer to media entity structure
1132 * @local : Pointer to local pad array
1133 * @remote : Pointer to remote pad array
1134 * @flags : Link flags
1135 * return -EINVAL or zero on success
1136 */
1137static int csi2_link_setup(struct media_entity *entity,
1138 const struct media_pad *local,
1139 const struct media_pad *remote, u32 flags)
1140{
1141 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1142 struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
1143 struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl;
1144
1145 /*
1146 * The ISS core doesn't support pipelines with multiple video outputs.
1147 * Revisit this when it will be implemented, and return -EBUSY for now.
1148 */
1149
1150 switch (local->index | media_entity_type(remote->entity)) {
1151 case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1152 if (flags & MEDIA_LNK_FL_ENABLED) {
1153 if (csi2->output & ~CSI2_OUTPUT_MEMORY)
1154 return -EBUSY;
1155 csi2->output |= CSI2_OUTPUT_MEMORY;
1156 } else {
1157 csi2->output &= ~CSI2_OUTPUT_MEMORY;
1158 }
1159 break;
1160
1161 case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1162 if (flags & MEDIA_LNK_FL_ENABLED) {
1163 if (csi2->output & ~CSI2_OUTPUT_IPIPEIF)
1164 return -EBUSY;
1165 csi2->output |= CSI2_OUTPUT_IPIPEIF;
1166 } else {
1167 csi2->output &= ~CSI2_OUTPUT_IPIPEIF;
1168 }
1169 break;
1170
1171 default:
1172 /* Link from camera to CSI2 is fixed... */
1173 return -EINVAL;
1174 }
1175
cd782f9d 1176 ctrl->vp_only_enable = csi2->output & CSI2_OUTPUT_MEMORY ? false : true;
b4a0477c
SA
1177 ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_IPIPEIF);
1178
1179 return 0;
1180}
1181
1182/* media operations */
1183static const struct media_entity_operations csi2_media_ops = {
1184 .link_setup = csi2_link_setup,
1185 .link_validate = v4l2_subdev_link_validate,
1186};
1187
1188void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2)
1189{
1190 v4l2_device_unregister_subdev(&csi2->subdev);
1191 omap4iss_video_unregister(&csi2->video_out);
1192}
1193
1194int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2,
1195 struct v4l2_device *vdev)
1196{
1197 int ret;
1198
1199 /* Register the subdev and video nodes. */
1200 ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
1201 if (ret < 0)
1202 goto error;
1203
1204 ret = omap4iss_video_register(&csi2->video_out, vdev);
1205 if (ret < 0)
1206 goto error;
1207
1208 return 0;
1209
1210error:
1211 omap4iss_csi2_unregister_entities(csi2);
1212 return ret;
1213}
1214
1215/* -----------------------------------------------------------------------------
1216 * ISS CSI2 initialisation and cleanup
1217 */
1218
1219/*
1220 * csi2_init_entities - Initialize subdev and media entity.
1221 * @csi2: Pointer to csi2 structure.
1222 * return -ENOMEM or zero on success
1223 */
1224static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname)
1225{
1226 struct v4l2_subdev *sd = &csi2->subdev;
1227 struct media_pad *pads = csi2->pads;
1228 struct media_entity *me = &sd->entity;
1229 int ret;
1230 char name[V4L2_SUBDEV_NAME_SIZE];
1231
1232 v4l2_subdev_init(sd, &csi2_ops);
1233 sd->internal_ops = &csi2_internal_ops;
1234 sprintf(name, "CSI2%s", subname);
eaf95eee 1235 snprintf(sd->name, sizeof(sd->name), "OMAP4 ISS %s", name);
b4a0477c
SA
1236
1237 sd->grp_id = 1 << 16; /* group ID for iss subdevs */
1238 v4l2_set_subdevdata(sd, csi2);
1239 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1240
1241 pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1242 pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1243
1244 me->ops = &csi2_media_ops;
1245 ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
1246 if (ret < 0)
1247 return ret;
1248
1249 csi2_init_formats(sd, NULL);
1250
1251 /* Video device node */
1252 csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1253 csi2->video_out.ops = &csi2_issvideo_ops;
1254 csi2->video_out.bpl_alignment = 32;
1255 csi2->video_out.bpl_zero_padding = 1;
1256 csi2->video_out.bpl_max = 0x1ffe0;
1257 csi2->video_out.iss = csi2->iss;
1258 csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
1259
1260 ret = omap4iss_video_init(&csi2->video_out, name);
1261 if (ret < 0)
1262 goto error_video;
1263
1264 /* Connect the CSI2 subdev to the video node. */
1265 ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
1266 &csi2->video_out.video.entity, 0, 0);
1267 if (ret < 0)
1268 goto error_link;
1269
1270 return 0;
1271
1272error_link:
1273 omap4iss_video_cleanup(&csi2->video_out);
1274error_video:
1275 media_entity_cleanup(&csi2->subdev.entity);
1276 return ret;
1277}
1278
1279/*
1280 * omap4iss_csi2_init - Routine for module driver init
1281 */
1282int omap4iss_csi2_init(struct iss_device *iss)
1283{
1284 struct iss_csi2_device *csi2a = &iss->csi2a;
1285 struct iss_csi2_device *csi2b = &iss->csi2b;
1286 int ret;
1287
1288 csi2a->iss = iss;
1289 csi2a->available = 1;
97059524 1290 csi2a->regs1 = OMAP4_ISS_MEM_CSI2_A_REGS1;
b4a0477c 1291 csi2a->phy = &iss->csiphy1;
216814fb 1292 csi2a->subclk = OMAP4_ISS_SUBCLK_CSI2_A;
b4a0477c
SA
1293 csi2a->state = ISS_PIPELINE_STREAM_STOPPED;
1294 init_waitqueue_head(&csi2a->wait);
1295
1296 ret = csi2_init_entities(csi2a, "a");
1297 if (ret < 0)
1298 return ret;
1299
1300 csi2b->iss = iss;
1301 csi2b->available = 1;
97059524 1302 csi2b->regs1 = OMAP4_ISS_MEM_CSI2_B_REGS1;
b4a0477c 1303 csi2b->phy = &iss->csiphy2;
216814fb 1304 csi2b->subclk = OMAP4_ISS_SUBCLK_CSI2_B;
b4a0477c
SA
1305 csi2b->state = ISS_PIPELINE_STREAM_STOPPED;
1306 init_waitqueue_head(&csi2b->wait);
1307
1308 ret = csi2_init_entities(csi2b, "b");
1309 if (ret < 0)
1310 return ret;
1311
1312 return 0;
1313}
1314
1315/*
1316 * omap4iss_csi2_cleanup - Routine for module driver cleanup
1317 */
1318void omap4iss_csi2_cleanup(struct iss_device *iss)
1319{
1320 struct iss_csi2_device *csi2a = &iss->csi2a;
1321 struct iss_csi2_device *csi2b = &iss->csi2b;
1322
1323 omap4iss_video_cleanup(&csi2a->video_out);
1324 media_entity_cleanup(&csi2a->subdev.entity);
1325
1326 omap4iss_video_cleanup(&csi2b->video_out);
1327 media_entity_cleanup(&csi2b->subdev.entity);
1328}
This page took 0.135239 seconds and 5 git commands to generate.