diff options
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r-- | drivers/media/i2c/adp1653.c | 4 | ||||
-rw-r--r-- | drivers/media/i2c/adv7183.c | 13 | ||||
-rw-r--r-- | drivers/media/i2c/adv7604.c | 16 | ||||
-rw-r--r-- | drivers/media/i2c/cx25840/cx25840-core.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/ir-kbd-i2c.c | 14 | ||||
-rw-r--r-- | drivers/media/i2c/s5k4ecgx.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp-pll.c | 219 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp-pll.h | 61 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-core.c | 74 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-limits.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-limits.h | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-quirk.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-quirk.h | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-reg-defs.h | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-reg.h | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-regs.c | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp-regs.h | 2 | ||||
-rw-r--r-- | drivers/media/i2c/smiapp/smiapp.h | 2 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9v022.c | 88 | ||||
-rw-r--r-- | drivers/media/i2c/soc_camera/ov2640.c | 55 | ||||
-rw-r--r-- | drivers/media/i2c/vs6624.c | 13 |
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 | ||
684 | static __init int adv7183_init(void) | 684 | module_i2c_driver(adv7183_driver); |
685 | { | ||
686 | return i2c_add_driver(&adv7183_driver); | ||
687 | } | ||
688 | |||
689 | static __exit void adv7183_exit(void) | ||
690 | { | ||
691 | i2c_del_driver(&adv7183_driver); | ||
692 | } | ||
693 | |||
694 | module_init(adv7183_init); | ||
695 | module_exit(adv7183_exit); | ||
696 | 685 | ||
697 | MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); | 686 | MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); |
698 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | 687 | MODULE_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 | ||
2068 | void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) | 2068 | static 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 | ||
90 | int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits, | 90 | static 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 | |||
361 | int 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 | } | ||
414 | EXPORT_SYMBOL_GPL(smiapp_pll_calculate); | 439 | EXPORT_SYMBOL_GPL(smiapp_pll_calculate); |
415 | 440 | ||
416 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>"); | 441 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>"); |
417 | MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator"); | 442 | MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator"); |
418 | MODULE_LICENSE("GPL"); | 443 | MODULE_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 | |||
30 | struct smiapp_pll { | 38 | struct 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 | ||
76 | struct 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 | |||
58 | struct smiapp_pll_limits { | 87 | struct 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 | |||
98 | struct device; | 108 | struct device; |
99 | 109 | ||
100 | int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits, | 110 | int 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 | ||
2894 | module_i2c_driver(smiapp_i2c_driver); | 2888 | module_i2c_driver(smiapp_i2c_driver); |
2895 | 2889 | ||
2896 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>"); | 2890 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>"); |
2897 | MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver"); | 2891 | MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver"); |
2898 | MODULE_LICENSE("GPL"); | 2892 | MODULE_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 */ |
77 | struct mt9v022_datafmt { | 87 | struct 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 | ||
589 | static const struct regval_list ov2640_yuv422_regs[] = { | 589 | static 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 | |||
600 | static 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 | ||
599 | static const struct regval_list ov2640_rgb565_regs[] = { | 610 | static 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 | |||
618 | static 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 | ||
607 | static enum v4l2_mbus_pixelcode ov2640_codes[] = { | 626 | static 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, | |||
896 | static int ov2640_try_fmt(struct v4l2_subdev *sd, | 929 | static 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 | ||
913 | static __init int vs6624_init(void) | 913 | module_i2c_driver(vs6624_driver); |
914 | { | ||
915 | return i2c_add_driver(&vs6624_driver); | ||
916 | } | ||
917 | |||
918 | static __exit void vs6624_exit(void) | ||
919 | { | ||
920 | i2c_del_driver(&vs6624_driver); | ||
921 | } | ||
922 | |||
923 | module_init(vs6624_init); | ||
924 | module_exit(vs6624_exit); | ||
925 | 914 | ||
926 | MODULE_DESCRIPTION("VS6624 sensor driver"); | 915 | MODULE_DESCRIPTION("VS6624 sensor driver"); |
927 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | 916 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); |