1 From 9fbe7b786427d981cac890a7407da09232f5d1e2 Mon Sep 17 00:00:00 2001
2 From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3 Date: Tue, 10 Mar 2009 10:49:02 +0200
4 Subject: [PATCH] omap3isp: Add CSI2 interface support
6 Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
8 drivers/media/video/isp/ispcsi2.c | 2124 +++++++++++++++++++++++++++++++++++++
9 drivers/media/video/isp/ispcsi2.h | 232 ++++
10 2 files changed, 2356 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/media/video/isp/ispcsi2.c
12 create mode 100644 drivers/media/video/isp/ispcsi2.h
14 diff --git a/drivers/media/video/isp/ispcsi2.c b/drivers/media/video/isp/ispcsi2.c
16 index 0000000..5141b5a
18 +++ b/drivers/media/video/isp/ispcsi2.c
23 + * Driver Library for ISP CSI Control module in TI's OMAP3 Camera ISP
24 + * ISP CSI interface and IRQ related APIs are defined here.
26 + * Copyright (C) 2009 Texas Instruments.
29 + * Sergio Aguirre <saaguirre@ti.com>
30 + * Dominic Curran <dcurran@ti.com>
32 + * This package is free software; you can redistribute it and/or modify
33 + * it under the terms of the GNU General Public License version 2 as
34 + * published by the Free Software Foundation.
36 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
37 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
38 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
41 +#include <linux/delay.h>
42 +#include <media/v4l2-common.h>
48 +static struct isp_csi2_cfg current_csi2_cfg;
49 +static struct isp_csi2_cfg_update current_csi2_cfg_update;
51 +static bool update_complexio_cfg1;
52 +static bool update_phy_cfg0;
53 +static bool update_phy_cfg1;
54 +static bool update_ctx_ctrl1[8];
55 +static bool update_ctx_ctrl2[8];
56 +static bool update_ctx_ctrl3[8];
57 +static bool update_timing;
58 +static bool update_ctrl;
59 +static bool uses_videoport;
62 + * isp_csi2_complexio_lanes_config - Configuration of CSI2 ComplexIO lanes.
63 + * @reqcfg: Pointer to structure containing desired lane configuration
65 + * Validates and saves to internal driver memory the passed configuration.
66 + * Returns 0 if successful, or -EINVAL if null pointer is passed, invalid
67 + * lane position or polarity is set, and if 2 lanes try to occupy the same
68 + * position. To apply this settings, use the isp_csi2_complexio_lanes_update()
69 + * function just after calling this function.
71 +int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg)
74 + bool pos_occupied[5] = {false, false, false, false, false};
75 + struct isp_csi2_lanes_cfg *currlanes = ¤t_csi2_cfg.lanes;
76 + struct isp_csi2_lanes_cfg_update *currlanes_u =
77 + ¤t_csi2_cfg_update.lanes;
79 + /* Validating parameters sent by driver */
80 + if (reqcfg == NULL) {
81 + printk(KERN_ERR "Invalid Complex IO Configuration sent by"
86 + /* Data lanes verification */
87 + for (i = 0; i < 4; i++) {
88 + if ((reqcfg->data[i].pol > 1) || (reqcfg->data[i].pos > 5)) {
89 + printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
90 + " parameters for data lane #%d\n", i);
93 + if (pos_occupied[reqcfg->data[i].pos - 1] &&
94 + reqcfg->data[i].pos > 0) {
95 + printk(KERN_ERR "Lane #%d already occupied\n",
96 + reqcfg->data[i].pos);
99 + pos_occupied[reqcfg->data[i].pos - 1] = true;
102 + /* Clock lane verification */
103 + if ((reqcfg->clk.pol > 1) || (reqcfg->clk.pos > 5) ||
104 + (reqcfg->clk.pos == 0)) {
105 + printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
106 + " parameters for clock lane\n");
109 + if (pos_occupied[reqcfg->clk.pos - 1]) {
110 + printk(KERN_ERR "Lane #%d already occupied",
114 + pos_occupied[reqcfg->clk.pos - 1] = true;
116 + for (i = 0; i < 4; i++) {
117 + if (currlanes->data[i].pos != reqcfg->data[i].pos) {
118 + currlanes->data[i].pos = reqcfg->data[i].pos;
119 + currlanes_u->data[i] = true;
120 + update_complexio_cfg1 = true;
122 + if (currlanes->data[i].pol != reqcfg->data[i].pol) {
123 + currlanes->data[i].pol = reqcfg->data[i].pol;
124 + currlanes_u->data[i] = true;
125 + update_complexio_cfg1 = true;
129 + if (currlanes->clk.pos != reqcfg->clk.pos) {
130 + currlanes->clk.pos = reqcfg->clk.pos;
131 + currlanes_u->clk = true;
132 + update_complexio_cfg1 = true;
134 + if (currlanes->clk.pol != reqcfg->clk.pol) {
135 + currlanes->clk.pol = reqcfg->clk.pol;
136 + currlanes_u->clk = true;
137 + update_complexio_cfg1 = true;
145 + * isp_csi2_complexio_lanes_update - Applies CSI2 ComplexIO lanes configuration.
146 + * @force_update: Flag to force rewrite of registers, even if they haven't been
147 + * updated with the isp_csi2_complexio_lanes_config() function.
149 + * It only saves settings when they were previously updated using the
150 + * isp_csi2_complexio_lanes_config() function, unless the force_update flag is
152 + * Always returns 0.
154 +int isp_csi2_complexio_lanes_update(bool force_update)
156 + struct isp_csi2_lanes_cfg *currlanes = ¤t_csi2_cfg.lanes;
157 + struct isp_csi2_lanes_cfg_update *currlanes_u =
158 + ¤t_csi2_cfg_update.lanes;
162 + if (!update_complexio_cfg1 && !force_update)
165 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
166 + for (i = 0; i < 4; i++) {
167 + if (currlanes_u->data[i] || force_update) {
168 + reg &= ~(ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1) |
169 + ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i +
171 + reg |= (currlanes->data[i].pol <<
172 + ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1));
173 + reg |= (currlanes->data[i].pos <<
174 + ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i +
176 + currlanes_u->data[i] = false;
180 + if (currlanes_u->clk || force_update) {
181 + reg &= ~(ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK |
182 + ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK);
183 + reg |= (currlanes->clk.pol <<
184 + ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT);
185 + reg |= (currlanes->clk.pos <<
186 + ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT);
187 + currlanes_u->clk = false;
189 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
191 + update_complexio_cfg1 = false;
196 + * isp_csi2_complexio_lanes_get - Gets CSI2 ComplexIO lanes configuration.
198 + * Gets settings from HW registers and fills in the internal driver memory
199 + * Always returns 0.
201 +int isp_csi2_complexio_lanes_get(void)
203 + struct isp_csi2_lanes_cfg *currlanes = ¤t_csi2_cfg.lanes;
204 + struct isp_csi2_lanes_cfg_update *currlanes_u =
205 + ¤t_csi2_cfg_update.lanes;
209 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
210 + for (i = 0; i < 4; i++) {
211 + currlanes->data[i].pol = (reg &
212 + ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1)) >>
213 + ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1);
214 + currlanes->data[i].pos = (reg &
215 + ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i + 1)) >>
216 + ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i + 1);
217 + currlanes_u->data[i] = false;
219 + currlanes->clk.pol = (reg & ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK) >>
220 + ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT;
221 + currlanes->clk.pos = (reg &
222 + ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK) >>
223 + ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT;
224 + currlanes_u->clk = false;
226 + update_complexio_cfg1 = false;
231 + * isp_csi2_complexio_power_status - Gets CSI2 ComplexIO power status.
233 + * Returns 3 possible valid states: ISP_CSI2_POWER_OFF, ISP_CSI2_POWER_ON,
234 + * and ISP_CSI2_POWER_ULPW.
236 +static enum isp_csi2_power_cmds isp_csi2_complexio_power_status(void)
238 + enum isp_csi2_power_cmds ret;
241 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
242 + ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK;
244 + case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF:
245 + ret = ISP_CSI2_POWER_OFF;
247 + case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON:
248 + ret = ISP_CSI2_POWER_ON;
250 + case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW:
251 + ret = ISP_CSI2_POWER_ULPW;
260 + * isp_csi2_complexio_power_autoswitch - Sets CSI2 ComplexIO power autoswitch.
261 + * @enable: Sets or clears the autoswitch function enable flag.
263 + * Always returns 0.
265 +int isp_csi2_complexio_power_autoswitch(bool enable)
269 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
270 + reg &= ~ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK;
273 + reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE;
275 + reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE;
277 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
282 + * isp_csi2_complexio_power - Sets the desired power command for CSI2 ComplexIO.
283 + * @power_cmd: Power command to be set.
285 + * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
287 +int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd)
289 + enum isp_csi2_power_cmds current_state;
293 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
294 + ~ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK;
295 + switch (power_cmd) {
296 + case ISP_CSI2_POWER_OFF:
297 + reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF;
299 + case ISP_CSI2_POWER_ON:
300 + reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON;
302 + case ISP_CSI2_POWER_ULPW:
303 + reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW;
306 + printk(KERN_ERR "CSI2: ERROR - Wrong Power command!\n");
309 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
314 + current_state = isp_csi2_complexio_power_status();
316 + if (current_state != power_cmd) {
317 + printk(KERN_DEBUG "CSI2: Complex IO power command not"
319 + if (++retry_count < 100) {
320 + printk(KERN_DEBUG " Retrying...\n");
323 + printk(KERN_DEBUG " Retry count exceeded!\n");
326 + } while ((current_state != power_cmd) && (retry_count < 100));
328 + if (retry_count == 100)
335 + * isp_csi2_ctrl_config_frame_mode - Configure if_en behaviour for CSI2
336 + * @frame_mode: Desired action for IF_EN switch off. 0 - disable IF immediately
337 + * 1 - disable after all Frame end Code is received in all
340 + * Validates and saves to internal driver memory the passed configuration.
341 + * Always returns 0.
343 +int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode)
345 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
346 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
347 + ¤t_csi2_cfg_update.ctrl;
349 + if (currctrl->frame_mode != frame_mode) {
350 + currctrl->frame_mode = frame_mode;
351 + currctrl_u->frame_mode = true;
352 + update_ctrl = true;
358 + * isp_csi2_ctrl_config_vp_clk_enable - Enables/disables CSI2 Videoport clock.
359 + * @vp_clk_enable: Boolean value to specify the Videoport clock state.
361 + * Validates and saves to internal driver memory the passed configuration.
362 + * Always returns 0.
364 +int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable)
366 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
367 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
368 + ¤t_csi2_cfg_update.ctrl;
370 + if (currctrl->vp_clk_enable != vp_clk_enable) {
371 + currctrl->vp_clk_enable = vp_clk_enable;
372 + currctrl_u->vp_clk_enable = true;
373 + update_ctrl = true;
379 + * isp_csi2_ctrl_config_vp_only_enable - Sets CSI2 Videoport clock as exclusive
380 + * @vp_only_enable: Boolean value to specify if the Videoport clock is
381 + * exclusive, setting the OCP port as disabled.
383 + * Validates and saves to internal driver memory the passed configuration.
384 + * Always returns 0.
386 +int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable)
388 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
389 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
390 + ¤t_csi2_cfg_update.ctrl;
392 + if (currctrl->vp_only_enable != vp_only_enable) {
393 + currctrl->vp_only_enable = vp_only_enable;
394 + currctrl_u->vp_only_enable = true;
395 + update_ctrl = true;
401 + * isp_csi2_ctrl_config_vp_out_ctrl - Sets CSI2 Videoport clock divider
402 + * @vp_out_ctrl: Divider value for setting videoport clock frequency based on
403 + * OCP port frequency, valid dividers are between 1 and 4.
405 + * Validates and saves to internal driver memory the passed configuration.
406 + * Returns 0 if successful, or -EINVAL if wrong divider value is passed.
408 +int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl)
410 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
411 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
412 + ¤t_csi2_cfg_update.ctrl;
414 + if ((vp_out_ctrl == 0) || (vp_out_ctrl > 4)) {
415 + printk(KERN_ERR "CSI2: Wrong divisor value. Must be between"
420 + if (currctrl->vp_out_ctrl != vp_out_ctrl) {
421 + currctrl->vp_out_ctrl = vp_out_ctrl;
422 + currctrl_u->vp_out_ctrl = true;
423 + update_ctrl = true;
429 + * isp_csi2_ctrl_config_debug_enable - Sets CSI2 debug
430 + * @debug_enable: Boolean for setting debug configuration on CSI2.
432 + * Always returns 0.
434 +int isp_csi2_ctrl_config_debug_enable(bool debug_enable)
436 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
437 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
438 + ¤t_csi2_cfg_update.ctrl;
440 + if (currctrl->debug_enable != debug_enable) {
441 + currctrl->debug_enable = debug_enable;
442 + currctrl_u->debug_enable = true;
443 + update_ctrl = true;
449 + * isp_csi2_ctrl_config_burst_size - Sets CSI2 burst size.
450 + * @burst_size: Burst size of the memory saving capability of receiver.
452 + * Returns 0 if successful, or -EINVAL if burst size is wrong.
454 +int isp_csi2_ctrl_config_burst_size(u8 burst_size)
456 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
457 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
458 + ¤t_csi2_cfg_update.ctrl;
459 + if (burst_size > 3) {
460 + printk(KERN_ERR "CSI2: Wrong burst size. Must be between"
465 + if (currctrl->burst_size != burst_size) {
466 + currctrl->burst_size = burst_size;
467 + currctrl_u->burst_size = true;
468 + update_ctrl = true;
474 + * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
475 + * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
477 + * Always returns 0.
479 +int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable)
481 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
482 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
483 + ¤t_csi2_cfg_update.ctrl;
485 + if (currctrl->ecc_enable != ecc_enable) {
486 + currctrl->ecc_enable = ecc_enable;
487 + currctrl_u->ecc_enable = true;
488 + update_ctrl = true;
494 + * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
495 + * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
497 + * Always returns 0.
499 +int isp_csi2_ctrl_config_secure_mode(bool secure_mode)
501 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
502 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
503 + ¤t_csi2_cfg_update.ctrl;
505 + if (currctrl->secure_mode != secure_mode) {
506 + currctrl->secure_mode = secure_mode;
507 + currctrl_u->secure_mode = true;
508 + update_ctrl = true;
514 + * isp_csi2_ctrl_config_if_enable - Enables CSI2 Receiver interface.
515 + * @if_enable: Boolean to enable/disable the CSI2 receiver interface.
517 + * Always returns 0.
519 +int isp_csi2_ctrl_config_if_enable(bool if_enable)
521 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
522 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
523 + ¤t_csi2_cfg_update.ctrl;
525 + if (currctrl->if_enable != if_enable) {
526 + currctrl->if_enable = if_enable;
527 + currctrl_u->if_enable = true;
528 + update_ctrl = true;
534 + * isp_csi2_ctrl_update - Applies CSI2 control configuration.
535 + * @force_update: Flag to force rewrite of registers, even if they haven't been
536 + * updated with the isp_csi2_ctrl_config_*() functions.
538 + * It only saves settings when they were previously updated using the
539 + * isp_csi2_ctrl_config_*() functions, unless the force_update flag is
541 + * Always returns 0.
543 +int isp_csi2_ctrl_update(bool force_update)
545 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
546 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
547 + ¤t_csi2_cfg_update.ctrl;
550 + if (update_ctrl || force_update) {
551 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
552 + if (currctrl_u->frame_mode || force_update) {
553 + reg &= ~ISPCSI2_CTRL_FRAME_MASK;
554 + if (currctrl->frame_mode)
555 + reg |= ISPCSI2_CTRL_FRAME_DISABLE_FEC;
557 + reg |= ISPCSI2_CTRL_FRAME_DISABLE_IMM;
558 + currctrl_u->frame_mode = false;
560 + if (currctrl_u->vp_clk_enable || force_update) {
561 + reg &= ~ISPCSI2_CTRL_VP_CLK_EN_MASK;
562 + if (currctrl->vp_clk_enable)
563 + reg |= ISPCSI2_CTRL_VP_CLK_EN_ENABLE;
565 + reg |= ISPCSI2_CTRL_VP_CLK_EN_DISABLE;
566 + currctrl_u->vp_clk_enable = false;
568 + if (currctrl_u->vp_only_enable || force_update) {
569 + reg &= ~ISPCSI2_CTRL_VP_ONLY_EN_MASK;
570 + uses_videoport = currctrl->vp_only_enable;
571 + if (currctrl->vp_only_enable)
572 + reg |= ISPCSI2_CTRL_VP_ONLY_EN_ENABLE;
574 + reg |= ISPCSI2_CTRL_VP_ONLY_EN_DISABLE;
575 + currctrl_u->vp_only_enable = false;
577 + if (currctrl_u->vp_out_ctrl || force_update) {
578 + reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
579 + reg |= (currctrl->vp_out_ctrl - 1) <<
580 + ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
581 + currctrl_u->vp_out_ctrl = false;
583 + if (currctrl_u->debug_enable || force_update) {
584 + reg &= ~ISPCSI2_CTRL_DBG_EN_MASK;
585 + if (currctrl->debug_enable)
586 + reg |= ISPCSI2_CTRL_DBG_EN_ENABLE;
588 + reg |= ISPCSI2_CTRL_DBG_EN_DISABLE;
589 + currctrl_u->debug_enable = false;
591 + if (currctrl_u->burst_size || force_update) {
592 + reg &= ~ISPCSI2_CTRL_BURST_SIZE_MASK;
593 + reg |= currctrl->burst_size <<
594 + ISPCSI2_CTRL_BURST_SIZE_SHIFT;
595 + currctrl_u->burst_size = false;
597 + if (currctrl_u->ecc_enable || force_update) {
598 + reg &= ~ISPCSI2_CTRL_ECC_EN_MASK;
599 + if (currctrl->ecc_enable)
600 + reg |= ISPCSI2_CTRL_ECC_EN_ENABLE;
602 + reg |= ISPCSI2_CTRL_ECC_EN_DISABLE;
603 + currctrl_u->ecc_enable = false;
605 + if (currctrl_u->secure_mode || force_update) {
606 + reg &= ~ISPCSI2_CTRL_SECURE_MASK;
607 + if (currctrl->secure_mode)
608 + reg |= ISPCSI2_CTRL_SECURE_ENABLE;
610 + reg |= ISPCSI2_CTRL_SECURE_DISABLE;
611 + currctrl_u->secure_mode = false;
613 + if (currctrl_u->if_enable || force_update) {
614 + reg &= ~ISPCSI2_CTRL_IF_EN_MASK;
615 + if (currctrl->if_enable)
616 + reg |= ISPCSI2_CTRL_IF_EN_ENABLE;
618 + reg |= ISPCSI2_CTRL_IF_EN_DISABLE;
619 + currctrl_u->if_enable = false;
621 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
622 + update_ctrl = false;
628 + * isp_csi2_ctrl_get - Gets CSI2 control configuration
630 + * Always returns 0.
632 +int isp_csi2_ctrl_get(void)
634 + struct isp_csi2_ctrl_cfg *currctrl = ¤t_csi2_cfg.ctrl;
635 + struct isp_csi2_ctrl_cfg_update *currctrl_u =
636 + ¤t_csi2_cfg_update.ctrl;
639 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
640 + currctrl->frame_mode = (reg & ISPCSI2_CTRL_FRAME_MASK) >>
641 + ISPCSI2_CTRL_FRAME_SHIFT;
642 + currctrl_u->frame_mode = false;
644 + if ((reg & ISPCSI2_CTRL_VP_CLK_EN_MASK) ==
645 + ISPCSI2_CTRL_VP_CLK_EN_ENABLE)
646 + currctrl->vp_clk_enable = true;
648 + currctrl->vp_clk_enable = false;
649 + currctrl_u->vp_clk_enable = false;
651 + if ((reg & ISPCSI2_CTRL_VP_ONLY_EN_MASK) ==
652 + ISPCSI2_CTRL_VP_ONLY_EN_ENABLE)
653 + currctrl->vp_only_enable = true;
655 + currctrl->vp_only_enable = false;
656 + uses_videoport = currctrl->vp_only_enable;
657 + currctrl_u->vp_only_enable = false;
659 + currctrl->vp_out_ctrl = ((reg & ISPCSI2_CTRL_VP_OUT_CTRL_MASK) >>
660 + ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT) + 1;
661 + currctrl_u->vp_out_ctrl = false;
663 + if ((reg & ISPCSI2_CTRL_DBG_EN_MASK) == ISPCSI2_CTRL_DBG_EN_ENABLE)
664 + currctrl->debug_enable = true;
666 + currctrl->debug_enable = false;
667 + currctrl_u->debug_enable = false;
669 + currctrl->burst_size = (reg & ISPCSI2_CTRL_BURST_SIZE_MASK) >>
670 + ISPCSI2_CTRL_BURST_SIZE_SHIFT;
671 + currctrl_u->burst_size = false;
673 + if ((reg & ISPCSI2_CTRL_ECC_EN_MASK) == ISPCSI2_CTRL_ECC_EN_ENABLE)
674 + currctrl->ecc_enable = true;
676 + currctrl->ecc_enable = false;
677 + currctrl_u->ecc_enable = false;
679 + if ((reg & ISPCSI2_CTRL_SECURE_MASK) == ISPCSI2_CTRL_SECURE_ENABLE)
680 + currctrl->secure_mode = true;
682 + currctrl->secure_mode = false;
683 + currctrl_u->secure_mode = false;
685 + if ((reg & ISPCSI2_CTRL_IF_EN_MASK) == ISPCSI2_CTRL_IF_EN_ENABLE)
686 + currctrl->if_enable = true;
688 + currctrl->if_enable = false;
689 + currctrl_u->if_enable = false;
691 + update_ctrl = false;
696 + * isp_csi2_ctx_validate - Validates the context number value
697 + * @ctxnum: Pointer to variable containing context number.
699 + * If the value is not in range (3 bits), it is being ANDed with 0x7 to force
700 + * it to be on range.
702 +static void isp_csi2_ctx_validate(u8 *ctxnum)
705 + printk(KERN_ERR "Invalid context number. Forcing valid"
712 + * isp_csi2_ctx_config_virtual_id - Maps a virtual ID with a CSI2 Rx context
713 + * @ctxnum: Context number, valid between 0 and 7 values.
714 + * @virtual_id: CSI2 Virtual ID to associate with specified context number.
716 + * Returns 0 if successful, or -EINVAL if Virtual ID is not in range (0-3).
718 +int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id)
720 + struct isp_csi2_ctx_cfg *selected_ctx;
721 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
723 + isp_csi2_ctx_validate(&ctxnum);
725 + if (virtual_id > 3) {
726 + printk(KERN_ERR "Wrong requested virtual_id\n");
730 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
731 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
733 + if (selected_ctx->virtual_id != virtual_id) {
734 + selected_ctx->virtual_id = virtual_id;
735 + selected_ctx_u->virtual_id = true;
736 + update_ctx_ctrl2[ctxnum] = true;
743 + * isp_csi2_ctx_config_frame_count - Sets frame count to be received in CSI2 Rx.
744 + * @ctxnum: Context number, valid between 0 and 7 values.
745 + * @frame_count: Number of frames to acquire.
747 + * Always returns 0.
749 +int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count)
751 + struct isp_csi2_ctx_cfg *selected_ctx;
752 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
754 + isp_csi2_ctx_validate(&ctxnum);
756 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
757 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
759 + if (selected_ctx->frame_count != frame_count) {
760 + selected_ctx->frame_count = frame_count;
761 + selected_ctx_u->frame_count = true;
762 + update_ctx_ctrl1[ctxnum] = true;
769 + * isp_csi2_ctx_config_format - Maps a pixel format to a specified context.
770 + * @ctxnum: Context number, valid between 0 and 7 values.
771 + * @pixformat: V4L2 structure for pixel format.
773 + * Returns 0 if successful, or -EINVAL if the format is not supported by the
776 +int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat)
778 + struct isp_csi2_ctx_cfg *selected_ctx;
779 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
780 + struct v4l2_pix_format pix;
782 + isp_csi2_ctx_validate(&ctxnum);
784 + pix.pixelformat = pixformat;
785 + switch (pix.pixelformat) {
786 + case V4L2_PIX_FMT_RGB565:
787 + case V4L2_PIX_FMT_RGB565X:
788 + case V4L2_PIX_FMT_YUYV:
789 + case V4L2_PIX_FMT_UYVY:
790 + case V4L2_PIX_FMT_RGB555:
791 + case V4L2_PIX_FMT_RGB555X:
792 + case V4L2_PIX_FMT_SGRBG10:
795 + printk(KERN_ERR "Context config pixel format unsupported\n");
799 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
800 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
802 + selected_ctx->format = pix;
803 + selected_ctx_u->format = true;
804 + update_ctx_ctrl2[ctxnum] = true;
810 + * isp_csi2_ctx_config_alpha - Sets the alpha value for pixel format
811 + * @ctxnum: Context number, valid between 0 and 7 values.
812 + * @alpha: Alpha value.
814 + * Returns 0 if successful, or -EINVAL if the alpha value is bigger than 16383.
816 +int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha)
818 + struct isp_csi2_ctx_cfg *selected_ctx;
819 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
821 + isp_csi2_ctx_validate(&ctxnum);
823 + if (alpha > 0x3FFF) {
824 + printk(KERN_ERR "Wrong alpha value\n");
828 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
829 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
831 + if (selected_ctx->alpha != alpha) {
832 + selected_ctx->alpha = alpha;
833 + selected_ctx_u->alpha = true;
834 + update_ctx_ctrl3[ctxnum] = true;
840 + * isp_csi2_ctx_config_data_offset - Sets the offset between received lines
841 + * @ctxnum: Context number, valid between 0 and 7 values.
842 + * @data_offset: Offset between first pixel of each 2 contiguous lines.
844 + * Returns 0 if successful, or -EINVAL if the line offset is bigger than 1023.
846 +int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset)
848 + struct isp_csi2_ctx_cfg *selected_ctx;
849 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
851 + isp_csi2_ctx_validate(&ctxnum);
853 + if (data_offset > 0x3FF) {
854 + printk(KERN_ERR "Wrong line offset\n");
858 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
859 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
861 + if (selected_ctx->data_offset != data_offset) {
862 + selected_ctx->data_offset = data_offset;
863 + selected_ctx_u->data_offset = true;
869 + * isp_csi2_ctx_config_ping_addr - Sets Ping address for CSI2 Rx. buffer saving
870 + * @ctxnum: Context number, valid between 0 and 7 values.
871 + * @ping_addr: 32 bit ISP MMU mapped address.
873 + * Always returns 0.
875 +int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr)
877 + struct isp_csi2_ctx_cfg *selected_ctx;
878 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
880 + isp_csi2_ctx_validate(&ctxnum);
882 + ping_addr &= ~(0x1F);
884 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
885 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
887 + if (selected_ctx->ping_addr != ping_addr) {
888 + selected_ctx->ping_addr = ping_addr;
889 + selected_ctx_u->ping_addr = true;
895 + * isp_csi2_ctx_config_pong_addr - Sets Pong address for CSI2 Rx. buffer saving
896 + * @ctxnum: Context number, valid between 0 and 7 values.
897 + * @pong_addr: 32 bit ISP MMU mapped address.
899 + * Always returns 0.
901 +int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr)
903 + struct isp_csi2_ctx_cfg *selected_ctx;
904 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
906 + isp_csi2_ctx_validate(&ctxnum);
908 + pong_addr &= ~(0x1F);
910 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
911 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
913 + if (selected_ctx->pong_addr != pong_addr) {
914 + selected_ctx->pong_addr = pong_addr;
915 + selected_ctx_u->pong_addr = true;
921 + * isp_csi2_ctx_config_eof_enabled - Enables EOF signal assertion
922 + * @ctxnum: Context number, valid between 0 and 7 values.
923 + * @eof_enabled: Boolean to enable/disable EOF signal assertion on received
926 + * Always returns 0.
928 +int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled)
930 + struct isp_csi2_ctx_cfg *selected_ctx;
931 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
933 + isp_csi2_ctx_validate(&ctxnum);
935 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
936 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
938 + if (selected_ctx->eof_enabled != eof_enabled) {
939 + selected_ctx->eof_enabled = eof_enabled;
940 + selected_ctx_u->eof_enabled = true;
941 + update_ctx_ctrl1[ctxnum] = true;
947 + * isp_csi2_ctx_config_eol_enabled - Enables EOL signal assertion
948 + * @ctxnum: Context number, valid between 0 and 7 values.
949 + * @eol_enabled: Boolean to enable/disable EOL signal assertion on received
952 + * Always returns 0.
954 +int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled)
956 + struct isp_csi2_ctx_cfg *selected_ctx;
957 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
959 + isp_csi2_ctx_validate(&ctxnum);
961 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
962 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
964 + if (selected_ctx->eol_enabled != eol_enabled) {
965 + selected_ctx->eol_enabled = eol_enabled;
966 + selected_ctx_u->eol_enabled = true;
967 + update_ctx_ctrl1[ctxnum] = true;
973 + * isp_csi2_ctx_config_checksum_enabled - Enables Checksum check in rcvd packets
974 + * @ctxnum: Context number, valid between 0 and 7 values.
975 + * @checksum_enabled: Boolean to enable/disable Checksum check on received
978 + * Always returns 0.
980 +int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled)
982 + struct isp_csi2_ctx_cfg *selected_ctx;
983 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
985 + isp_csi2_ctx_validate(&ctxnum);
987 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
988 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
990 + if (selected_ctx->checksum_enabled != checksum_enabled) {
991 + selected_ctx->checksum_enabled = checksum_enabled;
992 + selected_ctx_u->checksum_enabled = true;
993 + update_ctx_ctrl1[ctxnum] = true;
999 + * isp_csi2_ctx_config_enabled - Enables specified CSI2 context
1000 + * @ctxnum: Context number, valid between 0 and 7 values.
1001 + * @enabled: Boolean to enable/disable specified context.
1003 + * Always returns 0.
1005 +int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled)
1007 + struct isp_csi2_ctx_cfg *selected_ctx;
1008 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1010 + isp_csi2_ctx_validate(&ctxnum);
1012 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
1013 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
1015 + if (selected_ctx->enabled != enabled) {
1016 + selected_ctx->enabled = enabled;
1017 + selected_ctx_u->enabled = true;
1018 + update_ctx_ctrl1[ctxnum] = true;
1024 + * isp_csi2_ctx_update - Applies CSI2 context configuration.
1025 + * @ctxnum: Context number, valid between 0 and 7 values.
1026 + * @force_update: Flag to force rewrite of registers, even if they haven't been
1027 + * updated with the isp_csi2_ctx_config_*() functions.
1029 + * It only saves settings when they were previously updated using the
1030 + * isp_csi2_ctx_config_*() functions, unless the force_update flag is
1032 + * Always returns 0.
1034 +int isp_csi2_ctx_update(u8 ctxnum, bool force_update)
1036 + struct isp_csi2_ctx_cfg *selected_ctx;
1037 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1040 + isp_csi2_ctx_validate(&ctxnum);
1042 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
1043 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
1045 + if (update_ctx_ctrl1[ctxnum] || force_update) {
1046 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1047 + ISPCSI2_CTX_CTRL1(ctxnum));
1048 + if (selected_ctx_u->frame_count || force_update) {
1049 + reg &= ~(ISPCSI2_CTX_CTRL1_COUNT_MASK);
1050 + reg |= selected_ctx->frame_count <<
1051 + ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
1052 + selected_ctx_u->frame_count = false;
1054 + if (selected_ctx_u->eof_enabled || force_update) {
1055 + reg &= ~(ISPCSI2_CTX_CTRL1_EOF_EN_MASK);
1056 + if (selected_ctx->eof_enabled)
1057 + reg |= ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE;
1059 + reg |= ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE;
1060 + selected_ctx_u->eof_enabled = false;
1062 + if (selected_ctx_u->eol_enabled || force_update) {
1063 + reg &= ~(ISPCSI2_CTX_CTRL1_EOL_EN_MASK);
1064 + if (selected_ctx->eol_enabled)
1065 + reg |= ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE;
1067 + reg |= ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE;
1068 + selected_ctx_u->eol_enabled = false;
1070 + if (selected_ctx_u->checksum_enabled || force_update) {
1071 + reg &= ~(ISPCSI2_CTX_CTRL1_CS_EN_MASK);
1072 + if (selected_ctx->checksum_enabled)
1073 + reg |= ISPCSI2_CTX_CTRL1_CS_EN_ENABLE;
1075 + reg |= ISPCSI2_CTX_CTRL1_CS_EN_DISABLE;
1076 + selected_ctx_u->checksum_enabled = false;
1078 + if (selected_ctx_u->enabled || force_update) {
1079 + reg &= ~(ISPCSI2_CTX_CTRL1_CTX_EN_MASK);
1080 + if (selected_ctx->enabled)
1081 + reg |= ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE;
1083 + reg |= ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE;
1084 + selected_ctx_u->enabled = false;
1086 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1087 + ISPCSI2_CTX_CTRL1(ctxnum));
1088 + update_ctx_ctrl1[ctxnum] = false;
1091 + if (update_ctx_ctrl2[ctxnum] || force_update) {
1092 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1093 + ISPCSI2_CTX_CTRL2(ctxnum));
1094 + if (selected_ctx_u->virtual_id || force_update) {
1095 + reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
1096 + reg |= selected_ctx->virtual_id <<
1097 + ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
1098 + selected_ctx_u->virtual_id = false;
1101 + if (selected_ctx_u->format || force_update) {
1102 + struct v4l2_pix_format *pix;
1103 + u16 new_format = 0;
1105 + reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
1106 + pix = &selected_ctx->format;
1107 + switch (pix->pixelformat) {
1108 + case V4L2_PIX_FMT_RGB565:
1109 + case V4L2_PIX_FMT_RGB565X:
1110 + new_format = 0x22;
1112 + case V4L2_PIX_FMT_YUYV:
1113 + case V4L2_PIX_FMT_UYVY:
1114 + if (uses_videoport)
1115 + new_format = 0x9E;
1117 + new_format = 0x1E;
1119 + case V4L2_PIX_FMT_RGB555:
1120 + case V4L2_PIX_FMT_RGB555X:
1121 + new_format = 0xA1;
1123 + case V4L2_PIX_FMT_SGRBG10:
1124 + if (uses_videoport)
1125 + new_format = 0x12F;
1127 + new_format = 0xAB;
1130 + reg |= (new_format << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT);
1131 + selected_ctx_u->format = false;
1133 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1134 + ISPCSI2_CTX_CTRL2(ctxnum));
1135 + update_ctx_ctrl2[ctxnum] = false;
1138 + if (update_ctx_ctrl3[ctxnum] || force_update) {
1139 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1140 + ISPCSI2_CTX_CTRL3(ctxnum));
1141 + if (selected_ctx_u->alpha || force_update) {
1142 + reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
1143 + reg |= (selected_ctx->alpha <<
1144 + ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
1145 + selected_ctx_u->alpha = false;
1147 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1148 + ISPCSI2_CTX_CTRL3(ctxnum));
1149 + update_ctx_ctrl3[ctxnum] = false;
1152 + if (selected_ctx_u->data_offset) {
1153 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1154 + ISPCSI2_CTX_DAT_OFST(ctxnum));
1155 + reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
1156 + reg |= selected_ctx->data_offset <<
1157 + ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
1158 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1159 + ISPCSI2_CTX_DAT_OFST(ctxnum));
1160 + selected_ctx_u->data_offset = false;
1163 + if (selected_ctx_u->ping_addr) {
1164 + reg = selected_ctx->ping_addr;
1165 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1166 + ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
1167 + selected_ctx_u->ping_addr = false;
1170 + if (selected_ctx_u->pong_addr) {
1171 + reg = selected_ctx->pong_addr;
1172 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1173 + ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
1174 + selected_ctx_u->pong_addr = false;
1180 + * isp_csi2_ctx_get - Gets specific CSI2 Context configuration
1181 + * @ctxnum: Context number, valid between 0 and 7 values.
1183 + * Always returns 0.
1185 +int isp_csi2_ctx_get(u8 ctxnum)
1187 + struct isp_csi2_ctx_cfg *selected_ctx;
1188 + struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1191 + isp_csi2_ctx_validate(&ctxnum);
1193 + selected_ctx = ¤t_csi2_cfg.contexts[ctxnum];
1194 + selected_ctx_u = ¤t_csi2_cfg_update.contexts[ctxnum];
1196 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL1(ctxnum));
1197 + selected_ctx->frame_count = (reg & ISPCSI2_CTX_CTRL1_COUNT_MASK) >>
1198 + ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
1199 + selected_ctx_u->frame_count = false;
1201 + if ((reg & ISPCSI2_CTX_CTRL1_EOF_EN_MASK) ==
1202 + ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE)
1203 + selected_ctx->eof_enabled = true;
1205 + selected_ctx->eof_enabled = false;
1206 + selected_ctx_u->eof_enabled = false;
1208 + if ((reg & ISPCSI2_CTX_CTRL1_EOL_EN_MASK) ==
1209 + ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE)
1210 + selected_ctx->eol_enabled = true;
1212 + selected_ctx->eol_enabled = false;
1213 + selected_ctx_u->eol_enabled = false;
1215 + if ((reg & ISPCSI2_CTX_CTRL1_CS_EN_MASK) ==
1216 + ISPCSI2_CTX_CTRL1_CS_EN_ENABLE)
1217 + selected_ctx->checksum_enabled = true;
1219 + selected_ctx->checksum_enabled = false;
1220 + selected_ctx_u->checksum_enabled = false;
1222 + if ((reg & ISPCSI2_CTX_CTRL1_CTX_EN_MASK) ==
1223 + ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE)
1224 + selected_ctx->enabled = true;
1226 + selected_ctx->enabled = false;
1227 + selected_ctx_u->enabled = false;
1228 + update_ctx_ctrl1[ctxnum] = false;
1230 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL2(ctxnum));
1232 + selected_ctx->virtual_id = (reg & ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK) >>
1233 + ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
1234 + selected_ctx_u->virtual_id = false;
1236 + switch ((reg & ISPCSI2_CTX_CTRL2_FORMAT_MASK) >>
1237 + ISPCSI2_CTX_CTRL2_FORMAT_SHIFT) {
1239 + selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB565;
1243 + selected_ctx->format.pixelformat = V4L2_PIX_FMT_YUYV;
1246 + selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB555;
1250 + selected_ctx->format.pixelformat = V4L2_PIX_FMT_SGRBG10;
1253 + selected_ctx_u->format = false;
1254 + update_ctx_ctrl2[ctxnum] = false;
1256 + selected_ctx->alpha = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1257 + ISPCSI2_CTX_CTRL3(ctxnum)) &
1258 + ISPCSI2_CTX_CTRL3_ALPHA_MASK) >>
1259 + ISPCSI2_CTX_CTRL3_ALPHA_SHIFT;
1260 + selected_ctx_u->alpha = false;
1261 + update_ctx_ctrl3[ctxnum] = false;
1263 + selected_ctx->data_offset = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1264 + ISPCSI2_CTX_DAT_OFST(ctxnum)) &
1265 + ISPCSI2_CTX_DAT_OFST_OFST_MASK) >>
1266 + ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
1267 + selected_ctx_u->data_offset = false;
1269 + selected_ctx->ping_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1270 + ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
1271 + selected_ctx_u->ping_addr = false;
1273 + selected_ctx->pong_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1274 + ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
1275 + selected_ctx_u->pong_addr = false;
1280 + * isp_csi2_ctx_update_all - Applies all CSI2 context configuration.
1281 + * @force_update: Flag to force rewrite of registers, even if they haven't been
1282 + * updated with the isp_csi2_ctx_config_*() functions.
1284 + * It only saves settings when they were previously updated using the
1285 + * isp_csi2_ctx_config_*() functions, unless the force_update flag is
1287 + * Always returns 0.
1289 +int isp_csi2_ctx_update_all(bool force_update)
1293 + for (ctxnum = 0; ctxnum < 8; ctxnum++)
1294 + isp_csi2_ctx_update(ctxnum, force_update);
1300 + * isp_csi2_ctx_get_all - Gets all CSI2 Context configurations
1302 + * Always returns 0.
1304 +int isp_csi2_ctx_get_all(void)
1308 + for (ctxnum = 0; ctxnum < 8; ctxnum++)
1309 + isp_csi2_ctx_get(ctxnum);
1314 +int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig)
1316 + struct isp_csi2_phy_cfg *currphy = ¤t_csi2_cfg.phy;
1317 + struct isp_csi2_phy_cfg_update *currphy_u =
1318 + ¤t_csi2_cfg_update.phy;
1320 + if ((desiredphyconfig->tclk_term > 0x7f) ||
1321 + (desiredphyconfig->tclk_miss > 0x3)) {
1322 + printk(KERN_ERR "Invalid PHY configuration sent by the"
1327 + if (currphy->ths_term != desiredphyconfig->ths_term) {
1328 + currphy->ths_term = desiredphyconfig->ths_term;
1329 + currphy_u->ths_term = true;
1330 + update_phy_cfg0 = true;
1332 + if (currphy->ths_settle != desiredphyconfig->ths_settle) {
1333 + currphy->ths_settle = desiredphyconfig->ths_settle;
1334 + currphy_u->ths_settle = true;
1335 + update_phy_cfg0 = true;
1337 + if (currphy->tclk_term != desiredphyconfig->tclk_term) {
1338 + currphy->tclk_term = desiredphyconfig->tclk_term;
1339 + currphy_u->tclk_term = true;
1340 + update_phy_cfg1 = true;
1342 + if (currphy->tclk_miss != desiredphyconfig->tclk_miss) {
1343 + currphy->tclk_miss = desiredphyconfig->tclk_miss;
1344 + currphy_u->tclk_miss = true;
1345 + update_phy_cfg1 = true;
1347 + if (currphy->tclk_settle != desiredphyconfig->tclk_settle) {
1348 + currphy->tclk_settle = desiredphyconfig->tclk_settle;
1349 + currphy_u->tclk_settle = true;
1350 + update_phy_cfg1 = true;
1356 + * isp_csi2_calc_phy_cfg0 - Calculates D-PHY config based on the MIPIClk speed.
1357 + * @mipiclk: MIPI clock frequency being used with CSI2 sensor.
1358 + * @lbound_hs_settle: Lower bound for CSI2 High Speed Settle transition.
1359 + * @ubound_hs_settle: Upper bound for CSI2 High Speed Settle transition.
1361 + * From TRM, we have the same calculation for HS Termination signal.
1362 + * THS_TERM = ceil( 12.5ns / DDRCLK period ) - 1
1363 + * But for Settle, we use the mid value between the two passed boundaries from
1365 + * THS_SETTLE = (Upper bound + Lower bound) / 2
1367 + * Always returns 0.
1369 +int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
1370 + u32 ubound_hs_settle)
1372 + struct isp_csi2_phy_cfg *currphy = ¤t_csi2_cfg.phy;
1373 + struct isp_csi2_phy_cfg_update *currphy_u =
1374 + ¤t_csi2_cfg_update.phy;
1375 + u32 tmp, ddrclk = mipiclk >> 1;
1377 + /* Calculate THS_TERM */
1378 + tmp = ddrclk / 80000000;
1379 + if ((ddrclk % 80000000) > 0)
1381 + currphy->ths_term = tmp - 1;
1382 + currphy_u->ths_term = true;
1384 + /* Calculate THS_SETTLE */
1385 + currphy->ths_settle = (ubound_hs_settle + lbound_hs_settle) / 2;
1387 + currphy_u->ths_settle = true;
1388 + isp_csi2_phy_update(true);
1391 +EXPORT_SYMBOL(isp_csi2_calc_phy_cfg0);
1394 + * isp_csi2_phy_update - Applies CSI2 D-PHY configuration.
1395 + * @force_update: Flag to force rewrite of registers, even if they haven't been
1396 + * updated with the isp_csi2_phy_config_*() functions.
1398 + * It only saves settings when they were previously updated using the
1399 + * isp_csi2_phy_config_*() functions, unless the force_update flag is
1401 + * Always returns 0.
1403 +int isp_csi2_phy_update(bool force_update)
1405 + struct isp_csi2_phy_cfg *currphy = ¤t_csi2_cfg.phy;
1406 + struct isp_csi2_phy_cfg_update *currphy_u =
1407 + ¤t_csi2_cfg_update.phy;
1410 + if (update_phy_cfg0 || force_update) {
1411 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1412 + if (currphy_u->ths_term || force_update) {
1413 + reg &= ~ISPCSI2PHY_CFG0_THS_TERM_MASK;
1414 + reg |= (currphy->ths_term <<
1415 + ISPCSI2PHY_CFG0_THS_TERM_SHIFT);
1416 + currphy_u->ths_term = false;
1418 + if (currphy_u->ths_settle || force_update) {
1419 + reg &= ~ISPCSI2PHY_CFG0_THS_SETTLE_MASK;
1420 + reg |= (currphy->ths_settle <<
1421 + ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT);
1422 + currphy_u->ths_settle = false;
1424 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1425 + update_phy_cfg0 = false;
1428 + if (update_phy_cfg1 || force_update) {
1429 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1430 + if (currphy_u->tclk_term || force_update) {
1431 + reg &= ~ISPCSI2PHY_CFG1_TCLK_TERM_MASK;
1432 + reg |= (currphy->tclk_term <<
1433 + ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT);
1434 + currphy_u->tclk_term = false;
1436 + if (currphy_u->tclk_miss || force_update) {
1437 + reg &= ~ISPCSI2PHY_CFG1_TCLK_MISS_MASK;
1438 + reg |= (currphy->tclk_miss <<
1439 + ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT);
1440 + currphy_u->tclk_miss = false;
1442 + if (currphy_u->tclk_settle || force_update) {
1443 + reg &= ~ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK;
1444 + reg |= (currphy->tclk_settle <<
1445 + ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT);
1446 + currphy_u->tclk_settle = false;
1448 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1449 + update_phy_cfg1 = false;
1455 + * isp_csi2_phy_get - Gets CSI2 D-PHY configuration
1457 + * Gets settings from HW registers and fills in the internal driver memory
1458 + * Always returns 0.
1460 +int isp_csi2_phy_get(void)
1462 + struct isp_csi2_phy_cfg *currphy = ¤t_csi2_cfg.phy;
1463 + struct isp_csi2_phy_cfg_update *currphy_u =
1464 + ¤t_csi2_cfg_update.phy;
1467 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1468 + currphy->ths_term = (reg & ISPCSI2PHY_CFG0_THS_TERM_MASK) >>
1469 + ISPCSI2PHY_CFG0_THS_TERM_SHIFT;
1470 + currphy_u->ths_term = false;
1472 + currphy->ths_settle = (reg & ISPCSI2PHY_CFG0_THS_SETTLE_MASK) >>
1473 + ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT;
1474 + currphy_u->ths_settle = false;
1475 + update_phy_cfg0 = false;
1477 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1479 + currphy->tclk_term = (reg & ISPCSI2PHY_CFG1_TCLK_TERM_MASK) >>
1480 + ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT;
1481 + currphy_u->tclk_term = false;
1483 + currphy->tclk_miss = (reg & ISPCSI2PHY_CFG1_TCLK_MISS_MASK) >>
1484 + ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT;
1485 + currphy_u->tclk_miss = false;
1487 + currphy->tclk_settle = (reg & ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK) >>
1488 + ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT;
1489 + currphy_u->tclk_settle = false;
1491 + update_phy_cfg1 = false;
1496 + * isp_csi2_timings_config_forcerxmode - Sets Force Rx mode on stop state count
1497 + * @force_rx_mode: Boolean to enable/disable forcing Rx mode in CSI2 receiver
1499 + * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1501 +int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode)
1503 + struct isp_csi2_timings_cfg *currtimings;
1504 + struct isp_csi2_timings_cfg_update *currtimings_u;
1506 + if (io < 1 || io > 2) {
1507 + printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1511 + currtimings = ¤t_csi2_cfg.timings[io - 1];
1512 + currtimings_u = ¤t_csi2_cfg_update.timings[io - 1];
1513 + if (currtimings->force_rx_mode != force_rx_mode) {
1514 + currtimings->force_rx_mode = force_rx_mode;
1515 + currtimings_u->force_rx_mode = true;
1516 + update_timing = true;
1522 + * isp_csi2_timings_config_stopstate_16x - Sets 16x factor for L3 cycles
1523 + * @stop_state_16x: Boolean to use or not use the 16x multiplier for stop count
1525 + * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1527 +int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x)
1529 + struct isp_csi2_timings_cfg *currtimings;
1530 + struct isp_csi2_timings_cfg_update *currtimings_u;
1532 + if (io < 1 || io > 2) {
1533 + printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1537 + currtimings = ¤t_csi2_cfg.timings[io - 1];
1538 + currtimings_u = ¤t_csi2_cfg_update.timings[io - 1];
1539 + if (currtimings->stop_state_16x != stop_state_16x) {
1540 + currtimings->stop_state_16x = stop_state_16x;
1541 + currtimings_u->stop_state_16x = true;
1542 + update_timing = true;
1548 + * isp_csi2_timings_config_stopstate_4x - Sets 4x factor for L3 cycles
1549 + * @stop_state_4x: Boolean to use or not use the 4x multiplier for stop count
1551 + * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1553 +int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x)
1555 + struct isp_csi2_timings_cfg *currtimings;
1556 + struct isp_csi2_timings_cfg_update *currtimings_u;
1558 + if (io < 1 || io > 2) {
1559 + printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1563 + currtimings = ¤t_csi2_cfg.timings[io - 1];
1564 + currtimings_u = ¤t_csi2_cfg_update.timings[io - 1];
1565 + if (currtimings->stop_state_4x != stop_state_4x) {
1566 + currtimings->stop_state_4x = stop_state_4x;
1567 + currtimings_u->stop_state_4x = true;
1568 + update_timing = true;
1574 + * isp_csi2_timings_config_stopstate_cnt - Sets L3 cycles
1575 + * @stop_state_counter: Stop state counter value for L3 cycles
1577 + * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1579 +int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter)
1581 + struct isp_csi2_timings_cfg *currtimings;
1582 + struct isp_csi2_timings_cfg_update *currtimings_u;
1584 + if (io < 1 || io > 2) {
1585 + printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1589 + currtimings = ¤t_csi2_cfg.timings[io - 1];
1590 + currtimings_u = ¤t_csi2_cfg_update.timings[io - 1];
1591 + if (currtimings->stop_state_counter != stop_state_counter) {
1592 + currtimings->stop_state_counter = (stop_state_counter & 0x1FFF);
1593 + currtimings_u->stop_state_counter = true;
1594 + update_timing = true;
1600 + * isp_csi2_timings_update - Applies specified CSI2 timing configuration.
1601 + * @io: IO number (1 or 2) which specifies which ComplexIO are we updating
1602 + * @force_update: Flag to force rewrite of registers, even if they haven't been
1603 + * updated with the isp_csi2_timings_config_*() functions.
1605 + * It only saves settings when they were previously updated using the
1606 + * isp_csi2_timings_config_*() functions, unless the force_update flag is
1608 + * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
1610 +int isp_csi2_timings_update(u8 io, bool force_update)
1612 + struct isp_csi2_timings_cfg *currtimings;
1613 + struct isp_csi2_timings_cfg_update *currtimings_u;
1616 + if (io < 1 || io > 2) {
1617 + printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1621 + currtimings = ¤t_csi2_cfg.timings[io - 1];
1622 + currtimings_u = ¤t_csi2_cfg_update.timings[io - 1];
1624 + if (update_timing || force_update) {
1625 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1626 + if (currtimings_u->force_rx_mode || force_update) {
1627 + reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io);
1628 + if (currtimings->force_rx_mode)
1629 + reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE
1632 + reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE
1634 + currtimings_u->force_rx_mode = false;
1636 + if (currtimings_u->stop_state_16x || force_update) {
1637 + reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io);
1638 + if (currtimings->stop_state_16x)
1639 + reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE
1642 + reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE
1644 + currtimings_u->stop_state_16x = false;
1646 + if (currtimings_u->stop_state_4x || force_update) {
1647 + reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io);
1648 + if (currtimings->stop_state_4x) {
1649 + reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE
1652 + reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE
1655 + currtimings_u->stop_state_4x = false;
1657 + if (currtimings_u->stop_state_counter || force_update) {
1658 + reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io);
1659 + reg |= currtimings->stop_state_counter <<
1660 + ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
1661 + currtimings_u->stop_state_counter = false;
1663 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1664 + update_timing = false;
1670 + * isp_csi2_timings_get - Gets specific CSI2 ComplexIO timing configuration
1671 + * @io: IO number (1 or 2) which specifies which ComplexIO are we getting
1673 + * Gets settings from HW registers and fills in the internal driver memory
1674 + * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
1676 +int isp_csi2_timings_get(u8 io)
1678 + struct isp_csi2_timings_cfg *currtimings;
1679 + struct isp_csi2_timings_cfg_update *currtimings_u;
1682 + if (io < 1 || io > 2) {
1683 + printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1687 + currtimings = ¤t_csi2_cfg.timings[io - 1];
1688 + currtimings_u = ¤t_csi2_cfg_update.timings[io - 1];
1690 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1691 + if ((reg & ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io)) ==
1692 + ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(io))
1693 + currtimings->force_rx_mode = true;
1695 + currtimings->force_rx_mode = false;
1696 + currtimings_u->force_rx_mode = false;
1698 + if ((reg & ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io)) ==
1699 + ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(io))
1700 + currtimings->stop_state_16x = true;
1702 + currtimings->stop_state_16x = false;
1703 + currtimings_u->stop_state_16x = false;
1705 + if ((reg & ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io)) ==
1706 + ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(io))
1707 + currtimings->stop_state_4x = true;
1709 + currtimings->stop_state_4x = false;
1710 + currtimings_u->stop_state_4x = false;
1712 + currtimings->stop_state_counter = (reg &
1713 + ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io)) >>
1714 + ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
1715 + currtimings_u->stop_state_counter = false;
1716 + update_timing = false;
1721 + * isp_csi2_timings_update_all - Applies specified CSI2 timing configuration.
1722 + * @force_update: Flag to force rewrite of registers, even if they haven't been
1723 + * updated with the isp_csi2_timings_config_*() functions.
1725 + * It only saves settings when they were previously updated using the
1726 + * isp_csi2_timings_config_*() functions, unless the force_update flag is
1728 + * Always returns 0.
1730 +int isp_csi2_timings_update_all(bool force_update)
1734 + for (i = 1; i < 3; i++)
1735 + isp_csi2_timings_update(i, force_update);
1740 + * isp_csi2_timings_get_all - Gets all CSI2 ComplexIO timing configurations
1742 + * Always returns 0.
1744 +int isp_csi2_timings_get_all(void)
1748 + for (i = 1; i < 3; i++)
1749 + isp_csi2_timings_get(i);
1754 + * isp_csi2_isr - CSI2 interrupt handling.
1756 +void isp_csi2_isr(void)
1758 + u32 csi2_irqstatus, cpxio1_irqstatus, ctxirqstatus;
1760 + csi2_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1761 + ISPCSI2_IRQSTATUS);
1762 + isp_reg_writel(csi2_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
1763 + ISPCSI2_IRQSTATUS);
1765 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
1766 + cpxio1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1767 + ISPCSI2_COMPLEXIO1_IRQSTATUS);
1768 + isp_reg_writel(cpxio1_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
1769 + ISPCSI2_COMPLEXIO1_IRQSTATUS);
1770 + printk(KERN_ERR "CSI2: ComplexIO Error IRQ %x\n",
1771 + cpxio1_irqstatus);
1774 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) {
1775 + ctxirqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1776 + ISPCSI2_CTX_IRQSTATUS(0));
1777 + isp_reg_writel(ctxirqstatus, OMAP3_ISP_IOMEM_CSI2A,
1778 + ISPCSI2_CTX_IRQSTATUS(0));
1781 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_OCP_ERR_IRQ)
1782 + printk(KERN_ERR "CSI2: OCP Transmission Error\n");
1784 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ)
1785 + printk(KERN_ERR "CSI2: Short packet receive error\n");
1787 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
1788 + printk(KERN_DEBUG "CSI2: ECC correction done\n");
1790 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ)
1791 + printk(KERN_ERR "CSI2: ECC correction failed\n");
1793 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ)
1794 + printk(KERN_ERR "CSI2: ComplexIO #2 failed\n");
1796 + if (csi2_irqstatus & ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)
1797 + printk(KERN_ERR "CSI2: FIFO overflow error\n");
1801 +EXPORT_SYMBOL(isp_csi2_isr);
1804 + * isp_csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
1805 + * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
1807 +void isp_csi2_irq_complexio1_set(int enable)
1810 + reg = ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT |
1811 + ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER |
1812 + ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5 |
1813 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5 |
1814 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5 |
1815 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5 |
1816 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5 |
1817 + ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4 |
1818 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4 |
1819 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4 |
1820 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4 |
1821 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4 |
1822 + ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3 |
1823 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3 |
1824 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3 |
1825 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3 |
1826 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3 |
1827 + ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2 |
1828 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2 |
1829 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2 |
1830 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2 |
1831 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2 |
1832 + ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1 |
1833 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1 |
1834 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1 |
1835 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1 |
1836 + ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1;
1837 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1838 + ISPCSI2_COMPLEXIO1_IRQSTATUS);
1840 + reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1841 + ISPCSI2_COMPLEXIO1_IRQENABLE);
1844 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1845 + ISPCSI2_COMPLEXIO1_IRQENABLE);
1847 +EXPORT_SYMBOL(isp_csi2_irq_complexio1_set);
1850 + * isp_csi2_irq_ctx_set - Enables CSI2 Context IRQs.
1851 + * @enable: Enable/disable CSI2 Context interrupts
1853 +void isp_csi2_irq_ctx_set(int enable)
1858 + reg = ISPCSI2_CTX_IRQSTATUS_FS_IRQ | ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
1859 + for (i = 0; i < 8; i++) {
1860 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1861 + ISPCSI2_CTX_IRQSTATUS(i));
1863 + isp_reg_or(OMAP3_ISP_IOMEM_CSI2A,
1864 + ISPCSI2_CTX_IRQENABLE(i), reg);
1866 + isp_reg_writel(0, OMAP3_ISP_IOMEM_CSI2A,
1867 + ISPCSI2_CTX_IRQENABLE(i));
1872 +EXPORT_SYMBOL(isp_csi2_irq_ctx_set);
1875 + * isp_csi2_irq_status_set - Enables CSI2 Status IRQs.
1876 + * @enable: Enable/disable CSI2 Status interrupts
1878 +void isp_csi2_irq_status_set(int enable)
1881 + reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
1882 + ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
1883 + ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
1884 + ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
1885 + ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
1886 + ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
1887 + ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
1888 + ISPCSI2_IRQSTATUS_CONTEXT(0);
1889 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQSTATUS);
1891 + reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
1895 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
1897 +EXPORT_SYMBOL(isp_csi2_irq_status_set);
1900 + * isp_csi2_irq_status_set - Enables main CSI2 IRQ.
1901 + * @enable: Enable/disable main CSI2 interrupt
1903 +void isp_csi2_irq_set(int enable)
1905 + isp_reg_writel(IRQ0STATUS_CSIA_IRQ, OMAP3_ISP_IOMEM_MAIN,
1907 + isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
1908 + ~IRQ0ENABLE_CSIA_IRQ,
1909 + (enable ? IRQ0ENABLE_CSIA_IRQ : 0));
1911 +EXPORT_SYMBOL(isp_csi2_irq_set);
1914 + * isp_csi2_irq_all_set - Enable/disable CSI2 interrupts.
1915 + * @enable: 0-Disable, 1-Enable.
1917 +void isp_csi2_irq_all_set(int enable)
1920 + isp_csi2_irq_complexio1_set(enable);
1921 + isp_csi2_irq_ctx_set(enable);
1922 + isp_csi2_irq_status_set(enable);
1923 + isp_csi2_irq_set(enable);
1925 + isp_csi2_irq_set(enable);
1926 + isp_csi2_irq_status_set(enable);
1927 + isp_csi2_irq_ctx_set(enable);
1928 + isp_csi2_irq_complexio1_set(enable);
1932 +EXPORT_SYMBOL(isp_csi2_irq_all_set);
1935 + * isp_csi2_reset - Resets the CSI2 module.
1937 + * Returns 0 if successful, or -EBUSY if power command didn't respond.
1939 +int isp_csi2_reset(void)
1942 + u8 soft_reset_retries = 0;
1945 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1946 + reg |= ISPCSI2_SYSCONFIG_SOFT_RESET_RESET;
1947 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1950 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSSTATUS) &
1951 + ISPCSI2_SYSSTATUS_RESET_DONE_MASK;
1952 + if (reg == ISPCSI2_SYSSTATUS_RESET_DONE_DONE)
1954 + soft_reset_retries++;
1955 + if (soft_reset_retries < 5)
1957 + } while (soft_reset_retries < 5);
1959 + if (soft_reset_retries == 5) {
1960 + printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
1964 + reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1965 + reg &= ~ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK;
1966 + reg |= ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO;
1967 + reg &= ~ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK;
1968 + isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1970 + uses_videoport = false;
1971 + update_complexio_cfg1 = false;
1972 + update_phy_cfg0 = false;
1973 + update_phy_cfg1 = false;
1974 + for (i = 0; i < 8; i++) {
1975 + update_ctx_ctrl1[i] = false;
1976 + update_ctx_ctrl2[i] = false;
1977 + update_ctx_ctrl3[i] = false;
1979 + update_timing = false;
1980 + update_ctrl = false;
1982 + isp_csi2_complexio_lanes_get();
1983 + isp_csi2_ctrl_get();
1984 + isp_csi2_ctx_get_all();
1985 + isp_csi2_phy_get();
1986 + isp_csi2_timings_get_all();
1988 + isp_csi2_complexio_power_autoswitch(true);
1989 + isp_csi2_complexio_power(ISP_CSI2_POWER_ON);
1991 + isp_csi2_timings_config_forcerxmode(1, true);
1992 + isp_csi2_timings_config_stopstate_cnt(1, 0x1FF);
1993 + isp_csi2_timings_update_all(true);
1999 + * isp_csi2_enable - Enables the CSI2 module.
2000 + * @enable: Enables/disables the CSI2 module.
2002 +void isp_csi2_enable(int enable)
2005 + isp_csi2_ctx_config_enabled(0, true);
2006 + isp_csi2_ctx_config_eof_enabled(0, true);
2007 + isp_csi2_ctx_config_checksum_enabled(0, true);
2008 + isp_csi2_ctx_update(0, false);
2010 + isp_csi2_ctrl_config_ecc_enable(true);
2011 + isp_csi2_ctrl_config_if_enable(true);
2012 + isp_csi2_ctrl_update(false);
2014 + isp_csi2_ctx_config_enabled(0, false);
2015 + isp_csi2_ctx_config_eof_enabled(0, false);
2016 + isp_csi2_ctx_config_checksum_enabled(0, false);
2017 + isp_csi2_ctx_update(0, false);
2019 + isp_csi2_ctrl_config_ecc_enable(false);
2020 + isp_csi2_ctrl_config_if_enable(false);
2021 + isp_csi2_ctrl_update(false);
2024 +EXPORT_SYMBOL(isp_csi2_enable);
2027 + * isp_csi2_regdump - Prints CSI2 debug information.
2029 +void isp_csi2_regdump(void)
2031 + printk(KERN_DEBUG "-------------Register dump-------------\n");
2033 + printk(KERN_DEBUG "ISP_CTRL: %x\n",
2034 + isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
2035 + printk(KERN_DEBUG "ISP_TCTRL_CTRL: %x\n",
2036 + isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
2038 + printk(KERN_DEBUG "ISPCCDC_SDR_ADDR: %x\n",
2039 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
2040 + printk(KERN_DEBUG "ISPCCDC_SYN_MODE: %x\n",
2041 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
2042 + printk(KERN_DEBUG "ISPCCDC_CFG: %x\n",
2043 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
2044 + printk(KERN_DEBUG "ISPCCDC_FMTCFG: %x\n",
2045 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
2046 + printk(KERN_DEBUG "ISPCCDC_HSIZE_OFF: %x\n",
2047 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
2048 + printk(KERN_DEBUG "ISPCCDC_HORZ_INFO: %x\n",
2049 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
2050 + printk(KERN_DEBUG "ISPCCDC_VERT_START: %x\n",
2051 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
2052 + ISPCCDC_VERT_START));
2053 + printk(KERN_DEBUG "ISPCCDC_VERT_LINES: %x\n",
2054 + isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
2055 + ISPCCDC_VERT_LINES));
2057 + printk(KERN_DEBUG "ISPCSI2_COMPLEXIO_CFG1: %x\n",
2058 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2059 + ISPCSI2_COMPLEXIO_CFG1));
2060 + printk(KERN_DEBUG "ISPCSI2_SYSSTATUS: %x\n",
2061 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2062 + ISPCSI2_SYSSTATUS));
2063 + printk(KERN_DEBUG "ISPCSI2_SYSCONFIG: %x\n",
2064 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2065 + ISPCSI2_SYSCONFIG));
2066 + printk(KERN_DEBUG "ISPCSI2_IRQENABLE: %x\n",
2067 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2068 + ISPCSI2_IRQENABLE));
2069 + printk(KERN_DEBUG "ISPCSI2_IRQSTATUS: %x\n",
2070 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2071 + ISPCSI2_IRQSTATUS));
2073 + printk(KERN_DEBUG "ISPCSI2_CTX_IRQENABLE(0): %x\n",
2074 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2075 + ISPCSI2_CTX_IRQENABLE(0)));
2076 + printk(KERN_DEBUG "ISPCSI2_CTX_IRQSTATUS(0): %x\n",
2077 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2078 + ISPCSI2_CTX_IRQSTATUS(0)));
2079 + printk(KERN_DEBUG "ISPCSI2_TIMING: %x\n",
2080 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING));
2081 + printk(KERN_DEBUG "ISPCSI2PHY_CFG0: %x\n",
2082 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
2083 + ISPCSI2PHY_CFG0));
2084 + printk(KERN_DEBUG "ISPCSI2PHY_CFG1: %x\n",
2085 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
2086 + ISPCSI2PHY_CFG1));
2087 + printk(KERN_DEBUG "ISPCSI2_CTX_CTRL1(0): %x\n",
2088 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2089 + ISPCSI2_CTX_CTRL1(0)));
2090 + printk(KERN_DEBUG "ISPCSI2_CTX_CTRL2(0): %x\n",
2091 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2092 + ISPCSI2_CTX_CTRL2(0)));
2093 + printk(KERN_DEBUG "ISPCSI2_CTX_CTRL3(0): %x\n",
2094 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2095 + ISPCSI2_CTX_CTRL3(0)));
2096 + printk(KERN_DEBUG "ISPCSI2_CTX_DAT_OFST(0): %x\n",
2097 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2098 + ISPCSI2_CTX_DAT_OFST(0)));
2099 + printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PING_ADDR(0): %x\n",
2100 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2101 + ISPCSI2_CTX_DAT_PING_ADDR(0)));
2102 + printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PONG_ADDR(0): %x\n",
2103 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2104 + ISPCSI2_CTX_DAT_PONG_ADDR(0)));
2105 + printk(KERN_DEBUG "ISPCSI2_CTRL: %x\n",
2106 + isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL));
2107 + printk(KERN_DEBUG "---------------------------------------\n");
2111 + * isp_csi2_cleanup - Routine for module driver cleanup
2113 +void isp_csi2_cleanup(void)
2119 + * isp_csi2_init - Routine for module driver init
2121 +int __init isp_csi2_init(void)
2125 + update_complexio_cfg1 = false;
2126 + update_phy_cfg0 = false;
2127 + update_phy_cfg1 = false;
2128 + for (i = 0; i < 8; i++) {
2129 + update_ctx_ctrl1[i] = false;
2130 + update_ctx_ctrl2[i] = false;
2131 + update_ctx_ctrl3[i] = false;
2133 + update_timing = false;
2134 + update_ctrl = false;
2136 + memset(¤t_csi2_cfg, 0, sizeof(current_csi2_cfg));
2137 + memset(¤t_csi2_cfg_update, 0, sizeof(current_csi2_cfg_update));
2141 +MODULE_AUTHOR("Texas Instruments");
2142 +MODULE_DESCRIPTION("ISP CSI2 Receiver Module");
2143 +MODULE_LICENSE("GPL");
2144 diff --git a/drivers/media/video/isp/ispcsi2.h b/drivers/media/video/isp/ispcsi2.h
2145 new file mode 100644
2146 index 0000000..4582c96
2148 +++ b/drivers/media/video/isp/ispcsi2.h
2153 + * Copyright (C) 2009 Texas Instruments.
2156 + * Sergio Aguirre <saaguirre@ti.com>
2157 + * Dominic Curran <dcurran@ti.com>
2159 + * This package is free software; you can redistribute it and/or modify
2160 + * it under the terms of the GNU General Public License version 2 as
2161 + * published by the Free Software Foundation.
2163 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2164 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2165 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2168 +#ifndef OMAP_ISP_CSI2_API_H
2169 +#define OMAP_ISP_CSI2_API_H
2170 +#include <linux/videodev2.h>
2172 +enum isp_csi2_irqevents {
2173 + OCP_ERR_IRQ = 0x4000,
2174 + SHORT_PACKET_IRQ = 0x2000,
2175 + ECC_CORRECTION_IRQ = 0x1000,
2176 + ECC_NO_CORRECTION_IRQ = 0x800,
2177 + COMPLEXIO2_ERR_IRQ = 0x400,
2178 + COMPLEXIO1_ERR_IRQ = 0x200,
2179 + FIFO_OVF_IRQ = 0x100,
2190 +enum isp_csi2_ctx_irqevents {
2191 + CTX_ECC_CORRECTION = 0x100,
2192 + CTX_LINE_NUMBER = 0x80,
2193 + CTX_FRAME_NUMBER = 0x40,
2201 +enum isp_csi2_power_cmds {
2202 + ISP_CSI2_POWER_OFF,
2203 + ISP_CSI2_POWER_ON,
2204 + ISP_CSI2_POWER_ULPW,
2207 +enum isp_csi2_frame_mode {
2208 + ISP_CSI2_FRAME_IMMEDIATE,
2209 + ISP_CSI2_FRAME_AFTERFEC,
2212 +struct csi2_lanecfg {
2217 +struct isp_csi2_lanes_cfg {
2218 + struct csi2_lanecfg data[4];
2219 + struct csi2_lanecfg clk;
2222 +struct isp_csi2_lanes_cfg_update {
2227 +struct isp_csi2_phy_cfg {
2231 + unsigned tclk_miss:1;
2235 +struct isp_csi2_phy_cfg_update {
2243 +struct isp_csi2_ctx_cfg {
2246 + struct v4l2_pix_format format;
2253 + bool checksum_enabled;
2257 +struct isp_csi2_ctx_cfg_update {
2267 + bool checksum_enabled;
2271 +struct isp_csi2_timings_cfg {
2272 + bool force_rx_mode;
2273 + bool stop_state_16x;
2274 + bool stop_state_4x;
2275 + u16 stop_state_counter;
2278 +struct isp_csi2_timings_cfg_update {
2279 + bool force_rx_mode;
2280 + bool stop_state_16x;
2281 + bool stop_state_4x;
2282 + bool stop_state_counter;
2285 +struct isp_csi2_ctrl_cfg {
2286 + bool vp_clk_enable;
2287 + bool vp_only_enable;
2289 + bool debug_enable;
2291 + enum isp_csi2_frame_mode frame_mode;
2297 +struct isp_csi2_ctrl_cfg_update {
2298 + bool vp_clk_enable;
2299 + bool vp_only_enable;
2301 + bool debug_enable;
2309 +struct isp_csi2_cfg {
2310 + struct isp_csi2_lanes_cfg lanes;
2311 + struct isp_csi2_phy_cfg phy;
2312 + struct isp_csi2_ctx_cfg contexts[8];
2313 + struct isp_csi2_timings_cfg timings[2];
2314 + struct isp_csi2_ctrl_cfg ctrl;
2317 +struct isp_csi2_cfg_update {
2318 + struct isp_csi2_lanes_cfg_update lanes;
2319 + struct isp_csi2_phy_cfg_update phy;
2320 + struct isp_csi2_ctx_cfg_update contexts[8];
2321 + struct isp_csi2_timings_cfg_update timings[2];
2322 + struct isp_csi2_ctrl_cfg_update ctrl;
2325 +int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg);
2326 +int isp_csi2_complexio_lanes_update(bool force_update);
2327 +int isp_csi2_complexio_lanes_get(void);
2328 +int isp_csi2_complexio_power_autoswitch(bool enable);
2329 +int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd);
2330 +int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode);
2331 +int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable);
2332 +int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable);
2333 +int isp_csi2_ctrl_config_debug_enable(bool debug_enable);
2334 +int isp_csi2_ctrl_config_burst_size(u8 burst_size);
2335 +int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable);
2336 +int isp_csi2_ctrl_config_secure_mode(bool secure_mode);
2337 +int isp_csi2_ctrl_config_if_enable(bool if_enable);
2338 +int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl);
2339 +int isp_csi2_ctrl_update(bool force_update);
2340 +int isp_csi2_ctrl_get(void);
2341 +int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id);
2342 +int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count);
2343 +int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat);
2344 +int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha);
2345 +int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset);
2346 +int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr);
2347 +int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr);
2348 +int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled);
2349 +int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled);
2350 +int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled);
2351 +int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled);
2352 +int isp_csi2_ctx_update(u8 ctxnum, bool force_update);
2353 +int isp_csi2_ctx_get(u8 ctxnum);
2354 +int isp_csi2_ctx_update_all(bool force_update);
2355 +int isp_csi2_ctx_get_all(void);
2356 +int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig);
2357 +int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
2358 + u32 ubound_hs_settle);
2359 +int isp_csi2_phy_update(bool force_update);
2360 +int isp_csi2_phy_get(void);
2361 +int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode);
2362 +int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x);
2363 +int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x);
2364 +int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter);
2365 +int isp_csi2_timings_update(u8 io, bool force_update);
2366 +int isp_csi2_timings_get(u8 io);
2367 +int isp_csi2_timings_update_all(bool force_update);
2368 +int isp_csi2_timings_get_all(void);
2369 +void isp_csi2_irq_complexio1_set(int enable);
2370 +void isp_csi2_irq_ctx_set(int enable);
2371 +void isp_csi2_irq_status_set(int enable);
2372 +void isp_csi2_irq_set(int enable);
2373 +void isp_csi2_irq_all_set(int enable);
2375 +void isp_csi2_isr(void);
2376 +int isp_csi2_reset(void);
2377 +void isp_csi2_enable(int enable);
2378 +void isp_csi2_regdump(void);
2380 +#endif /* OMAP_ISP_CSI2_H */