aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/adp1653.c4
-rw-r--r--drivers/media/i2c/adv7183.c13
-rw-r--r--drivers/media/i2c/adv7604.c16
-rw-r--r--drivers/media/i2c/cx25840/cx25840-core.c2
-rw-r--r--drivers/media/i2c/ir-kbd-i2c.c14
-rw-r--r--drivers/media/i2c/s5k4ecgx.c2
-rw-r--r--drivers/media/i2c/smiapp-pll.c219
-rw-r--r--drivers/media/i2c/smiapp-pll.h61
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c74
-rw-r--r--drivers/media/i2c/smiapp/smiapp-limits.c2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-limits.h2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-quirk.c2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-quirk.h2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-reg-defs.h2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-reg.h2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-regs.c2
-rw-r--r--drivers/media/i2c/smiapp/smiapp-regs.h2
-rw-r--r--drivers/media/i2c/smiapp/smiapp.h2
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c88
-rw-r--r--drivers/media/i2c/soc_camera/ov2640.c55
-rw-r--r--drivers/media/i2c/vs6624.c13
21 files changed, 349 insertions, 230 deletions
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index 18a38b38fcb8..df163800c8e1 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -3,10 +3,10 @@
3 * 3 *
4 * Copyright (C) 2008--2011 Nokia Corporation 4 * Copyright (C) 2008--2011 Nokia Corporation
5 * 5 *
6 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 6 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
7 * 7 *
8 * Contributors: 8 * Contributors:
9 * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 9 * Sakari Ailus <sakari.ailus@iki.fi>
10 * Tuukka Toivonen <tuukkat76@gmail.com> 10 * Tuukka Toivonen <tuukkat76@gmail.com>
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index e1d4c89d7140..10c3c1db4cdd 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -681,18 +681,7 @@ static struct i2c_driver adv7183_driver = {
681 .id_table = adv7183_id, 681 .id_table = adv7183_id,
682}; 682};
683 683
684static __init int adv7183_init(void) 684module_i2c_driver(adv7183_driver);
685{
686 return i2c_add_driver(&adv7183_driver);
687}
688
689static __exit void adv7183_exit(void)
690{
691 i2c_del_driver(&adv7183_driver);
692}
693
694module_init(adv7183_init);
695module_exit(adv7183_exit);
696 685
697MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); 686MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver");
698MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); 687MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 05f8950f6f91..f47555b1000a 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -486,9 +486,19 @@ static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
486 struct i2c_client *client = state->i2c_edid; 486 struct i2c_client *client = state->i2c_edid;
487 u8 msgbuf0[1] = { 0 }; 487 u8 msgbuf0[1] = { 0 };
488 u8 msgbuf1[256]; 488 u8 msgbuf1[256];
489 struct i2c_msg msg[2] = { { client->addr, 0, 1, msgbuf0 }, 489 struct i2c_msg msg[2] = {
490 { client->addr, 0 | I2C_M_RD, len, msgbuf1 } 490 {
491 }; 491 .addr = client->addr,
492 .len = 1,
493 .buf = msgbuf0
494 },
495 {
496 .addr = client->addr,
497 .flags = I2C_M_RD,
498 .len = len,
499 .buf = msgbuf1
500 },
501 };
492 502
493 if (i2c_transfer(client->adapter, msg, 2) < 0) 503 if (i2c_transfer(client->adapter, msg, 2) < 0)
494 return -EIO; 504 return -EIO;
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index 2cee69e34184..f4149eb4d7b4 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -2065,7 +2065,7 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
2065#define DIF_BPF_COEFF3435 (0x38c) 2065#define DIF_BPF_COEFF3435 (0x38c)
2066#define DIF_BPF_COEFF36 (0x390) 2066#define DIF_BPF_COEFF36 (0x390)
2067 2067
2068void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) 2068static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
2069{ 2069{
2070 u64 pll_freq; 2070 u64 pll_freq;
2071 u32 pll_freq_word; 2071 u32 pll_freq_word;
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 04f192a0398a..08ae067b2b6f 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -284,7 +284,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
284{ 284{
285 char *ir_codes = NULL; 285 char *ir_codes = NULL;
286 const char *name = NULL; 286 const char *name = NULL;
287 u64 rc_type = RC_TYPE_UNKNOWN; 287 u64 rc_type = RC_BIT_UNKNOWN;
288 struct IR_i2c *ir; 288 struct IR_i2c *ir;
289 struct rc_dev *rc = NULL; 289 struct rc_dev *rc = NULL;
290 struct i2c_adapter *adap = client->adapter; 290 struct i2c_adapter *adap = client->adapter;
@@ -303,7 +303,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
303 case 0x64: 303 case 0x64:
304 name = "Pixelview"; 304 name = "Pixelview";
305 ir->get_key = get_key_pixelview; 305 ir->get_key = get_key_pixelview;
306 rc_type = RC_TYPE_OTHER; 306 rc_type = RC_BIT_OTHER;
307 ir_codes = RC_MAP_EMPTY; 307 ir_codes = RC_MAP_EMPTY;
308 break; 308 break;
309 case 0x18: 309 case 0x18:
@@ -311,31 +311,31 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
311 case 0x1a: 311 case 0x1a:
312 name = "Hauppauge"; 312 name = "Hauppauge";
313 ir->get_key = get_key_haup; 313 ir->get_key = get_key_haup;
314 rc_type = RC_TYPE_RC5; 314 rc_type = RC_BIT_RC5;
315 ir_codes = RC_MAP_HAUPPAUGE; 315 ir_codes = RC_MAP_HAUPPAUGE;
316 break; 316 break;
317 case 0x30: 317 case 0x30:
318 name = "KNC One"; 318 name = "KNC One";
319 ir->get_key = get_key_knc1; 319 ir->get_key = get_key_knc1;
320 rc_type = RC_TYPE_OTHER; 320 rc_type = RC_BIT_OTHER;
321 ir_codes = RC_MAP_EMPTY; 321 ir_codes = RC_MAP_EMPTY;
322 break; 322 break;
323 case 0x6b: 323 case 0x6b:
324 name = "FusionHDTV"; 324 name = "FusionHDTV";
325 ir->get_key = get_key_fusionhdtv; 325 ir->get_key = get_key_fusionhdtv;
326 rc_type = RC_TYPE_RC5; 326 rc_type = RC_BIT_RC5;
327 ir_codes = RC_MAP_FUSIONHDTV_MCE; 327 ir_codes = RC_MAP_FUSIONHDTV_MCE;
328 break; 328 break;
329 case 0x40: 329 case 0x40:
330 name = "AVerMedia Cardbus remote"; 330 name = "AVerMedia Cardbus remote";
331 ir->get_key = get_key_avermedia_cardbus; 331 ir->get_key = get_key_avermedia_cardbus;
332 rc_type = RC_TYPE_OTHER; 332 rc_type = RC_BIT_OTHER;
333 ir_codes = RC_MAP_AVERMEDIA_CARDBUS; 333 ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
334 break; 334 break;
335 case 0x71: 335 case 0x71:
336 name = "Hauppauge/Zilog Z8"; 336 name = "Hauppauge/Zilog Z8";
337 ir->get_key = get_key_haup_xvr; 337 ir->get_key = get_key_haup_xvr;
338 rc_type = RC_TYPE_RC5; 338 rc_type = RC_BIT_RC5;
339 ir_codes = RC_MAP_HAUPPAUGE; 339 ir_codes = RC_MAP_HAUPPAUGE;
340 break; 340 break;
341 } 341 }
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index 49c1b3abb425..2750de634270 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -343,7 +343,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
343 } 343 }
344 regs_num = le32_to_cpu(get_unaligned_le32(fw->data)); 344 regs_num = le32_to_cpu(get_unaligned_le32(fw->data));
345 345
346 v4l2_dbg(3, debug, sd, "FW: %s size %d register sets %d\n", 346 v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
347 S5K4ECGX_FIRMWARE, fw->size, regs_num); 347 S5K4ECGX_FIRMWARE, fw->size, regs_num);
348 348
349 regs_num++; /* Add header */ 349 regs_num++; /* Add header */
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index a577614bd84f..d8d5da7c52db 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
@@ -58,7 +58,7 @@ static int bounds_check(struct device *dev, uint32_t val,
58 if (val >= min && val <= max) 58 if (val >= min && val <= max)
59 return 0; 59 return 0;
60 60
61 dev_warn(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max); 61 dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
62 62
63 return -EINVAL; 63 return -EINVAL;
64} 64}
@@ -87,14 +87,14 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
87 dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz); 87 dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
88} 88}
89 89
90int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits, 90static int __smiapp_pll_calculate(struct device *dev,
91 struct smiapp_pll *pll) 91 const struct smiapp_pll_limits *limits,
92 struct smiapp_pll *pll, uint32_t mul,
93 uint32_t div, uint32_t lane_op_clock_ratio)
92{ 94{
93 uint32_t sys_div; 95 uint32_t sys_div;
94 uint32_t best_pix_div = INT_MAX >> 1; 96 uint32_t best_pix_div = INT_MAX >> 1;
95 uint32_t vt_op_binning_div; 97 uint32_t vt_op_binning_div;
96 uint32_t lane_op_clock_ratio;
97 uint32_t mul, div;
98 uint32_t more_mul_min, more_mul_max; 98 uint32_t more_mul_min, more_mul_max;
99 uint32_t more_mul_factor; 99 uint32_t more_mul_factor;
100 uint32_t min_vt_div, max_vt_div, vt_div; 100 uint32_t min_vt_div, max_vt_div, vt_div;
@@ -102,54 +102,6 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
102 unsigned int i; 102 unsigned int i;
103 int rval; 103 int rval;
104 104
105 if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
106 lane_op_clock_ratio = pll->lanes;
107 else
108 lane_op_clock_ratio = 1;
109 dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
110
111 dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
112 pll->binning_vertical);
113
114 /* CSI transfers 2 bits per clock per lane; thus times 2 */
115 pll->pll_op_clk_freq_hz = pll->link_freq * 2
116 * (pll->lanes / lane_op_clock_ratio);
117
118 /* Figure out limits for pre-pll divider based on extclk */
119 dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
120 limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
121 limits->max_pre_pll_clk_div =
122 min_t(uint16_t, limits->max_pre_pll_clk_div,
123 clk_div_even(pll->ext_clk_freq_hz /
124 limits->min_pll_ip_freq_hz));
125 limits->min_pre_pll_clk_div =
126 max_t(uint16_t, limits->min_pre_pll_clk_div,
127 clk_div_even_up(
128 DIV_ROUND_UP(pll->ext_clk_freq_hz,
129 limits->max_pll_ip_freq_hz)));
130 dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
131 limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
132
133 i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
134 mul = div_u64(pll->pll_op_clk_freq_hz, i);
135 div = pll->ext_clk_freq_hz / i;
136 dev_dbg(dev, "mul %d / div %d\n", mul, div);
137
138 limits->min_pre_pll_clk_div =
139 max_t(uint16_t, limits->min_pre_pll_clk_div,
140 clk_div_even_up(
141 DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
142 limits->max_pll_op_freq_hz)));
143 dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
144 limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
145
146 if (limits->min_pre_pll_clk_div > limits->max_pre_pll_clk_div) {
147 dev_err(dev, "unable to compute pre_pll divisor\n");
148 return -EINVAL;
149 }
150
151 pll->pre_pll_clk_div = limits->min_pre_pll_clk_div;
152
153 /* 105 /*
154 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be 106 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
155 * too high. 107 * too high.
@@ -162,7 +114,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
162 more_mul_max); 114 more_mul_max);
163 /* Don't go above max pll op frequency. */ 115 /* Don't go above max pll op frequency. */
164 more_mul_max = 116 more_mul_max =
165 min_t(int, 117 min_t(uint32_t,
166 more_mul_max, 118 more_mul_max,
167 limits->max_pll_op_freq_hz 119 limits->max_pll_op_freq_hz
168 / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul)); 120 / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
@@ -170,7 +122,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
170 more_mul_max); 122 more_mul_max);
171 /* Don't go above the division capability of op sys clock divider. */ 123 /* Don't go above the division capability of op sys clock divider. */
172 more_mul_max = min(more_mul_max, 124 more_mul_max = min(more_mul_max,
173 limits->max_op_sys_clk_div * pll->pre_pll_clk_div 125 limits->op.max_sys_clk_div * pll->pre_pll_clk_div
174 / div); 126 / div);
175 dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n", 127 dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
176 more_mul_max); 128 more_mul_max);
@@ -193,14 +145,14 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
193 more_mul_min); 145 more_mul_min);
194 146
195 if (more_mul_min > more_mul_max) { 147 if (more_mul_min > more_mul_max) {
196 dev_warn(dev, 148 dev_dbg(dev,
197 "unable to compute more_mul_min and more_mul_max"); 149 "unable to compute more_mul_min and more_mul_max\n");
198 return -EINVAL; 150 return -EINVAL;
199 } 151 }
200 152
201 more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div; 153 more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
202 dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor); 154 dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
203 more_mul_factor = lcm(more_mul_factor, limits->min_op_sys_clk_div); 155 more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
204 dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n", 156 dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
205 more_mul_factor); 157 more_mul_factor);
206 i = roundup(more_mul_min, more_mul_factor); 158 i = roundup(more_mul_min, more_mul_factor);
@@ -209,7 +161,7 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
209 161
210 dev_dbg(dev, "final more_mul: %d\n", i); 162 dev_dbg(dev, "final more_mul: %d\n", i);
211 if (i > more_mul_max) { 163 if (i > more_mul_max) {
212 dev_warn(dev, "final more_mul is bad, max %d", more_mul_max); 164 dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
213 return -EINVAL; 165 return -EINVAL;
214 } 166 }
215 167
@@ -268,19 +220,19 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
268 dev_dbg(dev, "min_vt_div: %d\n", min_vt_div); 220 dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
269 min_vt_div = max(min_vt_div, 221 min_vt_div = max(min_vt_div,
270 DIV_ROUND_UP(pll->pll_op_clk_freq_hz, 222 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
271 limits->max_vt_pix_clk_freq_hz)); 223 limits->vt.max_pix_clk_freq_hz));
272 dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n", 224 dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
273 min_vt_div); 225 min_vt_div);
274 min_vt_div = max_t(uint32_t, min_vt_div, 226 min_vt_div = max_t(uint32_t, min_vt_div,
275 limits->min_vt_pix_clk_div 227 limits->vt.min_pix_clk_div
276 * limits->min_vt_sys_clk_div); 228 * limits->vt.min_sys_clk_div);
277 dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div); 229 dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
278 230
279 max_vt_div = limits->max_vt_sys_clk_div * limits->max_vt_pix_clk_div; 231 max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
280 dev_dbg(dev, "max_vt_div: %d\n", max_vt_div); 232 dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
281 max_vt_div = min(max_vt_div, 233 max_vt_div = min(max_vt_div,
282 DIV_ROUND_UP(pll->pll_op_clk_freq_hz, 234 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
283 limits->min_vt_pix_clk_freq_hz)); 235 limits->vt.min_pix_clk_freq_hz));
284 dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n", 236 dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
285 max_vt_div); 237 max_vt_div);
286 238
@@ -288,28 +240,28 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
288 * Find limitsits for sys_clk_div. Not all values are possible 240 * Find limitsits for sys_clk_div. Not all values are possible
289 * with all values of pix_clk_div. 241 * with all values of pix_clk_div.
290 */ 242 */
291 min_sys_div = limits->min_vt_sys_clk_div; 243 min_sys_div = limits->vt.min_sys_clk_div;
292 dev_dbg(dev, "min_sys_div: %d\n", min_sys_div); 244 dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
293 min_sys_div = max(min_sys_div, 245 min_sys_div = max(min_sys_div,
294 DIV_ROUND_UP(min_vt_div, 246 DIV_ROUND_UP(min_vt_div,
295 limits->max_vt_pix_clk_div)); 247 limits->vt.max_pix_clk_div));
296 dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div); 248 dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
297 min_sys_div = max(min_sys_div, 249 min_sys_div = max(min_sys_div,
298 pll->pll_op_clk_freq_hz 250 pll->pll_op_clk_freq_hz
299 / limits->max_vt_sys_clk_freq_hz); 251 / limits->vt.max_sys_clk_freq_hz);
300 dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div); 252 dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
301 min_sys_div = clk_div_even_up(min_sys_div); 253 min_sys_div = clk_div_even_up(min_sys_div);
302 dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div); 254 dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
303 255
304 max_sys_div = limits->max_vt_sys_clk_div; 256 max_sys_div = limits->vt.max_sys_clk_div;
305 dev_dbg(dev, "max_sys_div: %d\n", max_sys_div); 257 dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
306 max_sys_div = min(max_sys_div, 258 max_sys_div = min(max_sys_div,
307 DIV_ROUND_UP(max_vt_div, 259 DIV_ROUND_UP(max_vt_div,
308 limits->min_vt_pix_clk_div)); 260 limits->vt.min_pix_clk_div));
309 dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div); 261 dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
310 max_sys_div = min(max_sys_div, 262 max_sys_div = min(max_sys_div,
311 DIV_ROUND_UP(pll->pll_op_clk_freq_hz, 263 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
312 limits->min_vt_pix_clk_freq_hz)); 264 limits->vt.min_pix_clk_freq_hz));
313 dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div); 265 dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
314 266
315 /* 267 /*
@@ -322,15 +274,15 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
322 for (sys_div = min_sys_div; 274 for (sys_div = min_sys_div;
323 sys_div <= max_sys_div; 275 sys_div <= max_sys_div;
324 sys_div += 2 - (sys_div & 1)) { 276 sys_div += 2 - (sys_div & 1)) {
325 int pix_div = DIV_ROUND_UP(vt_div, sys_div); 277 uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
326 278
327 if (pix_div < limits->min_vt_pix_clk_div 279 if (pix_div < limits->vt.min_pix_clk_div
328 || pix_div > limits->max_vt_pix_clk_div) { 280 || pix_div > limits->vt.max_pix_clk_div) {
329 dev_dbg(dev, 281 dev_dbg(dev,
330 "pix_div %d too small or too big (%d--%d)\n", 282 "pix_div %d too small or too big (%d--%d)\n",
331 pix_div, 283 pix_div,
332 limits->min_vt_pix_clk_div, 284 limits->vt.min_pix_clk_div,
333 limits->max_vt_pix_clk_div); 285 limits->vt.max_pix_clk_div);
334 continue; 286 continue;
335 } 287 }
336 288
@@ -354,16 +306,10 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
354 pll->pixel_rate_csi = 306 pll->pixel_rate_csi =
355 pll->op_pix_clk_freq_hz * lane_op_clock_ratio; 307 pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
356 308
357 print_pll(dev, pll); 309 rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
358 310 limits->min_pll_ip_freq_hz,
359 rval = bounds_check(dev, pll->pre_pll_clk_div, 311 limits->max_pll_ip_freq_hz,
360 limits->min_pre_pll_clk_div, 312 "pll_ip_clk_freq_hz");
361 limits->max_pre_pll_clk_div, "pre_pll_clk_div");
362 if (!rval)
363 rval = bounds_check(
364 dev, pll->pll_ip_clk_freq_hz,
365 limits->min_pll_ip_freq_hz, limits->max_pll_ip_freq_hz,
366 "pll_ip_clk_freq_hz");
367 if (!rval) 313 if (!rval)
368 rval = bounds_check( 314 rval = bounds_check(
369 dev, pll->pll_multiplier, 315 dev, pll->pll_multiplier,
@@ -377,42 +323,121 @@ int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
377 if (!rval) 323 if (!rval)
378 rval = bounds_check( 324 rval = bounds_check(
379 dev, pll->op_sys_clk_div, 325 dev, pll->op_sys_clk_div,
380 limits->min_op_sys_clk_div, limits->max_op_sys_clk_div, 326 limits->op.min_sys_clk_div, limits->op.max_sys_clk_div,
381 "op_sys_clk_div"); 327 "op_sys_clk_div");
382 if (!rval) 328 if (!rval)
383 rval = bounds_check( 329 rval = bounds_check(
384 dev, pll->op_pix_clk_div, 330 dev, pll->op_pix_clk_div,
385 limits->min_op_pix_clk_div, limits->max_op_pix_clk_div, 331 limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
386 "op_pix_clk_div"); 332 "op_pix_clk_div");
387 if (!rval) 333 if (!rval)
388 rval = bounds_check( 334 rval = bounds_check(
389 dev, pll->op_sys_clk_freq_hz, 335 dev, pll->op_sys_clk_freq_hz,
390 limits->min_op_sys_clk_freq_hz, 336 limits->op.min_sys_clk_freq_hz,
391 limits->max_op_sys_clk_freq_hz, 337 limits->op.max_sys_clk_freq_hz,
392 "op_sys_clk_freq_hz"); 338 "op_sys_clk_freq_hz");
393 if (!rval) 339 if (!rval)
394 rval = bounds_check( 340 rval = bounds_check(
395 dev, pll->op_pix_clk_freq_hz, 341 dev, pll->op_pix_clk_freq_hz,
396 limits->min_op_pix_clk_freq_hz, 342 limits->op.min_pix_clk_freq_hz,
397 limits->max_op_pix_clk_freq_hz, 343 limits->op.max_pix_clk_freq_hz,
398 "op_pix_clk_freq_hz"); 344 "op_pix_clk_freq_hz");
399 if (!rval) 345 if (!rval)
400 rval = bounds_check( 346 rval = bounds_check(
401 dev, pll->vt_sys_clk_freq_hz, 347 dev, pll->vt_sys_clk_freq_hz,
402 limits->min_vt_sys_clk_freq_hz, 348 limits->vt.min_sys_clk_freq_hz,
403 limits->max_vt_sys_clk_freq_hz, 349 limits->vt.max_sys_clk_freq_hz,
404 "vt_sys_clk_freq_hz"); 350 "vt_sys_clk_freq_hz");
405 if (!rval) 351 if (!rval)
406 rval = bounds_check( 352 rval = bounds_check(
407 dev, pll->vt_pix_clk_freq_hz, 353 dev, pll->vt_pix_clk_freq_hz,
408 limits->min_vt_pix_clk_freq_hz, 354 limits->vt.min_pix_clk_freq_hz,
409 limits->max_vt_pix_clk_freq_hz, 355 limits->vt.max_pix_clk_freq_hz,
410 "vt_pix_clk_freq_hz"); 356 "vt_pix_clk_freq_hz");
411 357
412 return rval; 358 return rval;
413} 359}
360
361int smiapp_pll_calculate(struct device *dev,
362 const struct smiapp_pll_limits *limits,
363 struct smiapp_pll *pll)
364{
365 uint16_t min_pre_pll_clk_div;
366 uint16_t max_pre_pll_clk_div;
367 uint32_t lane_op_clock_ratio;
368 uint32_t mul, div;
369 unsigned int i;
370 int rval = -EINVAL;
371
372 if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
373 lane_op_clock_ratio = pll->csi2.lanes;
374 else
375 lane_op_clock_ratio = 1;
376 dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
377
378 dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
379 pll->binning_vertical);
380
381 switch (pll->bus_type) {
382 case SMIAPP_PLL_BUS_TYPE_CSI2:
383 /* CSI transfers 2 bits per clock per lane; thus times 2 */
384 pll->pll_op_clk_freq_hz = pll->link_freq * 2
385 * (pll->csi2.lanes / lane_op_clock_ratio);
386 break;
387 case SMIAPP_PLL_BUS_TYPE_PARALLEL:
388 pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel
389 / DIV_ROUND_UP(pll->bits_per_pixel,
390 pll->parallel.bus_width);
391 break;
392 default:
393 return -EINVAL;
394 }
395
396 /* Figure out limits for pre-pll divider based on extclk */
397 dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
398 limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
399 max_pre_pll_clk_div =
400 min_t(uint16_t, limits->max_pre_pll_clk_div,
401 clk_div_even(pll->ext_clk_freq_hz /
402 limits->min_pll_ip_freq_hz));
403 min_pre_pll_clk_div =
404 max_t(uint16_t, limits->min_pre_pll_clk_div,
405 clk_div_even_up(
406 DIV_ROUND_UP(pll->ext_clk_freq_hz,
407 limits->max_pll_ip_freq_hz)));
408 dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
409 min_pre_pll_clk_div, max_pre_pll_clk_div);
410
411 i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
412 mul = div_u64(pll->pll_op_clk_freq_hz, i);
413 div = pll->ext_clk_freq_hz / i;
414 dev_dbg(dev, "mul %d / div %d\n", mul, div);
415
416 min_pre_pll_clk_div =
417 max_t(uint16_t, min_pre_pll_clk_div,
418 clk_div_even_up(
419 DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
420 limits->max_pll_op_freq_hz)));
421 dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
422 min_pre_pll_clk_div, max_pre_pll_clk_div);
423
424 for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
425 pll->pre_pll_clk_div <= max_pre_pll_clk_div;
426 pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
427 rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
428 lane_op_clock_ratio);
429 if (rval)
430 continue;
431
432 print_pll(dev, pll);
433 return 0;
434 }
435
436 dev_info(dev, "unable to compute pre_pll divisor\n");
437 return rval;
438}
414EXPORT_SYMBOL_GPL(smiapp_pll_calculate); 439EXPORT_SYMBOL_GPL(smiapp_pll_calculate);
415 440
416MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>"); 441MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
417MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator"); 442MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator");
418MODULE_LICENSE("GPL"); 443MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index cb2d2db5d02d..a4a649834a18 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2012 Nokia Corporation 6 * Copyright (C) 2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
@@ -27,16 +27,34 @@
27 27
28#include <linux/device.h> 28#include <linux/device.h>
29 29
30/* CSI-2 or CCP-2 */
31#define SMIAPP_PLL_BUS_TYPE_CSI2 0x00
32#define SMIAPP_PLL_BUS_TYPE_PARALLEL 0x01
33
34/* op pix clock is for all lanes in total normally */
35#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0)
36#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS (1 << 1)
37
30struct smiapp_pll { 38struct smiapp_pll {
31 uint8_t lanes; 39 /* input values */
40 uint8_t bus_type;
41 union {
42 struct {
43 uint8_t lanes;
44 } csi2;
45 struct {
46 uint8_t bus_width;
47 } parallel;
48 };
49 uint8_t flags;
32 uint8_t binning_horizontal; 50 uint8_t binning_horizontal;
33 uint8_t binning_vertical; 51 uint8_t binning_vertical;
34 uint8_t scale_m; 52 uint8_t scale_m;
35 uint8_t scale_n; 53 uint8_t scale_n;
36 uint8_t bits_per_pixel; 54 uint8_t bits_per_pixel;
37 uint16_t flags;
38 uint32_t link_freq; 55 uint32_t link_freq;
39 56
57 /* output values */
40 uint16_t pre_pll_clk_div; 58 uint16_t pre_pll_clk_div;
41 uint16_t pll_multiplier; 59 uint16_t pll_multiplier;
42 uint16_t op_sys_clk_div; 60 uint16_t op_sys_clk_div;
@@ -55,6 +73,17 @@ struct smiapp_pll {
55 uint32_t pixel_rate_csi; 73 uint32_t pixel_rate_csi;
56}; 74};
57 75
76struct smiapp_pll_branch_limits {
77 uint16_t min_sys_clk_div;
78 uint16_t max_sys_clk_div;
79 uint32_t min_sys_clk_freq_hz;
80 uint32_t max_sys_clk_freq_hz;
81 uint16_t min_pix_clk_div;
82 uint16_t max_pix_clk_div;
83 uint32_t min_pix_clk_freq_hz;
84 uint32_t max_pix_clk_freq_hz;
85};
86
58struct smiapp_pll_limits { 87struct smiapp_pll_limits {
59 /* Strict PLL limits */ 88 /* Strict PLL limits */
60 uint32_t min_ext_clk_freq_hz; 89 uint32_t min_ext_clk_freq_hz;
@@ -68,36 +97,18 @@ struct smiapp_pll_limits {
68 uint32_t min_pll_op_freq_hz; 97 uint32_t min_pll_op_freq_hz;
69 uint32_t max_pll_op_freq_hz; 98 uint32_t max_pll_op_freq_hz;
70 99
71 uint16_t min_vt_sys_clk_div; 100 struct smiapp_pll_branch_limits vt;
72 uint16_t max_vt_sys_clk_div; 101 struct smiapp_pll_branch_limits op;
73 uint32_t min_vt_sys_clk_freq_hz;
74 uint32_t max_vt_sys_clk_freq_hz;
75 uint16_t min_vt_pix_clk_div;
76 uint16_t max_vt_pix_clk_div;
77 uint32_t min_vt_pix_clk_freq_hz;
78 uint32_t max_vt_pix_clk_freq_hz;
79
80 uint16_t min_op_sys_clk_div;
81 uint16_t max_op_sys_clk_div;
82 uint32_t min_op_sys_clk_freq_hz;
83 uint32_t max_op_sys_clk_freq_hz;
84 uint16_t min_op_pix_clk_div;
85 uint16_t max_op_pix_clk_div;
86 uint32_t min_op_pix_clk_freq_hz;
87 uint32_t max_op_pix_clk_freq_hz;
88 102
89 /* Other relevant limits */ 103 /* Other relevant limits */
90 uint32_t min_line_length_pck_bin; 104 uint32_t min_line_length_pck_bin;
91 uint32_t min_line_length_pck; 105 uint32_t min_line_length_pck;
92}; 106};
93 107
94/* op pix clock is for all lanes in total normally */
95#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0)
96#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS (1 << 1)
97
98struct device; 108struct device;
99 109
100int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits, 110int smiapp_pll_calculate(struct device *dev,
111 const struct smiapp_pll_limits *limits,
101 struct smiapp_pll *pll); 112 struct smiapp_pll *pll);
102 113
103#endif /* SMIAPP_PLL_H */ 114#endif /* SMIAPP_PLL_H */
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index e08e588ad24b..83c7ed7ffcc2 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2010--2012 Nokia Corporation 6 * Copyright (C) 2010--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * Based on smiapp driver by Vimarsh Zutshi 9 * Based on smiapp driver by Vimarsh Zutshi
10 * Based on jt8ev1.c by Vimarsh Zutshi 10 * Based on jt8ev1.c by Vimarsh Zutshi
@@ -252,23 +252,23 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
252 .min_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ], 252 .min_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ],
253 .max_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ], 253 .max_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ],
254 254
255 .min_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV], 255 .op.min_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
256 .max_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV], 256 .op.max_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
257 .min_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV], 257 .op.min_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
258 .max_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV], 258 .op.max_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
259 .min_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ], 259 .op.min_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
260 .max_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ], 260 .op.max_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
261 .min_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ], 261 .op.min_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
262 .max_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ], 262 .op.max_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
263 263
264 .min_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV], 264 .vt.min_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
265 .max_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV], 265 .vt.max_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
266 .min_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV], 266 .vt.min_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
267 .max_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV], 267 .vt.max_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
268 .min_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ], 268 .vt.min_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
269 .max_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ], 269 .vt.max_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
270 .min_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ], 270 .vt.min_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
271 .max_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ], 271 .vt.max_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
272 272
273 .min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN], 273 .min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
274 .min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK], 274 .min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
@@ -276,11 +276,6 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
276 struct smiapp_pll *pll = &sensor->pll; 276 struct smiapp_pll *pll = &sensor->pll;
277 int rval; 277 int rval;
278 278
279 memset(&sensor->pll, 0, sizeof(sensor->pll));
280
281 pll->lanes = sensor->platform_data->lanes;
282 pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
283
284 if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) { 279 if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
285 /* 280 /*
286 * Fill in operational clock divisors limits from the 281 * Fill in operational clock divisors limits from the
@@ -288,28 +283,14 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
288 * requirements regarding them are essentially the 283 * requirements regarding them are essentially the
289 * same as on VT ones. 284 * same as on VT ones.
290 */ 285 */
291 lim.min_op_sys_clk_div = lim.min_vt_sys_clk_div; 286 lim.op = lim.vt;
292 lim.max_op_sys_clk_div = lim.max_vt_sys_clk_div;
293 lim.min_op_pix_clk_div = lim.min_vt_pix_clk_div;
294 lim.max_op_pix_clk_div = lim.max_vt_pix_clk_div;
295 lim.min_op_sys_clk_freq_hz = lim.min_vt_sys_clk_freq_hz;
296 lim.max_op_sys_clk_freq_hz = lim.max_vt_sys_clk_freq_hz;
297 lim.min_op_pix_clk_freq_hz = lim.min_vt_pix_clk_freq_hz;
298 lim.max_op_pix_clk_freq_hz = lim.max_vt_pix_clk_freq_hz;
299 /* Profile 0 sensors have no separate OP clock branch. */
300 pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
301 } 287 }
302 288
303 if (smiapp_needs_quirk(sensor,
304 SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
305 pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
306
307 pll->binning_horizontal = sensor->binning_horizontal; 289 pll->binning_horizontal = sensor->binning_horizontal;
308 pll->binning_vertical = sensor->binning_vertical; 290 pll->binning_vertical = sensor->binning_vertical;
309 pll->link_freq = 291 pll->link_freq =
310 sensor->link_freq->qmenu_int[sensor->link_freq->val]; 292 sensor->link_freq->qmenu_int[sensor->link_freq->val];
311 pll->scale_m = sensor->scale_m; 293 pll->scale_m = sensor->scale_m;
312 pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
313 pll->bits_per_pixel = sensor->csi_format->compressed; 294 pll->bits_per_pixel = sensor->csi_format->compressed;
314 295
315 rval = smiapp_pll_calculate(&client->dev, &lim, pll); 296 rval = smiapp_pll_calculate(&client->dev, &lim, pll);
@@ -1010,7 +991,7 @@ static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)
1010 * do not change, or if you do at least know what you're 991 * do not change, or if you do at least know what you're
1011 * doing. :-) 992 * doing. :-)
1012 * 993 *
1013 * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 2010-10-25 994 * Sakari Ailus <sakari.ailus@iki.fi> 2010-10-25
1014 * 995 *
1015 * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl 996 * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl
1016 * / EXTCLK freq [Hz]) * flash_strobe_adjustment 997 * / EXTCLK freq [Hz]) * flash_strobe_adjustment
@@ -2369,6 +2350,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
2369{ 2350{
2370 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); 2351 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2371 struct i2c_client *client = v4l2_get_subdevdata(subdev); 2352 struct i2c_client *client = v4l2_get_subdevdata(subdev);
2353 struct smiapp_pll *pll = &sensor->pll;
2372 struct smiapp_subdev *last = NULL; 2354 struct smiapp_subdev *last = NULL;
2373 u32 tmp; 2355 u32 tmp;
2374 unsigned int i; 2356 unsigned int i;
@@ -2635,6 +2617,18 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
2635 if (rval < 0) 2617 if (rval < 0)
2636 goto out_nvm_release; 2618 goto out_nvm_release;
2637 2619
2620 /* prepare PLL configuration input values */
2621 pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
2622 pll->csi2.lanes = sensor->platform_data->lanes;
2623 pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
2624 /* Profile 0 sensors have no separate OP clock branch. */
2625 if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
2626 pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
2627 if (smiapp_needs_quirk(sensor,
2628 SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
2629 pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
2630 pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
2631
2638 rval = smiapp_update_mode(sensor); 2632 rval = smiapp_update_mode(sensor);
2639 if (rval) { 2633 if (rval) {
2640 dev_err(&client->dev, "update mode failed\n"); 2634 dev_err(&client->dev, "update mode failed\n");
@@ -2893,6 +2887,6 @@ static struct i2c_driver smiapp_i2c_driver = {
2893 2887
2894module_i2c_driver(smiapp_i2c_driver); 2888module_i2c_driver(smiapp_i2c_driver);
2895 2889
2896MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>"); 2890MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
2897MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver"); 2891MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver");
2898MODULE_LICENSE("GPL"); 2892MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.c b/drivers/media/i2c/smiapp/smiapp-limits.c
index fb2f81ad8c3b..847cb235e198 100644
--- a/drivers/media/i2c/smiapp/smiapp-limits.c
+++ b/drivers/media/i2c/smiapp/smiapp-limits.c
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.h b/drivers/media/i2c/smiapp/smiapp-limits.h
index 9ae765e23ea5..343e9c3827fc 100644
--- a/drivers/media/i2c/smiapp/smiapp-limits.h
+++ b/drivers/media/i2c/smiapp/smiapp-limits.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
index 725cf62836c6..bb8c506e0e3d 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.c
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
index 86fd3e8bfb0f..504a6d80ced5 100644
--- a/drivers/media/i2c/smiapp/smiapp-quirk.h
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
index defa7c5adebf..3aa0ca948d87 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-reg.h b/drivers/media/i2c/smiapp/smiapp-reg.h
index 54568ca2fe6d..b0dcbb8fa5e2 100644
--- a/drivers/media/i2c/smiapp/smiapp-reg.h
+++ b/drivers/media/i2c/smiapp/smiapp-reg.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
index 70e0d8db0130..4fac32cfcb3f 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.c
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
index 7f9013b47971..eefc6c84d5fe 100644
--- a/drivers/media/i2c/smiapp/smiapp-regs.h
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2011--2012 Nokia Corporation 6 * Copyright (C) 2011--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index 4182a695ab53..7cc5aae662fd 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -4,7 +4,7 @@
4 * Generic driver for SMIA/SMIA++ compliant camera modules 4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 * 5 *
6 * Copyright (C) 2010--2012 Nokia Corporation 6 * Copyright (C) 2010--2012 Nokia Corporation
7 * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index 333ef178d6fb..d40a8858be01 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -15,6 +15,7 @@
15#include <linux/log2.h> 15#include <linux/log2.h>
16#include <linux/module.h> 16#include <linux/module.h>
17 17
18#include <media/mt9v022.h>
18#include <media/soc_camera.h> 19#include <media/soc_camera.h>
19#include <media/soc_mediabus.h> 20#include <media/soc_mediabus.h>
20#include <media/v4l2-subdev.h> 21#include <media/v4l2-subdev.h>
@@ -50,6 +51,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
50#define MT9V022_PIXEL_OPERATION_MODE 0x0f 51#define MT9V022_PIXEL_OPERATION_MODE 0x0f
51#define MT9V022_LED_OUT_CONTROL 0x1b 52#define MT9V022_LED_OUT_CONTROL 0x1b
52#define MT9V022_ADC_MODE_CONTROL 0x1c 53#define MT9V022_ADC_MODE_CONTROL 0x1c
54#define MT9V022_REG32 0x20
53#define MT9V022_ANALOG_GAIN 0x35 55#define MT9V022_ANALOG_GAIN 0x35
54#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 56#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
55#define MT9V022_PIXCLK_FV_LV 0x74 57#define MT9V022_PIXCLK_FV_LV 0x74
@@ -71,7 +73,15 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
71#define MT9V022_COLUMN_SKIP 1 73#define MT9V022_COLUMN_SKIP 1
72#define MT9V022_ROW_SKIP 4 74#define MT9V022_ROW_SKIP 4
73 75
74#define is_mt9v024(id) (id == 0x1324) 76#define MT9V022_HORIZONTAL_BLANKING_MIN 43
77#define MT9V022_HORIZONTAL_BLANKING_MAX 1023
78#define MT9V022_HORIZONTAL_BLANKING_DEF 94
79#define MT9V022_VERTICAL_BLANKING_MIN 2
80#define MT9V022_VERTICAL_BLANKING_MAX 3000
81#define MT9V022_VERTICAL_BLANKING_DEF 45
82
83#define is_mt9v022_rev3(id) (id == 0x1313)
84#define is_mt9v024(id) (id == 0x1324)
75 85
76/* MT9V022 has only one fixed colorspace per pixelcode */ 86/* MT9V022 has only one fixed colorspace per pixelcode */
77struct mt9v022_datafmt { 87struct mt9v022_datafmt {
@@ -136,6 +146,8 @@ struct mt9v022 {
136 struct v4l2_ctrl *autogain; 146 struct v4l2_ctrl *autogain;
137 struct v4l2_ctrl *gain; 147 struct v4l2_ctrl *gain;
138 }; 148 };
149 struct v4l2_ctrl *hblank;
150 struct v4l2_ctrl *vblank;
139 struct v4l2_rect rect; /* Sensor window */ 151 struct v4l2_rect rect; /* Sensor window */
140 const struct mt9v022_datafmt *fmt; 152 const struct mt9v022_datafmt *fmt;
141 const struct mt9v022_datafmt *fmts; 153 const struct mt9v022_datafmt *fmts;
@@ -143,6 +155,7 @@ struct mt9v022 {
143 int num_fmts; 155 int num_fmts;
144 int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ 156 int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
145 u16 chip_control; 157 u16 chip_control;
158 u16 chip_version;
146 unsigned short y_skip_top; /* Lines to skip at the top */ 159 unsigned short y_skip_top; /* Lines to skip at the top */
147}; 160};
148 161
@@ -225,12 +238,32 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
225 struct i2c_client *client = v4l2_get_subdevdata(sd); 238 struct i2c_client *client = v4l2_get_subdevdata(sd);
226 struct mt9v022 *mt9v022 = to_mt9v022(client); 239 struct mt9v022 *mt9v022 = to_mt9v022(client);
227 240
228 if (enable) 241 if (enable) {
229 /* Switch to master "normal" mode */ 242 /* Switch to master "normal" mode */
230 mt9v022->chip_control &= ~0x10; 243 mt9v022->chip_control &= ~0x10;
231 else 244 if (is_mt9v022_rev3(mt9v022->chip_version) ||
245 is_mt9v024(mt9v022->chip_version)) {
246 /*
247 * Unset snapshot mode specific settings: clear bit 9
248 * and bit 2 in reg. 0x20 when in normal mode.
249 */
250 if (reg_clear(client, MT9V022_REG32, 0x204))
251 return -EIO;
252 }
253 } else {
232 /* Switch to snapshot mode */ 254 /* Switch to snapshot mode */
233 mt9v022->chip_control |= 0x10; 255 mt9v022->chip_control |= 0x10;
256 if (is_mt9v022_rev3(mt9v022->chip_version) ||
257 is_mt9v024(mt9v022->chip_version)) {
258 /*
259 * Required settings for snapshot mode: set bit 9
260 * (RST enable) and bit 2 (CR enable) in reg. 0x20
261 * See TechNote TN0960 or TN-09-225.
262 */
263 if (reg_set(client, MT9V022_REG32, 0x204))
264 return -EIO;
265 }
266 }
234 267
235 if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) 268 if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0)
236 return -EIO; 269 return -EIO;
@@ -282,11 +315,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
282 * Default 94, Phytec driver says: 315 * Default 94, Phytec driver says:
283 * "width + horizontal blank >= 660" 316 * "width + horizontal blank >= 660"
284 */ 317 */
285 ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, 318 ret = v4l2_ctrl_s_ctrl(mt9v022->hblank,
286 rect.width > 660 - 43 ? 43 : 319 rect.width > 660 - 43 ? 43 : 660 - rect.width);
287 660 - rect.width);
288 if (!ret) 320 if (!ret)
289 ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); 321 ret = v4l2_ctrl_s_ctrl(mt9v022->vblank, 45);
290 if (!ret) 322 if (!ret)
291 ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); 323 ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
292 if (!ret) 324 if (!ret)
@@ -509,6 +541,18 @@ static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
509 range = exp->maximum - exp->minimum; 541 range = exp->maximum - exp->minimum;
510 exp->val = ((data - 1) * range + 239) / 479 + exp->minimum; 542 exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
511 return 0; 543 return 0;
544 case V4L2_CID_HBLANK:
545 data = reg_read(client, MT9V022_HORIZONTAL_BLANKING);
546 if (data < 0)
547 return -EIO;
548 ctrl->val = data;
549 return 0;
550 case V4L2_CID_VBLANK:
551 data = reg_read(client, MT9V022_VERTICAL_BLANKING);
552 if (data < 0)
553 return -EIO;
554 ctrl->val = data;
555 return 0;
512 } 556 }
513 return -EINVAL; 557 return -EINVAL;
514} 558}
@@ -590,6 +634,16 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
590 return -EIO; 634 return -EIO;
591 } 635 }
592 return 0; 636 return 0;
637 case V4L2_CID_HBLANK:
638 if (reg_write(client, MT9V022_HORIZONTAL_BLANKING,
639 ctrl->val) < 0)
640 return -EIO;
641 return 0;
642 case V4L2_CID_VBLANK:
643 if (reg_write(client, MT9V022_VERTICAL_BLANKING,
644 ctrl->val) < 0)
645 return -EIO;
646 return 0;
593 } 647 }
594 return -EINVAL; 648 return -EINVAL;
595} 649}
@@ -621,6 +675,8 @@ static int mt9v022_video_probe(struct i2c_client *client)
621 goto ei2c; 675 goto ei2c;
622 } 676 }
623 677
678 mt9v022->chip_version = data;
679
624 mt9v022->reg = is_mt9v024(data) ? &mt9v024_register : 680 mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
625 &mt9v022_register; 681 &mt9v022_register;
626 682
@@ -819,6 +875,7 @@ static int mt9v022_probe(struct i2c_client *client,
819 struct mt9v022 *mt9v022; 875 struct mt9v022 *mt9v022;
820 struct soc_camera_link *icl = soc_camera_i2c_to_link(client); 876 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
821 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 877 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
878 struct mt9v022_platform_data *pdata = icl->priv;
822 int ret; 879 int ret;
823 880
824 if (!icl) { 881 if (!icl) {
@@ -857,10 +914,21 @@ static int mt9v022_probe(struct i2c_client *client,
857 mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops, 914 mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
858 V4L2_CID_EXPOSURE, 1, 255, 1, 255); 915 V4L2_CID_EXPOSURE, 1, 255, 1, 255);
859 916
917 mt9v022->hblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
918 V4L2_CID_HBLANK, MT9V022_HORIZONTAL_BLANKING_MIN,
919 MT9V022_HORIZONTAL_BLANKING_MAX, 1,
920 MT9V022_HORIZONTAL_BLANKING_DEF);
921
922 mt9v022->vblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
923 V4L2_CID_VBLANK, MT9V022_VERTICAL_BLANKING_MIN,
924 MT9V022_VERTICAL_BLANKING_MAX, 1,
925 MT9V022_VERTICAL_BLANKING_DEF);
926
860 mt9v022->subdev.ctrl_handler = &mt9v022->hdl; 927 mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
861 if (mt9v022->hdl.error) { 928 if (mt9v022->hdl.error) {
862 int err = mt9v022->hdl.error; 929 int err = mt9v022->hdl.error;
863 930
931 dev_err(&client->dev, "control initialisation err %d\n", err);
864 kfree(mt9v022); 932 kfree(mt9v022);
865 return err; 933 return err;
866 } 934 }
@@ -871,10 +939,10 @@ static int mt9v022_probe(struct i2c_client *client,
871 mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; 939 mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
872 940
873 /* 941 /*
874 * MT9V022 _really_ corrupts the first read out line. 942 * On some platforms the first read out line is corrupted.
875 * TODO: verify on i.MX31 943 * Workaround it by skipping if indicated by platform data.
876 */ 944 */
877 mt9v022->y_skip_top = 1; 945 mt9v022->y_skip_top = pdata ? pdata->y_skip_top : 0;
878 mt9v022->rect.left = MT9V022_COLUMN_SKIP; 946 mt9v022->rect.left = MT9V022_COLUMN_SKIP;
879 mt9v022->rect.top = MT9V022_ROW_SKIP; 947 mt9v022->rect.top = MT9V022_ROW_SKIP;
880 mt9v022->rect.width = MT9V022_MAX_WIDTH; 948 mt9v022->rect.width = MT9V022_MAX_WIDTH;
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index d2d298b6354e..66698a83bda2 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -586,9 +586,20 @@ static const struct regval_list ov2640_format_change_preamble_regs[] = {
586 ENDMARKER, 586 ENDMARKER,
587}; 587};
588 588
589static const struct regval_list ov2640_yuv422_regs[] = { 589static const struct regval_list ov2640_yuyv_regs[] = {
590 { IMAGE_MODE, IMAGE_MODE_YUV422 },
591 { 0xd7, 0x03 },
592 { 0x33, 0xa0 },
593 { 0xe5, 0x1f },
594 { 0xe1, 0x67 },
595 { RESET, 0x00 },
596 { R_BYPASS, R_BYPASS_USE_DSP },
597 ENDMARKER,
598};
599
600static const struct regval_list ov2640_uyvy_regs[] = {
590 { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 }, 601 { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },
591 { 0xD7, 0x01 }, 602 { 0xd7, 0x01 },
592 { 0x33, 0xa0 }, 603 { 0x33, 0xa0 },
593 { 0xe1, 0x67 }, 604 { 0xe1, 0x67 },
594 { RESET, 0x00 }, 605 { RESET, 0x00 },
@@ -596,7 +607,15 @@ static const struct regval_list ov2640_yuv422_regs[] = {
596 ENDMARKER, 607 ENDMARKER,
597}; 608};
598 609
599static const struct regval_list ov2640_rgb565_regs[] = { 610static const struct regval_list ov2640_rgb565_be_regs[] = {
611 { IMAGE_MODE, IMAGE_MODE_RGB565 },
612 { 0xd7, 0x03 },
613 { RESET, 0x00 },
614 { R_BYPASS, R_BYPASS_USE_DSP },
615 ENDMARKER,
616};
617
618static const struct regval_list ov2640_rgb565_le_regs[] = {
600 { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 }, 619 { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },
601 { 0xd7, 0x03 }, 620 { 0xd7, 0x03 },
602 { RESET, 0x00 }, 621 { RESET, 0x00 },
@@ -605,7 +624,9 @@ static const struct regval_list ov2640_rgb565_regs[] = {
605}; 624};
606 625
607static enum v4l2_mbus_pixelcode ov2640_codes[] = { 626static enum v4l2_mbus_pixelcode ov2640_codes[] = {
627 V4L2_MBUS_FMT_YUYV8_2X8,
608 V4L2_MBUS_FMT_UYVY8_2X8, 628 V4L2_MBUS_FMT_UYVY8_2X8,
629 V4L2_MBUS_FMT_RGB565_2X8_BE,
609 V4L2_MBUS_FMT_RGB565_2X8_LE, 630 V4L2_MBUS_FMT_RGB565_2X8_LE,
610}; 631};
611 632
@@ -787,14 +808,22 @@ static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
787 /* select format */ 808 /* select format */
788 priv->cfmt_code = 0; 809 priv->cfmt_code = 0;
789 switch (code) { 810 switch (code) {
811 case V4L2_MBUS_FMT_RGB565_2X8_BE:
812 dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
813 selected_cfmt_regs = ov2640_rgb565_be_regs;
814 break;
790 case V4L2_MBUS_FMT_RGB565_2X8_LE: 815 case V4L2_MBUS_FMT_RGB565_2X8_LE:
791 dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__); 816 dev_dbg(&client->dev, "%s: Selected cfmt RGB565 LE", __func__);
792 selected_cfmt_regs = ov2640_rgb565_regs; 817 selected_cfmt_regs = ov2640_rgb565_le_regs;
818 break;
819 case V4L2_MBUS_FMT_YUYV8_2X8:
820 dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);
821 selected_cfmt_regs = ov2640_yuyv_regs;
793 break; 822 break;
794 default: 823 default:
795 case V4L2_MBUS_FMT_UYVY8_2X8: 824 case V4L2_MBUS_FMT_UYVY8_2X8:
796 dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__); 825 dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);
797 selected_cfmt_regs = ov2640_yuv422_regs; 826 selected_cfmt_regs = ov2640_uyvy_regs;
798 } 827 }
799 828
800 /* reset hardware */ 829 /* reset hardware */
@@ -859,10 +888,12 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd,
859 mf->code = priv->cfmt_code; 888 mf->code = priv->cfmt_code;
860 889
861 switch (mf->code) { 890 switch (mf->code) {
891 case V4L2_MBUS_FMT_RGB565_2X8_BE:
862 case V4L2_MBUS_FMT_RGB565_2X8_LE: 892 case V4L2_MBUS_FMT_RGB565_2X8_LE:
863 mf->colorspace = V4L2_COLORSPACE_SRGB; 893 mf->colorspace = V4L2_COLORSPACE_SRGB;
864 break; 894 break;
865 default: 895 default:
896 case V4L2_MBUS_FMT_YUYV8_2X8:
866 case V4L2_MBUS_FMT_UYVY8_2X8: 897 case V4L2_MBUS_FMT_UYVY8_2X8:
867 mf->colorspace = V4L2_COLORSPACE_JPEG; 898 mf->colorspace = V4L2_COLORSPACE_JPEG;
868 } 899 }
@@ -879,11 +910,13 @@ static int ov2640_s_fmt(struct v4l2_subdev *sd,
879 910
880 911
881 switch (mf->code) { 912 switch (mf->code) {
913 case V4L2_MBUS_FMT_RGB565_2X8_BE:
882 case V4L2_MBUS_FMT_RGB565_2X8_LE: 914 case V4L2_MBUS_FMT_RGB565_2X8_LE:
883 mf->colorspace = V4L2_COLORSPACE_SRGB; 915 mf->colorspace = V4L2_COLORSPACE_SRGB;
884 break; 916 break;
885 default: 917 default:
886 mf->code = V4L2_MBUS_FMT_UYVY8_2X8; 918 mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
919 case V4L2_MBUS_FMT_YUYV8_2X8:
887 case V4L2_MBUS_FMT_UYVY8_2X8: 920 case V4L2_MBUS_FMT_UYVY8_2X8:
888 mf->colorspace = V4L2_COLORSPACE_JPEG; 921 mf->colorspace = V4L2_COLORSPACE_JPEG;
889 } 922 }
@@ -896,21 +929,21 @@ static int ov2640_s_fmt(struct v4l2_subdev *sd,
896static int ov2640_try_fmt(struct v4l2_subdev *sd, 929static int ov2640_try_fmt(struct v4l2_subdev *sd,
897 struct v4l2_mbus_framefmt *mf) 930 struct v4l2_mbus_framefmt *mf)
898{ 931{
899 const struct ov2640_win_size *win;
900
901 /* 932 /*
902 * select suitable win 933 * select suitable win, but don't store it
903 */ 934 */
904 win = ov2640_select_win(&mf->width, &mf->height); 935 ov2640_select_win(&mf->width, &mf->height);
905 936
906 mf->field = V4L2_FIELD_NONE; 937 mf->field = V4L2_FIELD_NONE;
907 938
908 switch (mf->code) { 939 switch (mf->code) {
940 case V4L2_MBUS_FMT_RGB565_2X8_BE:
909 case V4L2_MBUS_FMT_RGB565_2X8_LE: 941 case V4L2_MBUS_FMT_RGB565_2X8_LE:
910 mf->colorspace = V4L2_COLORSPACE_SRGB; 942 mf->colorspace = V4L2_COLORSPACE_SRGB;
911 break; 943 break;
912 default: 944 default:
913 mf->code = V4L2_MBUS_FMT_UYVY8_2X8; 945 mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
946 case V4L2_MBUS_FMT_YUYV8_2X8:
914 case V4L2_MBUS_FMT_UYVY8_2X8: 947 case V4L2_MBUS_FMT_UYVY8_2X8:
915 mf->colorspace = V4L2_COLORSPACE_JPEG; 948 mf->colorspace = V4L2_COLORSPACE_JPEG;
916 } 949 }
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
index 42ae9dc9c574..f434a19b9bcb 100644
--- a/drivers/media/i2c/vs6624.c
+++ b/drivers/media/i2c/vs6624.c
@@ -910,18 +910,7 @@ static struct i2c_driver vs6624_driver = {
910 .id_table = vs6624_id, 910 .id_table = vs6624_id,
911}; 911};
912 912
913static __init int vs6624_init(void) 913module_i2c_driver(vs6624_driver);
914{
915 return i2c_add_driver(&vs6624_driver);
916}
917
918static __exit void vs6624_exit(void)
919{
920 i2c_del_driver(&vs6624_driver);
921}
922
923module_init(vs6624_init);
924module_exit(vs6624_exit);
925 914
926MODULE_DESCRIPTION("VS6624 sensor driver"); 915MODULE_DESCRIPTION("VS6624 sensor driver");
927MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); 916MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");