summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch2384
1 files changed, 2384 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
new file mode 100644
index 0000000000..842f395388
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
@@ -0,0 +1,2384 @@
1From 9fbe7b786427d981cac890a7407da09232f5d1e2 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add CSI2 interface support
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
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
13
14diff --git a/drivers/media/video/isp/ispcsi2.c b/drivers/media/video/isp/ispcsi2.c
15new file mode 100644
16index 0000000..5141b5a
17--- /dev/null
18+++ b/drivers/media/video/isp/ispcsi2.c
19@@ -0,0 +1,2124 @@
20+/*
21+ * ispcsi2.c
22+ *
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.
25+ *
26+ * Copyright (C) 2009 Texas Instruments.
27+ *
28+ * Contributors:
29+ * Sergio Aguirre <saaguirre@ti.com>
30+ * Dominic Curran <dcurran@ti.com>
31+ *
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.
35+ *
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.
39+ */
40+
41+#include <linux/delay.h>
42+#include <media/v4l2-common.h>
43+
44+#include "isp.h"
45+#include "ispreg.h"
46+#include "ispcsi2.h"
47+
48+static struct isp_csi2_cfg current_csi2_cfg;
49+static struct isp_csi2_cfg_update current_csi2_cfg_update;
50+
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;
60+
61+/**
62+ * isp_csi2_complexio_lanes_config - Configuration of CSI2 ComplexIO lanes.
63+ * @reqcfg: Pointer to structure containing desired lane configuration
64+ *
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.
70+ **/
71+int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg)
72+{
73+ int i;
74+ bool pos_occupied[5] = {false, false, false, false, false};
75+ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
76+ struct isp_csi2_lanes_cfg_update *currlanes_u =
77+ &current_csi2_cfg_update.lanes;
78+
79+ /* Validating parameters sent by driver */
80+ if (reqcfg == NULL) {
81+ printk(KERN_ERR "Invalid Complex IO Configuration sent by"
82+ " sensor\n");
83+ goto err_einval;
84+ }
85+
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);
91+ goto err_einval;
92+ }
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);
97+ goto err_einval;
98+ } else
99+ pos_occupied[reqcfg->data[i].pos - 1] = true;
100+ }
101+
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");
107+ goto err_einval;
108+ }
109+ if (pos_occupied[reqcfg->clk.pos - 1]) {
110+ printk(KERN_ERR "Lane #%d already occupied",
111+ reqcfg->clk.pos);
112+ goto err_einval;
113+ } else
114+ pos_occupied[reqcfg->clk.pos - 1] = true;
115+
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;
121+ }
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;
126+ }
127+ }
128+
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;
133+ }
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;
138+ }
139+ return 0;
140+err_einval:
141+ return -EINVAL;
142+}
143+
144+/**
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.
148+ *
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
151+ * set to true.
152+ * Always returns 0.
153+ **/
154+int isp_csi2_complexio_lanes_update(bool force_update)
155+{
156+ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
157+ struct isp_csi2_lanes_cfg_update *currlanes_u =
158+ &current_csi2_cfg_update.lanes;
159+ u32 reg;
160+ int i;
161+
162+ if (!update_complexio_cfg1 && !force_update)
163+ return 0;
164+
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 +
170+ 1));
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 +
175+ 1));
176+ currlanes_u->data[i] = false;
177+ }
178+ }
179+
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;
188+ }
189+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
190+
191+ update_complexio_cfg1 = false;
192+ return 0;
193+}
194+
195+/**
196+ * isp_csi2_complexio_lanes_get - Gets CSI2 ComplexIO lanes configuration.
197+ *
198+ * Gets settings from HW registers and fills in the internal driver memory
199+ * Always returns 0.
200+ **/
201+int isp_csi2_complexio_lanes_get(void)
202+{
203+ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
204+ struct isp_csi2_lanes_cfg_update *currlanes_u =
205+ &current_csi2_cfg_update.lanes;
206+ u32 reg;
207+ int i;
208+
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;
218+ }
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;
225+
226+ update_complexio_cfg1 = false;
227+ return 0;
228+}
229+
230+/**
231+ * isp_csi2_complexio_power_status - Gets CSI2 ComplexIO power status.
232+ *
233+ * Returns 3 possible valid states: ISP_CSI2_POWER_OFF, ISP_CSI2_POWER_ON,
234+ * and ISP_CSI2_POWER_ULPW.
235+ **/
236+static enum isp_csi2_power_cmds isp_csi2_complexio_power_status(void)
237+{
238+ enum isp_csi2_power_cmds ret;
239+ u32 reg;
240+
241+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
242+ ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK;
243+ switch (reg) {
244+ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF:
245+ ret = ISP_CSI2_POWER_OFF;
246+ break;
247+ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON:
248+ ret = ISP_CSI2_POWER_ON;
249+ break;
250+ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW:
251+ ret = ISP_CSI2_POWER_ULPW;
252+ break;
253+ default:
254+ return -EINVAL;
255+ }
256+ return ret;
257+}
258+
259+/**
260+ * isp_csi2_complexio_power_autoswitch - Sets CSI2 ComplexIO power autoswitch.
261+ * @enable: Sets or clears the autoswitch function enable flag.
262+ *
263+ * Always returns 0.
264+ **/
265+int isp_csi2_complexio_power_autoswitch(bool enable)
266+{
267+ u32 reg;
268+
269+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
270+ reg &= ~ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK;
271+
272+ if (enable)
273+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE;
274+ else
275+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE;
276+
277+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
278+ return 0;
279+}
280+
281+/**
282+ * isp_csi2_complexio_power - Sets the desired power command for CSI2 ComplexIO.
283+ * @power_cmd: Power command to be set.
284+ *
285+ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
286+ **/
287+int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd)
288+{
289+ enum isp_csi2_power_cmds current_state;
290+ u32 reg;
291+ u8 retry_count;
292+
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;
298+ break;
299+ case ISP_CSI2_POWER_ON:
300+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON;
301+ break;
302+ case ISP_CSI2_POWER_ULPW:
303+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW;
304+ break;
305+ default:
306+ printk(KERN_ERR "CSI2: ERROR - Wrong Power command!\n");
307+ return -EINVAL;
308+ }
309+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
310+
311+ retry_count = 0;
312+ do {
313+ udelay(50);
314+ current_state = isp_csi2_complexio_power_status();
315+
316+ if (current_state != power_cmd) {
317+ printk(KERN_DEBUG "CSI2: Complex IO power command not"
318+ " yet taken.");
319+ if (++retry_count < 100) {
320+ printk(KERN_DEBUG " Retrying...\n");
321+ udelay(50);
322+ } else {
323+ printk(KERN_DEBUG " Retry count exceeded!\n");
324+ }
325+ }
326+ } while ((current_state != power_cmd) && (retry_count < 100));
327+
328+ if (retry_count == 100)
329+ return -EBUSY;
330+
331+ return 0;
332+}
333+
334+/**
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
338+ * contexts.
339+ *
340+ * Validates and saves to internal driver memory the passed configuration.
341+ * Always returns 0.
342+ **/
343+int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode)
344+{
345+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
346+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
347+ &current_csi2_cfg_update.ctrl;
348+
349+ if (currctrl->frame_mode != frame_mode) {
350+ currctrl->frame_mode = frame_mode;
351+ currctrl_u->frame_mode = true;
352+ update_ctrl = true;
353+ }
354+ return 0;
355+}
356+
357+/**
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.
360+ *
361+ * Validates and saves to internal driver memory the passed configuration.
362+ * Always returns 0.
363+ **/
364+int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable)
365+{
366+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
367+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
368+ &current_csi2_cfg_update.ctrl;
369+
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;
374+ }
375+ return 0;
376+}
377+
378+/**
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.
382+ *
383+ * Validates and saves to internal driver memory the passed configuration.
384+ * Always returns 0.
385+ **/
386+int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable)
387+{
388+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
389+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
390+ &current_csi2_cfg_update.ctrl;
391+
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;
396+ }
397+ return 0;
398+}
399+
400+/**
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.
404+ *
405+ * Validates and saves to internal driver memory the passed configuration.
406+ * Returns 0 if successful, or -EINVAL if wrong divider value is passed.
407+ **/
408+int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl)
409+{
410+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
411+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
412+ &current_csi2_cfg_update.ctrl;
413+
414+ if ((vp_out_ctrl == 0) || (vp_out_ctrl > 4)) {
415+ printk(KERN_ERR "CSI2: Wrong divisor value. Must be between"
416+ " 1 and 4");
417+ return -EINVAL;
418+ }
419+
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;
424+ }
425+ return 0;
426+}
427+
428+/**
429+ * isp_csi2_ctrl_config_debug_enable - Sets CSI2 debug
430+ * @debug_enable: Boolean for setting debug configuration on CSI2.
431+ *
432+ * Always returns 0.
433+ **/
434+int isp_csi2_ctrl_config_debug_enable(bool debug_enable)
435+{
436+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
437+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
438+ &current_csi2_cfg_update.ctrl;
439+
440+ if (currctrl->debug_enable != debug_enable) {
441+ currctrl->debug_enable = debug_enable;
442+ currctrl_u->debug_enable = true;
443+ update_ctrl = true;
444+ }
445+ return 0;
446+}
447+
448+/**
449+ * isp_csi2_ctrl_config_burst_size - Sets CSI2 burst size.
450+ * @burst_size: Burst size of the memory saving capability of receiver.
451+ *
452+ * Returns 0 if successful, or -EINVAL if burst size is wrong.
453+ **/
454+int isp_csi2_ctrl_config_burst_size(u8 burst_size)
455+{
456+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
457+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
458+ &current_csi2_cfg_update.ctrl;
459+ if (burst_size > 3) {
460+ printk(KERN_ERR "CSI2: Wrong burst size. Must be between"
461+ " 0 and 3");
462+ return -EINVAL;
463+ }
464+
465+ if (currctrl->burst_size != burst_size) {
466+ currctrl->burst_size = burst_size;
467+ currctrl_u->burst_size = true;
468+ update_ctrl = true;
469+ }
470+ return 0;
471+}
472+
473+/**
474+ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
475+ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
476+ *
477+ * Always returns 0.
478+ **/
479+int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable)
480+{
481+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
482+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
483+ &current_csi2_cfg_update.ctrl;
484+
485+ if (currctrl->ecc_enable != ecc_enable) {
486+ currctrl->ecc_enable = ecc_enable;
487+ currctrl_u->ecc_enable = true;
488+ update_ctrl = true;
489+ }
490+ return 0;
491+}
492+
493+/**
494+ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
495+ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
496+ *
497+ * Always returns 0.
498+ **/
499+int isp_csi2_ctrl_config_secure_mode(bool secure_mode)
500+{
501+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
502+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
503+ &current_csi2_cfg_update.ctrl;
504+
505+ if (currctrl->secure_mode != secure_mode) {
506+ currctrl->secure_mode = secure_mode;
507+ currctrl_u->secure_mode = true;
508+ update_ctrl = true;
509+ }
510+ return 0;
511+}
512+
513+/**
514+ * isp_csi2_ctrl_config_if_enable - Enables CSI2 Receiver interface.
515+ * @if_enable: Boolean to enable/disable the CSI2 receiver interface.
516+ *
517+ * Always returns 0.
518+ **/
519+int isp_csi2_ctrl_config_if_enable(bool if_enable)
520+{
521+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
522+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
523+ &current_csi2_cfg_update.ctrl;
524+
525+ if (currctrl->if_enable != if_enable) {
526+ currctrl->if_enable = if_enable;
527+ currctrl_u->if_enable = true;
528+ update_ctrl = true;
529+ }
530+ return 0;
531+}
532+
533+/**
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.
537+ *
538+ * It only saves settings when they were previously updated using the
539+ * isp_csi2_ctrl_config_*() functions, unless the force_update flag is
540+ * set to true.
541+ * Always returns 0.
542+ **/
543+int isp_csi2_ctrl_update(bool force_update)
544+{
545+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
546+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
547+ &current_csi2_cfg_update.ctrl;
548+ u32 reg;
549+
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;
556+ else
557+ reg |= ISPCSI2_CTRL_FRAME_DISABLE_IMM;
558+ currctrl_u->frame_mode = false;
559+ }
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;
564+ else
565+ reg |= ISPCSI2_CTRL_VP_CLK_EN_DISABLE;
566+ currctrl_u->vp_clk_enable = false;
567+ }
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;
573+ else
574+ reg |= ISPCSI2_CTRL_VP_ONLY_EN_DISABLE;
575+ currctrl_u->vp_only_enable = false;
576+ }
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;
582+ }
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;
587+ else
588+ reg |= ISPCSI2_CTRL_DBG_EN_DISABLE;
589+ currctrl_u->debug_enable = false;
590+ }
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;
596+ }
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;
601+ else
602+ reg |= ISPCSI2_CTRL_ECC_EN_DISABLE;
603+ currctrl_u->ecc_enable = false;
604+ }
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;
609+ else
610+ reg |= ISPCSI2_CTRL_SECURE_DISABLE;
611+ currctrl_u->secure_mode = false;
612+ }
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;
617+ else
618+ reg |= ISPCSI2_CTRL_IF_EN_DISABLE;
619+ currctrl_u->if_enable = false;
620+ }
621+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
622+ update_ctrl = false;
623+ }
624+ return 0;
625+}
626+
627+/**
628+ * isp_csi2_ctrl_get - Gets CSI2 control configuration
629+ *
630+ * Always returns 0.
631+ **/
632+int isp_csi2_ctrl_get(void)
633+{
634+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
635+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
636+ &current_csi2_cfg_update.ctrl;
637+ u32 reg;
638+
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;
643+
644+ if ((reg & ISPCSI2_CTRL_VP_CLK_EN_MASK) ==
645+ ISPCSI2_CTRL_VP_CLK_EN_ENABLE)
646+ currctrl->vp_clk_enable = true;
647+ else
648+ currctrl->vp_clk_enable = false;
649+ currctrl_u->vp_clk_enable = false;
650+
651+ if ((reg & ISPCSI2_CTRL_VP_ONLY_EN_MASK) ==
652+ ISPCSI2_CTRL_VP_ONLY_EN_ENABLE)
653+ currctrl->vp_only_enable = true;
654+ else
655+ currctrl->vp_only_enable = false;
656+ uses_videoport = currctrl->vp_only_enable;
657+ currctrl_u->vp_only_enable = false;
658+
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;
662+
663+ if ((reg & ISPCSI2_CTRL_DBG_EN_MASK) == ISPCSI2_CTRL_DBG_EN_ENABLE)
664+ currctrl->debug_enable = true;
665+ else
666+ currctrl->debug_enable = false;
667+ currctrl_u->debug_enable = false;
668+
669+ currctrl->burst_size = (reg & ISPCSI2_CTRL_BURST_SIZE_MASK) >>
670+ ISPCSI2_CTRL_BURST_SIZE_SHIFT;
671+ currctrl_u->burst_size = false;
672+
673+ if ((reg & ISPCSI2_CTRL_ECC_EN_MASK) == ISPCSI2_CTRL_ECC_EN_ENABLE)
674+ currctrl->ecc_enable = true;
675+ else
676+ currctrl->ecc_enable = false;
677+ currctrl_u->ecc_enable = false;
678+
679+ if ((reg & ISPCSI2_CTRL_SECURE_MASK) == ISPCSI2_CTRL_SECURE_ENABLE)
680+ currctrl->secure_mode = true;
681+ else
682+ currctrl->secure_mode = false;
683+ currctrl_u->secure_mode = false;
684+
685+ if ((reg & ISPCSI2_CTRL_IF_EN_MASK) == ISPCSI2_CTRL_IF_EN_ENABLE)
686+ currctrl->if_enable = true;
687+ else
688+ currctrl->if_enable = false;
689+ currctrl_u->if_enable = false;
690+
691+ update_ctrl = false;
692+ return 0;
693+}
694+
695+/**
696+ * isp_csi2_ctx_validate - Validates the context number value
697+ * @ctxnum: Pointer to variable containing context number.
698+ *
699+ * If the value is not in range (3 bits), it is being ANDed with 0x7 to force
700+ * it to be on range.
701+ **/
702+static void isp_csi2_ctx_validate(u8 *ctxnum)
703+{
704+ if (*ctxnum > 7) {
705+ printk(KERN_ERR "Invalid context number. Forcing valid"
706+ " value...\n");
707+ *ctxnum &= ~(0x7);
708+ }
709+}
710+
711+/**
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.
715+ *
716+ * Returns 0 if successful, or -EINVAL if Virtual ID is not in range (0-3).
717+ **/
718+int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id)
719+{
720+ struct isp_csi2_ctx_cfg *selected_ctx;
721+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
722+
723+ isp_csi2_ctx_validate(&ctxnum);
724+
725+ if (virtual_id > 3) {
726+ printk(KERN_ERR "Wrong requested virtual_id\n");
727+ return -EINVAL;
728+ }
729+
730+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
731+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
732+
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;
737+ }
738+
739+ return 0;
740+}
741+
742+/**
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.
746+ *
747+ * Always returns 0.
748+ **/
749+int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count)
750+{
751+ struct isp_csi2_ctx_cfg *selected_ctx;
752+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
753+
754+ isp_csi2_ctx_validate(&ctxnum);
755+
756+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
757+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
758+
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;
763+ }
764+
765+ return 0;
766+}
767+
768+/**
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.
772+ *
773+ * Returns 0 if successful, or -EINVAL if the format is not supported by the
774+ * receiver.
775+ **/
776+int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat)
777+{
778+ struct isp_csi2_ctx_cfg *selected_ctx;
779+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
780+ struct v4l2_pix_format pix;
781+
782+ isp_csi2_ctx_validate(&ctxnum);
783+
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:
793+ break;
794+ default:
795+ printk(KERN_ERR "Context config pixel format unsupported\n");
796+ return -EINVAL;
797+ }
798+
799+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
800+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
801+
802+ selected_ctx->format = pix;
803+ selected_ctx_u->format = true;
804+ update_ctx_ctrl2[ctxnum] = true;
805+
806+ return 0;
807+}
808+
809+/**
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.
813+ *
814+ * Returns 0 if successful, or -EINVAL if the alpha value is bigger than 16383.
815+ **/
816+int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha)
817+{
818+ struct isp_csi2_ctx_cfg *selected_ctx;
819+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
820+
821+ isp_csi2_ctx_validate(&ctxnum);
822+
823+ if (alpha > 0x3FFF) {
824+ printk(KERN_ERR "Wrong alpha value\n");
825+ return -EINVAL;
826+ }
827+
828+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
829+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
830+
831+ if (selected_ctx->alpha != alpha) {
832+ selected_ctx->alpha = alpha;
833+ selected_ctx_u->alpha = true;
834+ update_ctx_ctrl3[ctxnum] = true;
835+ }
836+ return 0;
837+}
838+
839+/**
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.
843+ *
844+ * Returns 0 if successful, or -EINVAL if the line offset is bigger than 1023.
845+ **/
846+int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset)
847+{
848+ struct isp_csi2_ctx_cfg *selected_ctx;
849+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
850+
851+ isp_csi2_ctx_validate(&ctxnum);
852+
853+ if (data_offset > 0x3FF) {
854+ printk(KERN_ERR "Wrong line offset\n");
855+ return -EINVAL;
856+ }
857+
858+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
859+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
860+
861+ if (selected_ctx->data_offset != data_offset) {
862+ selected_ctx->data_offset = data_offset;
863+ selected_ctx_u->data_offset = true;
864+ }
865+ return 0;
866+}
867+
868+/**
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.
872+ *
873+ * Always returns 0.
874+ **/
875+int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr)
876+{
877+ struct isp_csi2_ctx_cfg *selected_ctx;
878+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
879+
880+ isp_csi2_ctx_validate(&ctxnum);
881+
882+ ping_addr &= ~(0x1F);
883+
884+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
885+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
886+
887+ if (selected_ctx->ping_addr != ping_addr) {
888+ selected_ctx->ping_addr = ping_addr;
889+ selected_ctx_u->ping_addr = true;
890+ }
891+ return 0;
892+}
893+
894+/**
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.
898+ *
899+ * Always returns 0.
900+ **/
901+int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr)
902+{
903+ struct isp_csi2_ctx_cfg *selected_ctx;
904+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
905+
906+ isp_csi2_ctx_validate(&ctxnum);
907+
908+ pong_addr &= ~(0x1F);
909+
910+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
911+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
912+
913+ if (selected_ctx->pong_addr != pong_addr) {
914+ selected_ctx->pong_addr = pong_addr;
915+ selected_ctx_u->pong_addr = true;
916+ }
917+ return 0;
918+}
919+
920+/**
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
924+ * packets.
925+ *
926+ * Always returns 0.
927+ **/
928+int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled)
929+{
930+ struct isp_csi2_ctx_cfg *selected_ctx;
931+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
932+
933+ isp_csi2_ctx_validate(&ctxnum);
934+
935+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
936+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
937+
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;
942+ }
943+ return 0;
944+}
945+
946+/**
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
950+ * packets.
951+ *
952+ * Always returns 0.
953+ **/
954+int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled)
955+{
956+ struct isp_csi2_ctx_cfg *selected_ctx;
957+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
958+
959+ isp_csi2_ctx_validate(&ctxnum);
960+
961+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
962+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
963+
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;
968+ }
969+ return 0;
970+}
971+
972+/**
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
976+ * packets
977+ *
978+ * Always returns 0.
979+ **/
980+int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled)
981+{
982+ struct isp_csi2_ctx_cfg *selected_ctx;
983+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
984+
985+ isp_csi2_ctx_validate(&ctxnum);
986+
987+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
988+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
989+
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;
994+ }
995+ return 0;
996+}
997+
998+/**
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.
1002+ *
1003+ * Always returns 0.
1004+ **/
1005+int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled)
1006+{
1007+ struct isp_csi2_ctx_cfg *selected_ctx;
1008+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1009+
1010+ isp_csi2_ctx_validate(&ctxnum);
1011+
1012+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
1013+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
1014+
1015+ if (selected_ctx->enabled != enabled) {
1016+ selected_ctx->enabled = enabled;
1017+ selected_ctx_u->enabled = true;
1018+ update_ctx_ctrl1[ctxnum] = true;
1019+ }
1020+ return 0;
1021+}
1022+
1023+/**
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.
1028+ *
1029+ * It only saves settings when they were previously updated using the
1030+ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
1031+ * set to true.
1032+ * Always returns 0.
1033+ **/
1034+int isp_csi2_ctx_update(u8 ctxnum, bool force_update)
1035+{
1036+ struct isp_csi2_ctx_cfg *selected_ctx;
1037+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1038+ u32 reg;
1039+
1040+ isp_csi2_ctx_validate(&ctxnum);
1041+
1042+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
1043+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
1044+
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;
1053+ }
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;
1058+ else
1059+ reg |= ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE;
1060+ selected_ctx_u->eof_enabled = false;
1061+ }
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;
1066+ else
1067+ reg |= ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE;
1068+ selected_ctx_u->eol_enabled = false;
1069+ }
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;
1074+ else
1075+ reg |= ISPCSI2_CTX_CTRL1_CS_EN_DISABLE;
1076+ selected_ctx_u->checksum_enabled = false;
1077+ }
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;
1082+ else
1083+ reg |= ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE;
1084+ selected_ctx_u->enabled = false;
1085+ }
1086+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1087+ ISPCSI2_CTX_CTRL1(ctxnum));
1088+ update_ctx_ctrl1[ctxnum] = false;
1089+ }
1090+
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;
1099+ }
1100+
1101+ if (selected_ctx_u->format || force_update) {
1102+ struct v4l2_pix_format *pix;
1103+ u16 new_format = 0;
1104+
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;
1111+ break;
1112+ case V4L2_PIX_FMT_YUYV:
1113+ case V4L2_PIX_FMT_UYVY:
1114+ if (uses_videoport)
1115+ new_format = 0x9E;
1116+ else
1117+ new_format = 0x1E;
1118+ break;
1119+ case V4L2_PIX_FMT_RGB555:
1120+ case V4L2_PIX_FMT_RGB555X:
1121+ new_format = 0xA1;
1122+ break;
1123+ case V4L2_PIX_FMT_SGRBG10:
1124+ if (uses_videoport)
1125+ new_format = 0x12F;
1126+ else
1127+ new_format = 0xAB;
1128+ break;
1129+ }
1130+ reg |= (new_format << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT);
1131+ selected_ctx_u->format = false;
1132+ }
1133+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1134+ ISPCSI2_CTX_CTRL2(ctxnum));
1135+ update_ctx_ctrl2[ctxnum] = false;
1136+ }
1137+
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;
1146+ }
1147+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1148+ ISPCSI2_CTX_CTRL3(ctxnum));
1149+ update_ctx_ctrl3[ctxnum] = false;
1150+ }
1151+
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;
1161+ }
1162+
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;
1168+ }
1169+
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;
1175+ }
1176+ return 0;
1177+}
1178+
1179+/**
1180+ * isp_csi2_ctx_get - Gets specific CSI2 Context configuration
1181+ * @ctxnum: Context number, valid between 0 and 7 values.
1182+ *
1183+ * Always returns 0.
1184+ **/
1185+int isp_csi2_ctx_get(u8 ctxnum)
1186+{
1187+ struct isp_csi2_ctx_cfg *selected_ctx;
1188+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1189+ u32 reg;
1190+
1191+ isp_csi2_ctx_validate(&ctxnum);
1192+
1193+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
1194+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
1195+
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;
1200+
1201+ if ((reg & ISPCSI2_CTX_CTRL1_EOF_EN_MASK) ==
1202+ ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE)
1203+ selected_ctx->eof_enabled = true;
1204+ else
1205+ selected_ctx->eof_enabled = false;
1206+ selected_ctx_u->eof_enabled = false;
1207+
1208+ if ((reg & ISPCSI2_CTX_CTRL1_EOL_EN_MASK) ==
1209+ ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE)
1210+ selected_ctx->eol_enabled = true;
1211+ else
1212+ selected_ctx->eol_enabled = false;
1213+ selected_ctx_u->eol_enabled = false;
1214+
1215+ if ((reg & ISPCSI2_CTX_CTRL1_CS_EN_MASK) ==
1216+ ISPCSI2_CTX_CTRL1_CS_EN_ENABLE)
1217+ selected_ctx->checksum_enabled = true;
1218+ else
1219+ selected_ctx->checksum_enabled = false;
1220+ selected_ctx_u->checksum_enabled = false;
1221+
1222+ if ((reg & ISPCSI2_CTX_CTRL1_CTX_EN_MASK) ==
1223+ ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE)
1224+ selected_ctx->enabled = true;
1225+ else
1226+ selected_ctx->enabled = false;
1227+ selected_ctx_u->enabled = false;
1228+ update_ctx_ctrl1[ctxnum] = false;
1229+
1230+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL2(ctxnum));
1231+
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;
1235+
1236+ switch ((reg & ISPCSI2_CTX_CTRL2_FORMAT_MASK) >>
1237+ ISPCSI2_CTX_CTRL2_FORMAT_SHIFT) {
1238+ case 0x22:
1239+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB565;
1240+ break;
1241+ case 0x9E:
1242+ case 0x1E:
1243+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_YUYV;
1244+ break;
1245+ case 0xA1:
1246+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB555;
1247+ break;
1248+ case 0xAB:
1249+ case 0x12F:
1250+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_SGRBG10;
1251+ break;
1252+ }
1253+ selected_ctx_u->format = false;
1254+ update_ctx_ctrl2[ctxnum] = false;
1255+
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;
1262+
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;
1268+
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;
1272+
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;
1276+ return 0;
1277+}
1278+
1279+/**
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.
1283+ *
1284+ * It only saves settings when they were previously updated using the
1285+ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
1286+ * set to true.
1287+ * Always returns 0.
1288+ **/
1289+int isp_csi2_ctx_update_all(bool force_update)
1290+{
1291+ u8 ctxnum;
1292+
1293+ for (ctxnum = 0; ctxnum < 8; ctxnum++)
1294+ isp_csi2_ctx_update(ctxnum, force_update);
1295+
1296+ return 0;
1297+}
1298+
1299+/**
1300+ * isp_csi2_ctx_get_all - Gets all CSI2 Context configurations
1301+ *
1302+ * Always returns 0.
1303+ **/
1304+int isp_csi2_ctx_get_all(void)
1305+{
1306+ u8 ctxnum;
1307+
1308+ for (ctxnum = 0; ctxnum < 8; ctxnum++)
1309+ isp_csi2_ctx_get(ctxnum);
1310+
1311+ return 0;
1312+}
1313+
1314+int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig)
1315+{
1316+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1317+ struct isp_csi2_phy_cfg_update *currphy_u =
1318+ &current_csi2_cfg_update.phy;
1319+
1320+ if ((desiredphyconfig->tclk_term > 0x7f) ||
1321+ (desiredphyconfig->tclk_miss > 0x3)) {
1322+ printk(KERN_ERR "Invalid PHY configuration sent by the"
1323+ " driver\n");
1324+ return -EINVAL;
1325+ }
1326+
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;
1331+ }
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;
1336+ }
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;
1341+ }
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;
1346+ }
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;
1351+ }
1352+ return 0;
1353+}
1354+
1355+/**
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.
1360+ *
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
1364+ * sensor:
1365+ * THS_SETTLE = (Upper bound + Lower bound) / 2
1366+ *
1367+ * Always returns 0.
1368+ */
1369+int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
1370+ u32 ubound_hs_settle)
1371+{
1372+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1373+ struct isp_csi2_phy_cfg_update *currphy_u =
1374+ &current_csi2_cfg_update.phy;
1375+ u32 tmp, ddrclk = mipiclk >> 1;
1376+
1377+ /* Calculate THS_TERM */
1378+ tmp = ddrclk / 80000000;
1379+ if ((ddrclk % 80000000) > 0)
1380+ tmp++;
1381+ currphy->ths_term = tmp - 1;
1382+ currphy_u->ths_term = true;
1383+
1384+ /* Calculate THS_SETTLE */
1385+ currphy->ths_settle = (ubound_hs_settle + lbound_hs_settle) / 2;
1386+
1387+ currphy_u->ths_settle = true;
1388+ isp_csi2_phy_update(true);
1389+ return 0;
1390+}
1391+EXPORT_SYMBOL(isp_csi2_calc_phy_cfg0);
1392+
1393+/**
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.
1397+ *
1398+ * It only saves settings when they were previously updated using the
1399+ * isp_csi2_phy_config_*() functions, unless the force_update flag is
1400+ * set to true.
1401+ * Always returns 0.
1402+ **/
1403+int isp_csi2_phy_update(bool force_update)
1404+{
1405+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1406+ struct isp_csi2_phy_cfg_update *currphy_u =
1407+ &current_csi2_cfg_update.phy;
1408+ u32 reg;
1409+
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;
1417+ }
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;
1423+ }
1424+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1425+ update_phy_cfg0 = false;
1426+ }
1427+
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;
1435+ }
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;
1441+ }
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;
1447+ }
1448+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1449+ update_phy_cfg1 = false;
1450+ }
1451+ return 0;
1452+}
1453+
1454+/**
1455+ * isp_csi2_phy_get - Gets CSI2 D-PHY configuration
1456+ *
1457+ * Gets settings from HW registers and fills in the internal driver memory
1458+ * Always returns 0.
1459+ **/
1460+int isp_csi2_phy_get(void)
1461+{
1462+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1463+ struct isp_csi2_phy_cfg_update *currphy_u =
1464+ &current_csi2_cfg_update.phy;
1465+ u32 reg;
1466+
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;
1471+
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;
1476+
1477+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1478+
1479+ currphy->tclk_term = (reg & ISPCSI2PHY_CFG1_TCLK_TERM_MASK) >>
1480+ ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT;
1481+ currphy_u->tclk_term = false;
1482+
1483+ currphy->tclk_miss = (reg & ISPCSI2PHY_CFG1_TCLK_MISS_MASK) >>
1484+ ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT;
1485+ currphy_u->tclk_miss = false;
1486+
1487+ currphy->tclk_settle = (reg & ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK) >>
1488+ ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT;
1489+ currphy_u->tclk_settle = false;
1490+
1491+ update_phy_cfg1 = false;
1492+ return 0;
1493+}
1494+
1495+/**
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
1498+ *
1499+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1500+ **/
1501+int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode)
1502+{
1503+ struct isp_csi2_timings_cfg *currtimings;
1504+ struct isp_csi2_timings_cfg_update *currtimings_u;
1505+
1506+ if (io < 1 || io > 2) {
1507+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1508+ return -EINVAL;
1509+ }
1510+
1511+ currtimings = &current_csi2_cfg.timings[io - 1];
1512+ currtimings_u = &current_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;
1517+ }
1518+ return 0;
1519+}
1520+
1521+/**
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
1524+ *
1525+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1526+ **/
1527+int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x)
1528+{
1529+ struct isp_csi2_timings_cfg *currtimings;
1530+ struct isp_csi2_timings_cfg_update *currtimings_u;
1531+
1532+ if (io < 1 || io > 2) {
1533+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1534+ return -EINVAL;
1535+ }
1536+
1537+ currtimings = &current_csi2_cfg.timings[io - 1];
1538+ currtimings_u = &current_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;
1543+ }
1544+ return 0;
1545+}
1546+
1547+/**
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
1550+ *
1551+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1552+ **/
1553+int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x)
1554+{
1555+ struct isp_csi2_timings_cfg *currtimings;
1556+ struct isp_csi2_timings_cfg_update *currtimings_u;
1557+
1558+ if (io < 1 || io > 2) {
1559+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1560+ return -EINVAL;
1561+ }
1562+
1563+ currtimings = &current_csi2_cfg.timings[io - 1];
1564+ currtimings_u = &current_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;
1569+ }
1570+ return 0;
1571+}
1572+
1573+/**
1574+ * isp_csi2_timings_config_stopstate_cnt - Sets L3 cycles
1575+ * @stop_state_counter: Stop state counter value for L3 cycles
1576+ *
1577+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1578+ **/
1579+int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter)
1580+{
1581+ struct isp_csi2_timings_cfg *currtimings;
1582+ struct isp_csi2_timings_cfg_update *currtimings_u;
1583+
1584+ if (io < 1 || io > 2) {
1585+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1586+ return -EINVAL;
1587+ }
1588+
1589+ currtimings = &current_csi2_cfg.timings[io - 1];
1590+ currtimings_u = &current_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;
1595+ }
1596+ return 0;
1597+}
1598+
1599+/**
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.
1604+ *
1605+ * It only saves settings when they were previously updated using the
1606+ * isp_csi2_timings_config_*() functions, unless the force_update flag is
1607+ * set to true.
1608+ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
1609+ **/
1610+int isp_csi2_timings_update(u8 io, bool force_update)
1611+{
1612+ struct isp_csi2_timings_cfg *currtimings;
1613+ struct isp_csi2_timings_cfg_update *currtimings_u;
1614+ u32 reg;
1615+
1616+ if (io < 1 || io > 2) {
1617+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1618+ return -EINVAL;
1619+ }
1620+
1621+ currtimings = &current_csi2_cfg.timings[io - 1];
1622+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1623+
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
1630+ (io);
1631+ else
1632+ reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE
1633+ (io);
1634+ currtimings_u->force_rx_mode = false;
1635+ }
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
1640+ (io);
1641+ else
1642+ reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE
1643+ (io);
1644+ currtimings_u->stop_state_16x = false;
1645+ }
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
1650+ (io);
1651+ } else {
1652+ reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE
1653+ (io);
1654+ }
1655+ currtimings_u->stop_state_4x = false;
1656+ }
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;
1662+ }
1663+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1664+ update_timing = false;
1665+ }
1666+ return 0;
1667+}
1668+
1669+/**
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
1672+ *
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.
1675+ **/
1676+int isp_csi2_timings_get(u8 io)
1677+{
1678+ struct isp_csi2_timings_cfg *currtimings;
1679+ struct isp_csi2_timings_cfg_update *currtimings_u;
1680+ u32 reg;
1681+
1682+ if (io < 1 || io > 2) {
1683+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1684+ return -EINVAL;
1685+ }
1686+
1687+ currtimings = &current_csi2_cfg.timings[io - 1];
1688+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1689+
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;
1694+ else
1695+ currtimings->force_rx_mode = false;
1696+ currtimings_u->force_rx_mode = false;
1697+
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;
1701+ else
1702+ currtimings->stop_state_16x = false;
1703+ currtimings_u->stop_state_16x = false;
1704+
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;
1708+ else
1709+ currtimings->stop_state_4x = false;
1710+ currtimings_u->stop_state_4x = false;
1711+
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;
1717+ return 0;
1718+}
1719+
1720+/**
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.
1724+ *
1725+ * It only saves settings when they were previously updated using the
1726+ * isp_csi2_timings_config_*() functions, unless the force_update flag is
1727+ * set to true.
1728+ * Always returns 0.
1729+ **/
1730+int isp_csi2_timings_update_all(bool force_update)
1731+{
1732+ int i;
1733+
1734+ for (i = 1; i < 3; i++)
1735+ isp_csi2_timings_update(i, force_update);
1736+ return 0;
1737+}
1738+
1739+/**
1740+ * isp_csi2_timings_get_all - Gets all CSI2 ComplexIO timing configurations
1741+ *
1742+ * Always returns 0.
1743+ **/
1744+int isp_csi2_timings_get_all(void)
1745+{
1746+ int i;
1747+
1748+ for (i = 1; i < 3; i++)
1749+ isp_csi2_timings_get(i);
1750+ return 0;
1751+}
1752+
1753+/**
1754+ * isp_csi2_isr - CSI2 interrupt handling.
1755+ **/
1756+void isp_csi2_isr(void)
1757+{
1758+ u32 csi2_irqstatus, cpxio1_irqstatus, ctxirqstatus;
1759+
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);
1764+
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);
1772+ }
1773+
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));
1779+ }
1780+
1781+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_OCP_ERR_IRQ)
1782+ printk(KERN_ERR "CSI2: OCP Transmission Error\n");
1783+
1784+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ)
1785+ printk(KERN_ERR "CSI2: Short packet receive error\n");
1786+
1787+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
1788+ printk(KERN_DEBUG "CSI2: ECC correction done\n");
1789+
1790+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ)
1791+ printk(KERN_ERR "CSI2: ECC correction failed\n");
1792+
1793+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ)
1794+ printk(KERN_ERR "CSI2: ComplexIO #2 failed\n");
1795+
1796+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)
1797+ printk(KERN_ERR "CSI2: FIFO overflow error\n");
1798+
1799+ return;
1800+}
1801+EXPORT_SYMBOL(isp_csi2_isr);
1802+
1803+/**
1804+ * isp_csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
1805+ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
1806+ **/
1807+void isp_csi2_irq_complexio1_set(int enable)
1808+{
1809+ u32 reg;
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);
1839+ if (enable) {
1840+ reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1841+ ISPCSI2_COMPLEXIO1_IRQENABLE);
1842+ } else
1843+ reg = 0;
1844+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1845+ ISPCSI2_COMPLEXIO1_IRQENABLE);
1846+}
1847+EXPORT_SYMBOL(isp_csi2_irq_complexio1_set);
1848+
1849+/**
1850+ * isp_csi2_irq_ctx_set - Enables CSI2 Context IRQs.
1851+ * @enable: Enable/disable CSI2 Context interrupts
1852+ **/
1853+void isp_csi2_irq_ctx_set(int enable)
1854+{
1855+ u32 reg;
1856+ int i;
1857+
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));
1862+ if (enable) {
1863+ isp_reg_or(OMAP3_ISP_IOMEM_CSI2A,
1864+ ISPCSI2_CTX_IRQENABLE(i), reg);
1865+ } else {
1866+ isp_reg_writel(0, OMAP3_ISP_IOMEM_CSI2A,
1867+ ISPCSI2_CTX_IRQENABLE(i));
1868+ }
1869+ }
1870+
1871+}
1872+EXPORT_SYMBOL(isp_csi2_irq_ctx_set);
1873+
1874+/**
1875+ * isp_csi2_irq_status_set - Enables CSI2 Status IRQs.
1876+ * @enable: Enable/disable CSI2 Status interrupts
1877+ **/
1878+void isp_csi2_irq_status_set(int enable)
1879+{
1880+ u32 reg;
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);
1890+ if (enable)
1891+ reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
1892+ else
1893+ reg = 0;
1894+
1895+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
1896+}
1897+EXPORT_SYMBOL(isp_csi2_irq_status_set);
1898+
1899+/**
1900+ * isp_csi2_irq_status_set - Enables main CSI2 IRQ.
1901+ * @enable: Enable/disable main CSI2 interrupt
1902+ **/
1903+void isp_csi2_irq_set(int enable)
1904+{
1905+ isp_reg_writel(IRQ0STATUS_CSIA_IRQ, OMAP3_ISP_IOMEM_MAIN,
1906+ ISP_IRQ0STATUS);
1907+ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
1908+ ~IRQ0ENABLE_CSIA_IRQ,
1909+ (enable ? IRQ0ENABLE_CSIA_IRQ : 0));
1910+}
1911+EXPORT_SYMBOL(isp_csi2_irq_set);
1912+
1913+/**
1914+ * isp_csi2_irq_all_set - Enable/disable CSI2 interrupts.
1915+ * @enable: 0-Disable, 1-Enable.
1916+ **/
1917+void isp_csi2_irq_all_set(int enable)
1918+{
1919+ if (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);
1924+ } else {
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);
1929+ }
1930+ return;
1931+}
1932+EXPORT_SYMBOL(isp_csi2_irq_all_set);
1933+
1934+/**
1935+ * isp_csi2_reset - Resets the CSI2 module.
1936+ *
1937+ * Returns 0 if successful, or -EBUSY if power command didn't respond.
1938+ **/
1939+int isp_csi2_reset(void)
1940+{
1941+ u32 reg;
1942+ u8 soft_reset_retries = 0;
1943+ int i;
1944+
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);
1948+
1949+ do {
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)
1953+ break;
1954+ soft_reset_retries++;
1955+ if (soft_reset_retries < 5)
1956+ udelay(100);
1957+ } while (soft_reset_retries < 5);
1958+
1959+ if (soft_reset_retries == 5) {
1960+ printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
1961+ return -EBUSY;
1962+ }
1963+
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);
1969+
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;
1978+ }
1979+ update_timing = false;
1980+ update_ctrl = false;
1981+
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();
1987+
1988+ isp_csi2_complexio_power_autoswitch(true);
1989+ isp_csi2_complexio_power(ISP_CSI2_POWER_ON);
1990+
1991+ isp_csi2_timings_config_forcerxmode(1, true);
1992+ isp_csi2_timings_config_stopstate_cnt(1, 0x1FF);
1993+ isp_csi2_timings_update_all(true);
1994+
1995+ return 0;
1996+}
1997+
1998+/**
1999+ * isp_csi2_enable - Enables the CSI2 module.
2000+ * @enable: Enables/disables the CSI2 module.
2001+ **/
2002+void isp_csi2_enable(int enable)
2003+{
2004+ if (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);
2009+
2010+ isp_csi2_ctrl_config_ecc_enable(true);
2011+ isp_csi2_ctrl_config_if_enable(true);
2012+ isp_csi2_ctrl_update(false);
2013+ } else {
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);
2018+
2019+ isp_csi2_ctrl_config_ecc_enable(false);
2020+ isp_csi2_ctrl_config_if_enable(false);
2021+ isp_csi2_ctrl_update(false);
2022+ }
2023+}
2024+EXPORT_SYMBOL(isp_csi2_enable);
2025+
2026+/**
2027+ * isp_csi2_regdump - Prints CSI2 debug information.
2028+ **/
2029+void isp_csi2_regdump(void)
2030+{
2031+ printk(KERN_DEBUG "-------------Register dump-------------\n");
2032+
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));
2037+
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));
2056+
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));
2072+
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");
2108+}
2109+
2110+/**
2111+ * isp_csi2_cleanup - Routine for module driver cleanup
2112+ **/
2113+void isp_csi2_cleanup(void)
2114+{
2115+ return;
2116+}
2117+
2118+/**
2119+ * isp_csi2_init - Routine for module driver init
2120+ **/
2121+int __init isp_csi2_init(void)
2122+{
2123+ int i;
2124+
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;
2132+ }
2133+ update_timing = false;
2134+ update_ctrl = false;
2135+
2136+ memset(&current_csi2_cfg, 0, sizeof(current_csi2_cfg));
2137+ memset(&current_csi2_cfg_update, 0, sizeof(current_csi2_cfg_update));
2138+ return 0;
2139+}
2140+
2141+MODULE_AUTHOR("Texas Instruments");
2142+MODULE_DESCRIPTION("ISP CSI2 Receiver Module");
2143+MODULE_LICENSE("GPL");
2144diff --git a/drivers/media/video/isp/ispcsi2.h b/drivers/media/video/isp/ispcsi2.h
2145new file mode 100644
2146index 0000000..4582c96
2147--- /dev/null
2148+++ b/drivers/media/video/isp/ispcsi2.h
2149@@ -0,0 +1,232 @@
2150+/*
2151+ * ispcsi2.h
2152+ *
2153+ * Copyright (C) 2009 Texas Instruments.
2154+ *
2155+ * Contributors:
2156+ * Sergio Aguirre <saaguirre@ti.com>
2157+ * Dominic Curran <dcurran@ti.com>
2158+ *
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.
2162+ *
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.
2166+ */
2167+
2168+#ifndef OMAP_ISP_CSI2_API_H
2169+#define OMAP_ISP_CSI2_API_H
2170+#include <linux/videodev2.h>
2171+
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,
2180+ CONTEXT7 = 0x80,
2181+ CONTEXT6 = 0x40,
2182+ CONTEXT5 = 0x20,
2183+ CONTEXT4 = 0x10,
2184+ CONTEXT3 = 0x8,
2185+ CONTEXT2 = 0x4,
2186+ CONTEXT1 = 0x2,
2187+ CONTEXT0 = 0x1,
2188+};
2189+
2190+enum isp_csi2_ctx_irqevents {
2191+ CTX_ECC_CORRECTION = 0x100,
2192+ CTX_LINE_NUMBER = 0x80,
2193+ CTX_FRAME_NUMBER = 0x40,
2194+ CTX_CS = 0x20,
2195+ CTX_LE = 0x8,
2196+ CTX_LS = 0x4,
2197+ CTX_FE = 0x2,
2198+ CTX_FS = 0x1,
2199+};
2200+
2201+enum isp_csi2_power_cmds {
2202+ ISP_CSI2_POWER_OFF,
2203+ ISP_CSI2_POWER_ON,
2204+ ISP_CSI2_POWER_ULPW,
2205+};
2206+
2207+enum isp_csi2_frame_mode {
2208+ ISP_CSI2_FRAME_IMMEDIATE,
2209+ ISP_CSI2_FRAME_AFTERFEC,
2210+};
2211+
2212+struct csi2_lanecfg {
2213+ u8 pos;
2214+ u8 pol;
2215+};
2216+
2217+struct isp_csi2_lanes_cfg {
2218+ struct csi2_lanecfg data[4];
2219+ struct csi2_lanecfg clk;
2220+};
2221+
2222+struct isp_csi2_lanes_cfg_update {
2223+ bool data[4];
2224+ bool clk;
2225+};
2226+
2227+struct isp_csi2_phy_cfg {
2228+ u8 ths_term;
2229+ u8 ths_settle;
2230+ u8 tclk_term;
2231+ unsigned tclk_miss:1;
2232+ u8 tclk_settle;
2233+};
2234+
2235+struct isp_csi2_phy_cfg_update {
2236+ bool ths_term;
2237+ bool ths_settle;
2238+ bool tclk_term;
2239+ bool tclk_miss;
2240+ bool tclk_settle;
2241+};
2242+
2243+struct isp_csi2_ctx_cfg {
2244+ u8 virtual_id;
2245+ u8 frame_count;
2246+ struct v4l2_pix_format format;
2247+ u16 alpha;
2248+ u16 data_offset;
2249+ u32 ping_addr;
2250+ u32 pong_addr;
2251+ bool eof_enabled;
2252+ bool eol_enabled;
2253+ bool checksum_enabled;
2254+ bool enabled;
2255+};
2256+
2257+struct isp_csi2_ctx_cfg_update {
2258+ bool virtual_id;
2259+ bool frame_count;
2260+ bool format;
2261+ bool alpha;
2262+ bool data_offset;
2263+ bool ping_addr;
2264+ bool pong_addr;
2265+ bool eof_enabled;
2266+ bool eol_enabled;
2267+ bool checksum_enabled;
2268+ bool enabled;
2269+};
2270+
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;
2276+};
2277+
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;
2283+};
2284+
2285+struct isp_csi2_ctrl_cfg {
2286+ bool vp_clk_enable;
2287+ bool vp_only_enable;
2288+ u8 vp_out_ctrl;
2289+ bool debug_enable;
2290+ u8 burst_size;
2291+ enum isp_csi2_frame_mode frame_mode;
2292+ bool ecc_enable;
2293+ bool secure_mode;
2294+ bool if_enable;
2295+};
2296+
2297+struct isp_csi2_ctrl_cfg_update {
2298+ bool vp_clk_enable;
2299+ bool vp_only_enable;
2300+ bool vp_out_ctrl;
2301+ bool debug_enable;
2302+ bool burst_size;
2303+ bool frame_mode;
2304+ bool ecc_enable;
2305+ bool secure_mode;
2306+ bool if_enable;
2307+};
2308+
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;
2315+};
2316+
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;
2323+};
2324+
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);
2374+
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);
2379+
2380+#endif /* OMAP_ISP_CSI2_H */
2381+
2382--
23831.5.6.5
2384