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:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
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