]>
Commit | Line | Data |
---|---|---|
a49d2536 AC |
1 | /* |
2 | * Support for GalaxyCore GC0310 VGA camera sensor. | |
3 | * | |
4 | * Copyright (c) 2013 Intel Corporation. All Rights Reserved. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License version | |
8 | * 2 as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
a49d2536 AC |
15 | */ |
16 | ||
17 | #include <linux/module.h> | |
18 | #include <linux/types.h> | |
19 | #include <linux/kernel.h> | |
20 | #include <linux/mm.h> | |
21 | #include <linux/string.h> | |
22 | #include <linux/errno.h> | |
23 | #include <linux/init.h> | |
24 | #include <linux/kmod.h> | |
25 | #include <linux/device.h> | |
26 | #include <linux/delay.h> | |
27 | #include <linux/slab.h> | |
28 | #include <linux/i2c.h> | |
a49d2536 AC |
29 | #include <linux/moduleparam.h> |
30 | #include <media/v4l2-device.h> | |
31 | #include <linux/io.h> | |
25016567 | 32 | #include "../include/linux/atomisp_gmin_platform.h" |
a49d2536 AC |
33 | |
34 | #include "gc0310.h" | |
35 | ||
36 | /* i2c read/write stuff */ | |
37 | static int gc0310_read_reg(struct i2c_client *client, | |
38 | u16 data_length, u8 reg, u8 *val) | |
39 | { | |
40 | int err; | |
41 | struct i2c_msg msg[2]; | |
42 | unsigned char data[1]; | |
43 | ||
44 | if (!client->adapter) { | |
45 | dev_err(&client->dev, "%s error, no client->adapter\n", | |
46 | __func__); | |
47 | return -ENODEV; | |
48 | } | |
49 | ||
50 | if (data_length != GC0310_8BIT) { | |
51 | dev_err(&client->dev, "%s error, invalid data length\n", | |
52 | __func__); | |
53 | return -EINVAL; | |
54 | } | |
55 | ||
33a2e390 | 56 | memset(msg, 0, sizeof(msg)); |
a49d2536 AC |
57 | |
58 | msg[0].addr = client->addr; | |
59 | msg[0].flags = 0; | |
60 | msg[0].len = I2C_MSG_LENGTH; | |
61 | msg[0].buf = data; | |
62 | ||
63 | /* high byte goes out first */ | |
64 | data[0] = (u8)(reg & 0xff); | |
65 | ||
66 | msg[1].addr = client->addr; | |
67 | msg[1].len = data_length; | |
68 | msg[1].flags = I2C_M_RD; | |
69 | msg[1].buf = data; | |
70 | ||
71 | err = i2c_transfer(client->adapter, msg, 2); | |
72 | if (err != 2) { | |
73 | if (err >= 0) | |
74 | err = -EIO; | |
75 | dev_err(&client->dev, | |
76 | "read from offset 0x%x error %d", reg, err); | |
77 | return err; | |
78 | } | |
79 | ||
80 | *val = 0; | |
81 | /* high byte comes first */ | |
82 | if (data_length == GC0310_8BIT) | |
83 | *val = (u8)data[0]; | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
88 | static int gc0310_i2c_write(struct i2c_client *client, u16 len, u8 *data) | |
89 | { | |
90 | struct i2c_msg msg; | |
91 | const int num_msg = 1; | |
92 | int ret; | |
93 | ||
94 | msg.addr = client->addr; | |
95 | msg.flags = 0; | |
96 | msg.len = len; | |
97 | msg.buf = data; | |
98 | ret = i2c_transfer(client->adapter, &msg, 1); | |
99 | ||
100 | return ret == num_msg ? 0 : -EIO; | |
101 | } | |
102 | ||
103 | static int gc0310_write_reg(struct i2c_client *client, u16 data_length, | |
104 | u8 reg, u8 val) | |
105 | { | |
106 | int ret; | |
107 | unsigned char data[2] = {0}; | |
108 | u8 *wreg = (u8 *)data; | |
109 | const u16 len = data_length + sizeof(u8); /* 8-bit address + data */ | |
110 | ||
111 | if (data_length != GC0310_8BIT) { | |
112 | dev_err(&client->dev, | |
113 | "%s error, invalid data_length\n", __func__); | |
114 | return -EINVAL; | |
115 | } | |
116 | ||
117 | /* high byte goes out first */ | |
118 | *wreg = (u8)(reg & 0xff); | |
119 | ||
a827c1a9 | 120 | if (data_length == GC0310_8BIT) |
a49d2536 | 121 | data[1] = (u8)(val); |
a49d2536 AC |
122 | |
123 | ret = gc0310_i2c_write(client, len, data); | |
124 | if (ret) | |
125 | dev_err(&client->dev, | |
126 | "write error: wrote 0x%x to offset 0x%x error %d", | |
127 | val, reg, ret); | |
128 | ||
129 | return ret; | |
130 | } | |
131 | ||
132 | /* | |
133 | * gc0310_write_reg_array - Initializes a list of GC0310 registers | |
134 | * @client: i2c driver client structure | |
135 | * @reglist: list of registers to be written | |
136 | * | |
137 | * This function initializes a list of registers. When consecutive addresses | |
138 | * are found in a row on the list, this function creates a buffer and sends | |
139 | * consecutive data in a single i2c_transfer(). | |
140 | * | |
141 | * __gc0310_flush_reg_array, __gc0310_buf_reg_array() and | |
142 | * __gc0310_write_reg_is_consecutive() are internal functions to | |
143 | * gc0310_write_reg_array_fast() and should be not used anywhere else. | |
144 | * | |
145 | */ | |
146 | ||
147 | static int __gc0310_flush_reg_array(struct i2c_client *client, | |
148 | struct gc0310_write_ctrl *ctrl) | |
149 | { | |
150 | u16 size; | |
151 | ||
152 | if (ctrl->index == 0) | |
153 | return 0; | |
154 | ||
155 | size = sizeof(u8) + ctrl->index; /* 8-bit address + data */ | |
156 | ctrl->buffer.addr = (u8)(ctrl->buffer.addr); | |
157 | ctrl->index = 0; | |
158 | ||
159 | return gc0310_i2c_write(client, size, (u8 *)&ctrl->buffer); | |
160 | } | |
161 | ||
162 | static int __gc0310_buf_reg_array(struct i2c_client *client, | |
163 | struct gc0310_write_ctrl *ctrl, | |
164 | const struct gc0310_reg *next) | |
165 | { | |
166 | int size; | |
167 | ||
168 | switch (next->type) { | |
169 | case GC0310_8BIT: | |
170 | size = 1; | |
171 | ctrl->buffer.data[ctrl->index] = (u8)next->val; | |
172 | break; | |
173 | default: | |
174 | return -EINVAL; | |
175 | } | |
176 | ||
177 | /* When first item is added, we need to store its starting address */ | |
178 | if (ctrl->index == 0) | |
179 | ctrl->buffer.addr = next->reg; | |
180 | ||
181 | ctrl->index += size; | |
182 | ||
183 | /* | |
184 | * Buffer cannot guarantee free space for u32? Better flush it to avoid | |
185 | * possible lack of memory for next item. | |
186 | */ | |
187 | if (ctrl->index + sizeof(u8) >= GC0310_MAX_WRITE_BUF_SIZE) | |
188 | return __gc0310_flush_reg_array(client, ctrl); | |
189 | ||
190 | return 0; | |
191 | } | |
192 | ||
193 | static int __gc0310_write_reg_is_consecutive(struct i2c_client *client, | |
194 | struct gc0310_write_ctrl *ctrl, | |
195 | const struct gc0310_reg *next) | |
196 | { | |
197 | if (ctrl->index == 0) | |
198 | return 1; | |
199 | ||
200 | return ctrl->buffer.addr + ctrl->index == next->reg; | |
201 | } | |
202 | ||
203 | static int gc0310_write_reg_array(struct i2c_client *client, | |
204 | const struct gc0310_reg *reglist) | |
205 | { | |
206 | const struct gc0310_reg *next = reglist; | |
207 | struct gc0310_write_ctrl ctrl; | |
208 | int err; | |
209 | ||
210 | ctrl.index = 0; | |
211 | for (; next->type != GC0310_TOK_TERM; next++) { | |
212 | switch (next->type & GC0310_TOK_MASK) { | |
213 | case GC0310_TOK_DELAY: | |
214 | err = __gc0310_flush_reg_array(client, &ctrl); | |
215 | if (err) | |
216 | return err; | |
217 | msleep(next->val); | |
218 | break; | |
219 | default: | |
220 | /* | |
221 | * If next address is not consecutive, data needs to be | |
222 | * flushed before proceed. | |
223 | */ | |
224 | if (!__gc0310_write_reg_is_consecutive(client, &ctrl, | |
225 | next)) { | |
226 | err = __gc0310_flush_reg_array(client, &ctrl); | |
227 | if (err) | |
228 | return err; | |
229 | } | |
230 | err = __gc0310_buf_reg_array(client, &ctrl, next); | |
231 | if (err) { | |
232 | dev_err(&client->dev, "%s: write error, aborted\n", | |
233 | __func__); | |
234 | return err; | |
235 | } | |
236 | break; | |
237 | } | |
238 | } | |
239 | ||
240 | return __gc0310_flush_reg_array(client, &ctrl); | |
241 | } | |
242 | static int gc0310_g_focal(struct v4l2_subdev *sd, s32 *val) | |
243 | { | |
244 | *val = (GC0310_FOCAL_LENGTH_NUM << 16) | GC0310_FOCAL_LENGTH_DEM; | |
245 | return 0; | |
246 | } | |
247 | ||
248 | static int gc0310_g_fnumber(struct v4l2_subdev *sd, s32 *val) | |
249 | { | |
250 | /*const f number for imx*/ | |
251 | *val = (GC0310_F_NUMBER_DEFAULT_NUM << 16) | GC0310_F_NUMBER_DEM; | |
252 | return 0; | |
253 | } | |
254 | ||
255 | static int gc0310_g_fnumber_range(struct v4l2_subdev *sd, s32 *val) | |
256 | { | |
257 | *val = (GC0310_F_NUMBER_DEFAULT_NUM << 24) | | |
258 | (GC0310_F_NUMBER_DEM << 16) | | |
259 | (GC0310_F_NUMBER_DEFAULT_NUM << 8) | GC0310_F_NUMBER_DEM; | |
260 | return 0; | |
261 | } | |
262 | ||
263 | static int gc0310_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val) | |
264 | { | |
265 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
266 | ||
267 | *val = gc0310_res[dev->fmt_idx].bin_factor_x; | |
268 | ||
269 | return 0; | |
270 | } | |
271 | ||
272 | static int gc0310_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val) | |
273 | { | |
274 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
275 | ||
276 | *val = gc0310_res[dev->fmt_idx].bin_factor_y; | |
277 | ||
278 | return 0; | |
279 | } | |
280 | ||
281 | static int gc0310_get_intg_factor(struct i2c_client *client, | |
282 | struct camera_mipi_info *info, | |
283 | const struct gc0310_resolution *res) | |
284 | { | |
285 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | |
286 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
287 | struct atomisp_sensor_mode_data *buf = &info->data; | |
288 | u16 val; | |
289 | u8 reg_val; | |
290 | int ret; | |
291 | unsigned int hori_blanking; | |
292 | unsigned int vert_blanking; | |
293 | unsigned int sh_delay; | |
294 | ||
c9d9602f | 295 | if (!info) |
a49d2536 AC |
296 | return -EINVAL; |
297 | ||
298 | /* pixel clock calculattion */ | |
299 | dev->vt_pix_clk_freq_mhz = 14400000; // 16.8MHz | |
300 | buf->vt_pix_clk_freq_mhz = dev->vt_pix_clk_freq_mhz; | |
301 | pr_info("vt_pix_clk_freq_mhz=%d\n", buf->vt_pix_clk_freq_mhz); | |
302 | ||
303 | /* get integration time */ | |
304 | buf->coarse_integration_time_min = GC0310_COARSE_INTG_TIME_MIN; | |
305 | buf->coarse_integration_time_max_margin = | |
306 | GC0310_COARSE_INTG_TIME_MAX_MARGIN; | |
307 | ||
308 | buf->fine_integration_time_min = GC0310_FINE_INTG_TIME_MIN; | |
309 | buf->fine_integration_time_max_margin = | |
310 | GC0310_FINE_INTG_TIME_MAX_MARGIN; | |
311 | ||
312 | buf->fine_integration_time_def = GC0310_FINE_INTG_TIME_MIN; | |
313 | buf->read_mode = res->bin_mode; | |
314 | ||
315 | /* get the cropping and output resolution to ISP for this mode. */ | |
316 | /* Getting crop_horizontal_start */ | |
317 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
318 | GC0310_H_CROP_START_H, ®_val); | |
319 | if (ret) | |
320 | return ret; | |
321 | val = (reg_val & 0xFF) << 8; | |
322 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
323 | GC0310_H_CROP_START_L, ®_val); | |
324 | if (ret) | |
325 | return ret; | |
326 | buf->crop_horizontal_start = val | (reg_val & 0xFF); | |
327 | pr_info("crop_horizontal_start=%d\n", buf->crop_horizontal_start); | |
328 | ||
329 | /* Getting crop_vertical_start */ | |
330 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
331 | GC0310_V_CROP_START_H, ®_val); | |
332 | if (ret) | |
333 | return ret; | |
334 | val = (reg_val & 0xFF) << 8; | |
335 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
336 | GC0310_V_CROP_START_L, ®_val); | |
337 | if (ret) | |
338 | return ret; | |
339 | buf->crop_vertical_start = val | (reg_val & 0xFF); | |
340 | pr_info("crop_vertical_start=%d\n", buf->crop_vertical_start); | |
341 | ||
342 | /* Getting output_width */ | |
343 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
344 | GC0310_H_OUTSIZE_H, ®_val); | |
345 | if (ret) | |
346 | return ret; | |
347 | val = (reg_val & 0xFF) << 8; | |
348 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
349 | GC0310_H_OUTSIZE_L, ®_val); | |
350 | if (ret) | |
351 | return ret; | |
352 | buf->output_width = val | (reg_val & 0xFF); | |
353 | pr_info("output_width=%d\n", buf->output_width); | |
354 | ||
355 | /* Getting output_height */ | |
356 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
357 | GC0310_V_OUTSIZE_H, ®_val); | |
358 | if (ret) | |
359 | return ret; | |
360 | val = (reg_val & 0xFF) << 8; | |
361 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
362 | GC0310_V_OUTSIZE_L, ®_val); | |
363 | if (ret) | |
364 | return ret; | |
365 | buf->output_height = val | (reg_val & 0xFF); | |
366 | pr_info("output_height=%d\n", buf->output_height); | |
367 | ||
368 | buf->crop_horizontal_end = buf->crop_horizontal_start + buf->output_width - 1; | |
369 | buf->crop_vertical_end = buf->crop_vertical_start + buf->output_height - 1; | |
370 | pr_info("crop_horizontal_end=%d\n", buf->crop_horizontal_end); | |
371 | pr_info("crop_vertical_end=%d\n", buf->crop_vertical_end); | |
372 | ||
373 | /* Getting line_length_pck */ | |
374 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
375 | GC0310_H_BLANKING_H, ®_val); | |
376 | if (ret) | |
377 | return ret; | |
378 | val = (reg_val & 0xFF) << 8; | |
379 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
380 | GC0310_H_BLANKING_L, ®_val); | |
381 | if (ret) | |
382 | return ret; | |
383 | hori_blanking = val | (reg_val & 0xFF); | |
384 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
385 | GC0310_SH_DELAY, ®_val); | |
386 | if (ret) | |
387 | return ret; | |
388 | sh_delay = reg_val; | |
389 | buf->line_length_pck = buf->output_width + hori_blanking + sh_delay + 4; | |
390 | pr_info("hori_blanking=%d sh_delay=%d line_length_pck=%d\n", hori_blanking, sh_delay, buf->line_length_pck); | |
391 | ||
392 | /* Getting frame_length_lines */ | |
393 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
394 | GC0310_V_BLANKING_H, ®_val); | |
395 | if (ret) | |
396 | return ret; | |
397 | val = (reg_val & 0xFF) << 8; | |
398 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
399 | GC0310_V_BLANKING_L, ®_val); | |
400 | if (ret) | |
401 | return ret; | |
402 | vert_blanking = val | (reg_val & 0xFF); | |
403 | buf->frame_length_lines = buf->output_height + vert_blanking; | |
404 | pr_info("vert_blanking=%d frame_length_lines=%d\n", vert_blanking, buf->frame_length_lines); | |
405 | ||
406 | buf->binning_factor_x = res->bin_factor_x ? | |
407 | res->bin_factor_x : 1; | |
408 | buf->binning_factor_y = res->bin_factor_y ? | |
409 | res->bin_factor_y : 1; | |
410 | return 0; | |
411 | } | |
412 | ||
413 | static int gc0310_set_gain(struct v4l2_subdev *sd, int gain) | |
414 | ||
415 | { | |
416 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
417 | int ret; | |
418 | u8 again, dgain; | |
419 | ||
420 | if (gain < 0x20) | |
421 | gain = 0x20; | |
422 | if (gain > 0x80) | |
423 | gain = 0x80; | |
424 | ||
425 | if (gain >= 0x20 && gain < 0x40) { | |
426 | again = 0x0; /* sqrt(2) */ | |
427 | dgain = gain; | |
428 | } else { | |
429 | again = 0x2; /* 2 * sqrt(2) */ | |
430 | dgain = gain / 2; | |
431 | } | |
432 | ||
433 | pr_info("gain=0x%x again=0x%x dgain=0x%x\n", gain, again, dgain); | |
434 | ||
435 | /* set analog gain */ | |
436 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
437 | GC0310_AGC_ADJ, again); | |
438 | if (ret) | |
439 | return ret; | |
440 | ||
441 | /* set digital gain */ | |
442 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
443 | GC0310_DGC_ADJ, dgain); | |
444 | if (ret) | |
445 | return ret; | |
446 | ||
447 | return 0; | |
448 | } | |
449 | ||
450 | static int __gc0310_set_exposure(struct v4l2_subdev *sd, int coarse_itg, | |
451 | int gain, int digitgain) | |
452 | ||
453 | { | |
454 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
455 | int ret; | |
456 | ||
457 | pr_info("coarse_itg=%d gain=%d digitgain=%d\n", coarse_itg, gain, digitgain); | |
458 | ||
459 | /* set exposure */ | |
460 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
461 | GC0310_AEC_PK_EXPO_L, | |
462 | coarse_itg & 0xff); | |
463 | if (ret) | |
464 | return ret; | |
465 | ||
466 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
467 | GC0310_AEC_PK_EXPO_H, | |
468 | (coarse_itg >> 8) & 0x0f); | |
469 | if (ret) | |
470 | return ret; | |
471 | ||
472 | ret = gc0310_set_gain(sd, gain); | |
473 | if (ret) | |
474 | return ret; | |
475 | ||
476 | return ret; | |
477 | } | |
478 | ||
479 | static int gc0310_set_exposure(struct v4l2_subdev *sd, int exposure, | |
480 | int gain, int digitgain) | |
481 | { | |
482 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
483 | int ret; | |
484 | ||
485 | mutex_lock(&dev->input_lock); | |
486 | ret = __gc0310_set_exposure(sd, exposure, gain, digitgain); | |
487 | mutex_unlock(&dev->input_lock); | |
488 | ||
489 | return ret; | |
490 | } | |
491 | ||
492 | static long gc0310_s_exposure(struct v4l2_subdev *sd, | |
493 | struct atomisp_exposure *exposure) | |
494 | { | |
495 | int exp = exposure->integration_time[0]; | |
496 | int gain = exposure->gain[0]; | |
497 | int digitgain = exposure->gain[1]; | |
498 | ||
499 | /* we should not accept the invalid value below. */ | |
500 | if (gain == 0) { | |
501 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
502 | v4l2_err(client, "%s: invalid value\n", __func__); | |
503 | return -EINVAL; | |
504 | } | |
505 | ||
506 | return gc0310_set_exposure(sd, exp, gain, digitgain); | |
507 | } | |
508 | ||
509 | /* TO DO */ | |
510 | static int gc0310_v_flip(struct v4l2_subdev *sd, s32 value) | |
511 | { | |
512 | return 0; | |
513 | } | |
514 | ||
515 | /* TO DO */ | |
516 | static int gc0310_h_flip(struct v4l2_subdev *sd, s32 value) | |
517 | { | |
518 | return 0; | |
519 | } | |
520 | ||
521 | static long gc0310_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) | |
522 | { | |
523 | ||
524 | switch (cmd) { | |
525 | case ATOMISP_IOC_S_EXPOSURE: | |
526 | return gc0310_s_exposure(sd, arg); | |
527 | default: | |
528 | return -EINVAL; | |
529 | } | |
530 | return 0; | |
531 | } | |
532 | ||
533 | /* This returns the exposure time being used. This should only be used | |
e17a17a0 VR |
534 | * for filling in EXIF data, not for actual image processing. |
535 | */ | |
a49d2536 AC |
536 | static int gc0310_q_exposure(struct v4l2_subdev *sd, s32 *value) |
537 | { | |
538 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
539 | u8 reg_v; | |
540 | int ret; | |
541 | ||
542 | /* get exposure */ | |
543 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
544 | GC0310_AEC_PK_EXPO_L, | |
545 | ®_v); | |
546 | if (ret) | |
547 | goto err; | |
548 | ||
549 | *value = reg_v; | |
550 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
551 | GC0310_AEC_PK_EXPO_H, | |
552 | ®_v); | |
553 | if (ret) | |
554 | goto err; | |
555 | ||
556 | *value = *value + (reg_v << 8); | |
557 | err: | |
558 | return ret; | |
559 | } | |
560 | ||
561 | static int gc0310_s_ctrl(struct v4l2_ctrl *ctrl) | |
562 | { | |
563 | struct gc0310_device *dev = | |
564 | container_of(ctrl->handler, struct gc0310_device, ctrl_handler); | |
565 | struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); | |
566 | int ret = 0; | |
567 | ||
568 | switch (ctrl->id) { | |
569 | case V4L2_CID_VFLIP: | |
570 | dev_dbg(&client->dev, "%s: CID_VFLIP:%d.\n", | |
571 | __func__, ctrl->val); | |
572 | ret = gc0310_v_flip(&dev->sd, ctrl->val); | |
573 | break; | |
574 | case V4L2_CID_HFLIP: | |
575 | dev_dbg(&client->dev, "%s: CID_HFLIP:%d.\n", | |
576 | __func__, ctrl->val); | |
577 | ret = gc0310_h_flip(&dev->sd, ctrl->val); | |
578 | break; | |
579 | default: | |
580 | ret = -EINVAL; | |
581 | } | |
582 | return ret; | |
583 | } | |
584 | ||
585 | static int gc0310_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |
586 | { | |
587 | struct gc0310_device *dev = | |
588 | container_of(ctrl->handler, struct gc0310_device, ctrl_handler); | |
589 | int ret = 0; | |
590 | ||
591 | switch (ctrl->id) { | |
592 | case V4L2_CID_EXPOSURE_ABSOLUTE: | |
593 | ret = gc0310_q_exposure(&dev->sd, &ctrl->val); | |
594 | break; | |
595 | case V4L2_CID_FOCAL_ABSOLUTE: | |
596 | ret = gc0310_g_focal(&dev->sd, &ctrl->val); | |
597 | break; | |
598 | case V4L2_CID_FNUMBER_ABSOLUTE: | |
599 | ret = gc0310_g_fnumber(&dev->sd, &ctrl->val); | |
600 | break; | |
601 | case V4L2_CID_FNUMBER_RANGE: | |
602 | ret = gc0310_g_fnumber_range(&dev->sd, &ctrl->val); | |
603 | break; | |
604 | case V4L2_CID_BIN_FACTOR_HORZ: | |
605 | ret = gc0310_g_bin_factor_x(&dev->sd, &ctrl->val); | |
606 | break; | |
607 | case V4L2_CID_BIN_FACTOR_VERT: | |
608 | ret = gc0310_g_bin_factor_y(&dev->sd, &ctrl->val); | |
609 | break; | |
610 | default: | |
611 | ret = -EINVAL; | |
612 | } | |
613 | ||
614 | return ret; | |
615 | } | |
616 | ||
617 | static const struct v4l2_ctrl_ops ctrl_ops = { | |
618 | .s_ctrl = gc0310_s_ctrl, | |
619 | .g_volatile_ctrl = gc0310_g_volatile_ctrl | |
620 | }; | |
621 | ||
622 | struct v4l2_ctrl_config gc0310_controls[] = { | |
623 | { | |
624 | .ops = &ctrl_ops, | |
625 | .id = V4L2_CID_EXPOSURE_ABSOLUTE, | |
626 | .type = V4L2_CTRL_TYPE_INTEGER, | |
627 | .name = "exposure", | |
628 | .min = 0x0, | |
629 | .max = 0xffff, | |
630 | .step = 0x01, | |
631 | .def = 0x00, | |
632 | .flags = 0, | |
633 | }, | |
634 | { | |
635 | .ops = &ctrl_ops, | |
636 | .id = V4L2_CID_VFLIP, | |
637 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
638 | .name = "Flip", | |
639 | .min = 0, | |
640 | .max = 1, | |
641 | .step = 1, | |
642 | .def = 0, | |
643 | }, | |
644 | { | |
645 | .ops = &ctrl_ops, | |
646 | .id = V4L2_CID_HFLIP, | |
647 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
648 | .name = "Mirror", | |
649 | .min = 0, | |
650 | .max = 1, | |
651 | .step = 1, | |
652 | .def = 0, | |
653 | }, | |
654 | { | |
655 | .ops = &ctrl_ops, | |
656 | .id = V4L2_CID_FOCAL_ABSOLUTE, | |
657 | .type = V4L2_CTRL_TYPE_INTEGER, | |
658 | .name = "focal length", | |
659 | .min = GC0310_FOCAL_LENGTH_DEFAULT, | |
660 | .max = GC0310_FOCAL_LENGTH_DEFAULT, | |
661 | .step = 0x01, | |
662 | .def = GC0310_FOCAL_LENGTH_DEFAULT, | |
663 | .flags = 0, | |
664 | }, | |
665 | { | |
666 | .ops = &ctrl_ops, | |
667 | .id = V4L2_CID_FNUMBER_ABSOLUTE, | |
668 | .type = V4L2_CTRL_TYPE_INTEGER, | |
669 | .name = "f-number", | |
670 | .min = GC0310_F_NUMBER_DEFAULT, | |
671 | .max = GC0310_F_NUMBER_DEFAULT, | |
672 | .step = 0x01, | |
673 | .def = GC0310_F_NUMBER_DEFAULT, | |
674 | .flags = 0, | |
675 | }, | |
676 | { | |
677 | .ops = &ctrl_ops, | |
678 | .id = V4L2_CID_FNUMBER_RANGE, | |
679 | .type = V4L2_CTRL_TYPE_INTEGER, | |
680 | .name = "f-number range", | |
681 | .min = GC0310_F_NUMBER_RANGE, | |
682 | .max = GC0310_F_NUMBER_RANGE, | |
683 | .step = 0x01, | |
684 | .def = GC0310_F_NUMBER_RANGE, | |
685 | .flags = 0, | |
686 | }, | |
687 | { | |
688 | .ops = &ctrl_ops, | |
689 | .id = V4L2_CID_BIN_FACTOR_HORZ, | |
690 | .type = V4L2_CTRL_TYPE_INTEGER, | |
691 | .name = "horizontal binning factor", | |
692 | .min = 0, | |
693 | .max = GC0310_BIN_FACTOR_MAX, | |
694 | .step = 1, | |
695 | .def = 0, | |
696 | .flags = 0, | |
697 | }, | |
698 | { | |
699 | .ops = &ctrl_ops, | |
700 | .id = V4L2_CID_BIN_FACTOR_VERT, | |
701 | .type = V4L2_CTRL_TYPE_INTEGER, | |
702 | .name = "vertical binning factor", | |
703 | .min = 0, | |
704 | .max = GC0310_BIN_FACTOR_MAX, | |
705 | .step = 1, | |
706 | .def = 0, | |
707 | .flags = 0, | |
708 | }, | |
709 | }; | |
710 | ||
711 | static int gc0310_init(struct v4l2_subdev *sd) | |
712 | { | |
713 | int ret; | |
714 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
715 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
716 | ||
717 | pr_info("%s S\n", __func__); | |
718 | mutex_lock(&dev->input_lock); | |
719 | ||
720 | /* set inital registers */ | |
721 | ret = gc0310_write_reg_array(client, gc0310_reset_register); | |
722 | ||
723 | /* restore settings */ | |
724 | gc0310_res = gc0310_res_preview; | |
725 | N_RES = N_RES_PREVIEW; | |
726 | ||
727 | mutex_unlock(&dev->input_lock); | |
728 | ||
729 | pr_info("%s E\n", __func__); | |
730 | return 0; | |
731 | } | |
732 | ||
733 | static int power_ctrl(struct v4l2_subdev *sd, bool flag) | |
734 | { | |
735 | int ret = 0; | |
736 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
737 | if (!dev || !dev->platform_data) | |
738 | return -ENODEV; | |
739 | ||
a49d2536 AC |
740 | if (flag) { |
741 | /* The upstream module driver (written to Crystal | |
742 | * Cove) had this logic to pulse the rails low first. | |
743 | * This appears to break things on the MRD7 with the | |
744 | * X-Powers PMIC... | |
745 | * | |
746 | * ret = dev->platform_data->v1p8_ctrl(sd, 0); | |
747 | * ret |= dev->platform_data->v2p8_ctrl(sd, 0); | |
748 | * mdelay(50); | |
749 | */ | |
750 | ret |= dev->platform_data->v1p8_ctrl(sd, 1); | |
751 | ret |= dev->platform_data->v2p8_ctrl(sd, 1); | |
752 | usleep_range(10000, 15000); | |
753 | } | |
754 | ||
755 | if (!flag || ret) { | |
756 | ret |= dev->platform_data->v1p8_ctrl(sd, 0); | |
757 | ret |= dev->platform_data->v2p8_ctrl(sd, 0); | |
758 | } | |
759 | return ret; | |
760 | } | |
761 | ||
762 | static int gpio_ctrl(struct v4l2_subdev *sd, bool flag) | |
763 | { | |
764 | int ret; | |
765 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
766 | ||
767 | if (!dev || !dev->platform_data) | |
768 | return -ENODEV; | |
769 | ||
a49d2536 AC |
770 | /* GPIO0 == "reset" (active low), GPIO1 == "power down" */ |
771 | if (flag) { | |
772 | /* Pulse reset, then release power down */ | |
773 | ret = dev->platform_data->gpio0_ctrl(sd, 0); | |
774 | usleep_range(5000, 10000); | |
775 | ret |= dev->platform_data->gpio0_ctrl(sd, 1); | |
776 | usleep_range(10000, 15000); | |
777 | ret |= dev->platform_data->gpio1_ctrl(sd, 0); | |
778 | usleep_range(10000, 15000); | |
779 | } else { | |
780 | ret = dev->platform_data->gpio1_ctrl(sd, 1); | |
781 | ret |= dev->platform_data->gpio0_ctrl(sd, 0); | |
782 | } | |
783 | return ret; | |
784 | } | |
785 | ||
786 | ||
787 | static int power_down(struct v4l2_subdev *sd); | |
788 | ||
789 | static int power_up(struct v4l2_subdev *sd) | |
790 | { | |
791 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
792 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
793 | int ret; | |
794 | ||
795 | pr_info("%s S\n", __func__); | |
c9d9602f | 796 | if (!dev->platform_data) { |
a49d2536 AC |
797 | dev_err(&client->dev, |
798 | "no camera_sensor_platform_data"); | |
799 | return -ENODEV; | |
800 | } | |
801 | ||
802 | /* power control */ | |
803 | ret = power_ctrl(sd, 1); | |
804 | if (ret) | |
805 | goto fail_power; | |
806 | ||
807 | /* flis clock control */ | |
808 | ret = dev->platform_data->flisclk_ctrl(sd, 1); | |
809 | if (ret) | |
810 | goto fail_clk; | |
811 | ||
812 | /* gpio ctrl */ | |
813 | ret = gpio_ctrl(sd, 1); | |
814 | if (ret) { | |
815 | ret = gpio_ctrl(sd, 1); | |
816 | if (ret) | |
817 | goto fail_gpio; | |
818 | } | |
819 | ||
820 | msleep(100); | |
821 | ||
822 | pr_info("%s E\n", __func__); | |
823 | return 0; | |
824 | ||
825 | fail_gpio: | |
826 | dev->platform_data->flisclk_ctrl(sd, 0); | |
827 | fail_clk: | |
828 | power_ctrl(sd, 0); | |
829 | fail_power: | |
830 | dev_err(&client->dev, "sensor power-up failed\n"); | |
831 | ||
832 | return ret; | |
833 | } | |
834 | ||
835 | static int power_down(struct v4l2_subdev *sd) | |
836 | { | |
837 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
838 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
839 | int ret = 0; | |
840 | ||
c9d9602f | 841 | if (!dev->platform_data) { |
a49d2536 AC |
842 | dev_err(&client->dev, |
843 | "no camera_sensor_platform_data"); | |
844 | return -ENODEV; | |
845 | } | |
846 | ||
847 | /* gpio ctrl */ | |
848 | ret = gpio_ctrl(sd, 0); | |
849 | if (ret) { | |
850 | ret = gpio_ctrl(sd, 0); | |
851 | if (ret) | |
852 | dev_err(&client->dev, "gpio failed 2\n"); | |
853 | } | |
854 | ||
855 | ret = dev->platform_data->flisclk_ctrl(sd, 0); | |
856 | if (ret) | |
857 | dev_err(&client->dev, "flisclk failed\n"); | |
858 | ||
859 | /* power control */ | |
860 | ret = power_ctrl(sd, 0); | |
861 | if (ret) | |
862 | dev_err(&client->dev, "vprog failed.\n"); | |
863 | ||
864 | return ret; | |
865 | } | |
866 | ||
867 | static int gc0310_s_power(struct v4l2_subdev *sd, int on) | |
868 | { | |
869 | int ret; | |
870 | if (on == 0) | |
871 | return power_down(sd); | |
872 | else { | |
873 | ret = power_up(sd); | |
874 | if (!ret) | |
875 | return gc0310_init(sd); | |
876 | } | |
877 | return ret; | |
878 | } | |
879 | ||
880 | /* | |
881 | * distance - calculate the distance | |
882 | * @res: resolution | |
883 | * @w: width | |
884 | * @h: height | |
885 | * | |
886 | * Get the gap between resolution and w/h. | |
887 | * res->width/height smaller than w/h wouldn't be considered. | |
888 | * Returns the value of gap or -1 if fail. | |
889 | */ | |
890 | #define LARGEST_ALLOWED_RATIO_MISMATCH 800 | |
891 | static int distance(struct gc0310_resolution *res, u32 w, u32 h) | |
892 | { | |
56b41836 | 893 | unsigned int w_ratio = (res->width << 13) / w; |
a49d2536 AC |
894 | unsigned int h_ratio; |
895 | int match; | |
896 | ||
897 | if (h == 0) | |
898 | return -1; | |
6c492211 | 899 | h_ratio = (res->height << 13) / h; |
a49d2536 AC |
900 | if (h_ratio == 0) |
901 | return -1; | |
902 | match = abs(((w_ratio << 13) / h_ratio) - ((int)8192)); | |
903 | ||
904 | if ((w_ratio < (int)8192) || (h_ratio < (int)8192) || | |
905 | (match > LARGEST_ALLOWED_RATIO_MISMATCH)) | |
906 | return -1; | |
907 | ||
908 | return w_ratio + h_ratio; | |
909 | } | |
910 | ||
911 | /* Return the nearest higher resolution index */ | |
912 | static int nearest_resolution_index(int w, int h) | |
913 | { | |
914 | int i; | |
915 | int idx = -1; | |
916 | int dist; | |
917 | int min_dist = INT_MAX; | |
918 | struct gc0310_resolution *tmp_res = NULL; | |
919 | ||
920 | for (i = 0; i < N_RES; i++) { | |
921 | tmp_res = &gc0310_res[i]; | |
922 | dist = distance(tmp_res, w, h); | |
923 | if (dist == -1) | |
924 | continue; | |
925 | if (dist < min_dist) { | |
926 | min_dist = dist; | |
927 | idx = i; | |
928 | } | |
929 | } | |
930 | ||
931 | return idx; | |
932 | } | |
933 | ||
934 | static int get_resolution_index(int w, int h) | |
935 | { | |
936 | int i; | |
937 | ||
938 | for (i = 0; i < N_RES; i++) { | |
939 | if (w != gc0310_res[i].width) | |
940 | continue; | |
941 | if (h != gc0310_res[i].height) | |
942 | continue; | |
943 | ||
944 | return i; | |
945 | } | |
946 | ||
947 | return -1; | |
948 | } | |
949 | ||
950 | ||
951 | /* TODO: remove it. */ | |
952 | static int startup(struct v4l2_subdev *sd) | |
953 | { | |
954 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
955 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
956 | int ret = 0; | |
957 | ||
958 | pr_info("%s S\n", __func__); | |
959 | ||
960 | ret = gc0310_write_reg_array(client, gc0310_res[dev->fmt_idx].regs); | |
961 | if (ret) { | |
962 | dev_err(&client->dev, "gc0310 write register err.\n"); | |
963 | return ret; | |
964 | } | |
965 | ||
966 | pr_info("%s E\n", __func__); | |
967 | return ret; | |
968 | } | |
969 | ||
970 | static int gc0310_set_fmt(struct v4l2_subdev *sd, | |
971 | struct v4l2_subdev_pad_config *cfg, | |
972 | struct v4l2_subdev_format *format) | |
973 | { | |
974 | struct v4l2_mbus_framefmt *fmt = &format->format; | |
975 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
976 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
977 | struct camera_mipi_info *gc0310_info = NULL; | |
978 | int ret = 0; | |
979 | int idx = 0; | |
980 | pr_info("%s S\n", __func__); | |
981 | ||
982 | if (format->pad) | |
983 | return -EINVAL; | |
984 | ||
985 | if (!fmt) | |
986 | return -EINVAL; | |
987 | ||
988 | gc0310_info = v4l2_get_subdev_hostdata(sd); | |
c9d9602f | 989 | if (!gc0310_info) |
a49d2536 AC |
990 | return -EINVAL; |
991 | ||
992 | mutex_lock(&dev->input_lock); | |
993 | ||
994 | idx = nearest_resolution_index(fmt->width, fmt->height); | |
995 | if (idx == -1) { | |
996 | /* return the largest resolution */ | |
997 | fmt->width = gc0310_res[N_RES - 1].width; | |
998 | fmt->height = gc0310_res[N_RES - 1].height; | |
999 | } else { | |
1000 | fmt->width = gc0310_res[idx].width; | |
1001 | fmt->height = gc0310_res[idx].height; | |
1002 | } | |
1003 | fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8; | |
1004 | ||
1005 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) { | |
1006 | cfg->try_fmt = *fmt; | |
1007 | mutex_unlock(&dev->input_lock); | |
1008 | return 0; | |
1009 | } | |
1010 | ||
1011 | dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); | |
1012 | if (dev->fmt_idx == -1) { | |
1013 | dev_err(&client->dev, "get resolution fail\n"); | |
1014 | mutex_unlock(&dev->input_lock); | |
1015 | return -EINVAL; | |
1016 | } | |
1017 | ||
1018 | printk("%s: before gc0310_write_reg_array %s\n", __FUNCTION__, | |
1019 | gc0310_res[dev->fmt_idx].desc); | |
1020 | ret = startup(sd); | |
1021 | if (ret) { | |
1022 | dev_err(&client->dev, "gc0310 startup err\n"); | |
1023 | goto err; | |
1024 | } | |
1025 | ||
1026 | ret = gc0310_get_intg_factor(client, gc0310_info, | |
1027 | &gc0310_res[dev->fmt_idx]); | |
1028 | if (ret) { | |
1029 | dev_err(&client->dev, "failed to get integration_factor\n"); | |
1030 | goto err; | |
1031 | } | |
1032 | ||
1033 | pr_info("%s E\n", __func__); | |
1034 | err: | |
1035 | mutex_unlock(&dev->input_lock); | |
1036 | return ret; | |
1037 | } | |
1038 | ||
1039 | static int gc0310_get_fmt(struct v4l2_subdev *sd, | |
1040 | struct v4l2_subdev_pad_config *cfg, | |
1041 | struct v4l2_subdev_format *format) | |
1042 | { | |
1043 | struct v4l2_mbus_framefmt *fmt = &format->format; | |
1044 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1045 | ||
1046 | if (format->pad) | |
1047 | return -EINVAL; | |
1048 | ||
1049 | if (!fmt) | |
1050 | return -EINVAL; | |
1051 | ||
1052 | fmt->width = gc0310_res[dev->fmt_idx].width; | |
1053 | fmt->height = gc0310_res[dev->fmt_idx].height; | |
1054 | fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8; | |
1055 | ||
1056 | return 0; | |
1057 | } | |
1058 | ||
1059 | static int gc0310_detect(struct i2c_client *client) | |
1060 | { | |
1061 | struct i2c_adapter *adapter = client->adapter; | |
1062 | u8 high, low; | |
1063 | int ret; | |
1064 | u16 id; | |
1065 | ||
1066 | pr_info("%s S\n", __func__); | |
1067 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | |
1068 | return -ENODEV; | |
1069 | ||
1070 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
1071 | GC0310_SC_CMMN_CHIP_ID_H, &high); | |
1072 | if (ret) { | |
1073 | dev_err(&client->dev, "read sensor_id_high failed\n"); | |
1074 | return -ENODEV; | |
1075 | } | |
1076 | ret = gc0310_read_reg(client, GC0310_8BIT, | |
1077 | GC0310_SC_CMMN_CHIP_ID_L, &low); | |
1078 | if (ret) { | |
1079 | dev_err(&client->dev, "read sensor_id_low failed\n"); | |
1080 | return -ENODEV; | |
1081 | } | |
1082 | id = ((((u16) high) << 8) | (u16) low); | |
1083 | pr_info("sensor ID = 0x%x\n", id); | |
1084 | ||
1085 | if (id != GC0310_ID) { | |
1086 | dev_err(&client->dev, "sensor ID error, read id = 0x%x, target id = 0x%x\n", id, GC0310_ID); | |
1087 | return -ENODEV; | |
1088 | } | |
1089 | ||
1090 | dev_dbg(&client->dev, "detect gc0310 success\n"); | |
1091 | ||
1092 | pr_info("%s E\n", __func__); | |
1093 | ||
1094 | return 0; | |
1095 | } | |
1096 | ||
1097 | static int gc0310_s_stream(struct v4l2_subdev *sd, int enable) | |
1098 | { | |
1099 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1100 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
1101 | int ret; | |
1102 | ||
1103 | pr_info("%s S enable=%d\n", __func__, enable); | |
1104 | mutex_lock(&dev->input_lock); | |
1105 | ||
1106 | if (enable) { | |
1107 | /* enable per frame MIPI and sensor ctrl reset */ | |
1108 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
1109 | 0xFE, 0x30); | |
1110 | if (ret) { | |
1111 | mutex_unlock(&dev->input_lock); | |
1112 | return ret; | |
1113 | } | |
1114 | } | |
1115 | ||
1116 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
1117 | GC0310_RESET_RELATED, GC0310_REGISTER_PAGE_3); | |
1118 | if (ret) { | |
1119 | mutex_unlock(&dev->input_lock); | |
1120 | return ret; | |
1121 | } | |
1122 | ||
1123 | ret = gc0310_write_reg(client, GC0310_8BIT, GC0310_SW_STREAM, | |
1124 | enable ? GC0310_START_STREAMING : | |
1125 | GC0310_STOP_STREAMING); | |
1126 | if (ret) { | |
1127 | mutex_unlock(&dev->input_lock); | |
1128 | return ret; | |
1129 | } | |
1130 | ||
1131 | ret = gc0310_write_reg(client, GC0310_8BIT, | |
1132 | GC0310_RESET_RELATED, GC0310_REGISTER_PAGE_0); | |
1133 | if (ret) { | |
1134 | mutex_unlock(&dev->input_lock); | |
1135 | return ret; | |
1136 | } | |
1137 | ||
1138 | mutex_unlock(&dev->input_lock); | |
1139 | pr_info("%s E\n", __func__); | |
1140 | return ret; | |
1141 | } | |
1142 | ||
1143 | ||
1144 | static int gc0310_s_config(struct v4l2_subdev *sd, | |
1145 | int irq, void *platform_data) | |
1146 | { | |
1147 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1148 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
1149 | int ret = 0; | |
1150 | ||
1151 | pr_info("%s S\n", __func__); | |
c9d9602f | 1152 | if (!platform_data) |
a49d2536 AC |
1153 | return -ENODEV; |
1154 | ||
1155 | dev->platform_data = | |
1156 | (struct camera_sensor_platform_data *)platform_data; | |
1157 | ||
1158 | mutex_lock(&dev->input_lock); | |
1159 | if (dev->platform_data->platform_init) { | |
1160 | ret = dev->platform_data->platform_init(client); | |
1161 | if (ret) { | |
1162 | dev_err(&client->dev, "platform init err\n"); | |
1163 | goto platform_init_failed; | |
1164 | } | |
1165 | } | |
1166 | /* power off the module, then power on it in future | |
1167 | * as first power on by board may not fulfill the | |
1168 | * power on sequqence needed by the module | |
1169 | */ | |
1170 | ret = power_down(sd); | |
1171 | if (ret) { | |
1172 | dev_err(&client->dev, "gc0310 power-off err.\n"); | |
1173 | goto fail_power_off; | |
1174 | } | |
1175 | ||
1176 | ret = power_up(sd); | |
1177 | if (ret) { | |
1178 | dev_err(&client->dev, "gc0310 power-up err.\n"); | |
1179 | goto fail_power_on; | |
1180 | } | |
1181 | ||
1182 | ret = dev->platform_data->csi_cfg(sd, 1); | |
1183 | if (ret) | |
1184 | goto fail_csi_cfg; | |
1185 | ||
1186 | /* config & detect sensor */ | |
1187 | ret = gc0310_detect(client); | |
1188 | if (ret) { | |
1189 | dev_err(&client->dev, "gc0310_detect err s_config.\n"); | |
1190 | goto fail_csi_cfg; | |
1191 | } | |
1192 | ||
1193 | /* turn off sensor, after probed */ | |
1194 | ret = power_down(sd); | |
1195 | if (ret) { | |
1196 | dev_err(&client->dev, "gc0310 power-off err.\n"); | |
1197 | goto fail_csi_cfg; | |
1198 | } | |
1199 | mutex_unlock(&dev->input_lock); | |
1200 | ||
1201 | pr_info("%s E\n", __func__); | |
1202 | return 0; | |
1203 | ||
1204 | fail_csi_cfg: | |
1205 | dev->platform_data->csi_cfg(sd, 0); | |
1206 | fail_power_on: | |
1207 | power_down(sd); | |
1208 | dev_err(&client->dev, "sensor power-gating failed\n"); | |
1209 | fail_power_off: | |
1210 | if (dev->platform_data->platform_deinit) | |
1211 | dev->platform_data->platform_deinit(); | |
1212 | platform_init_failed: | |
1213 | mutex_unlock(&dev->input_lock); | |
1214 | return ret; | |
1215 | } | |
1216 | ||
1217 | static int gc0310_g_parm(struct v4l2_subdev *sd, | |
1218 | struct v4l2_streamparm *param) | |
1219 | { | |
1220 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1221 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
1222 | ||
1223 | if (!param) | |
1224 | return -EINVAL; | |
1225 | ||
1226 | if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | |
1227 | dev_err(&client->dev, "unsupported buffer type.\n"); | |
1228 | return -EINVAL; | |
1229 | } | |
1230 | ||
1231 | memset(param, 0, sizeof(*param)); | |
1232 | param->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
1233 | ||
1234 | if (dev->fmt_idx >= 0 && dev->fmt_idx < N_RES) { | |
1235 | param->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | |
1236 | param->parm.capture.timeperframe.numerator = 1; | |
1237 | param->parm.capture.capturemode = dev->run_mode; | |
1238 | param->parm.capture.timeperframe.denominator = | |
1239 | gc0310_res[dev->fmt_idx].fps; | |
1240 | } | |
1241 | return 0; | |
1242 | } | |
1243 | ||
1244 | static int gc0310_s_parm(struct v4l2_subdev *sd, | |
1245 | struct v4l2_streamparm *param) | |
1246 | { | |
1247 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1248 | dev->run_mode = param->parm.capture.capturemode; | |
1249 | ||
1250 | mutex_lock(&dev->input_lock); | |
1251 | switch (dev->run_mode) { | |
1252 | case CI_MODE_VIDEO: | |
1253 | gc0310_res = gc0310_res_video; | |
1254 | N_RES = N_RES_VIDEO; | |
1255 | break; | |
1256 | case CI_MODE_STILL_CAPTURE: | |
1257 | gc0310_res = gc0310_res_still; | |
1258 | N_RES = N_RES_STILL; | |
1259 | break; | |
1260 | default: | |
1261 | gc0310_res = gc0310_res_preview; | |
1262 | N_RES = N_RES_PREVIEW; | |
1263 | } | |
1264 | mutex_unlock(&dev->input_lock); | |
1265 | return 0; | |
1266 | } | |
1267 | ||
1268 | static int gc0310_g_frame_interval(struct v4l2_subdev *sd, | |
1269 | struct v4l2_subdev_frame_interval *interval) | |
1270 | { | |
1271 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1272 | ||
1273 | interval->interval.numerator = 1; | |
1274 | interval->interval.denominator = gc0310_res[dev->fmt_idx].fps; | |
1275 | ||
1276 | return 0; | |
1277 | } | |
1278 | ||
1279 | static int gc0310_enum_mbus_code(struct v4l2_subdev *sd, | |
1280 | struct v4l2_subdev_pad_config *cfg, | |
1281 | struct v4l2_subdev_mbus_code_enum *code) | |
1282 | { | |
1283 | if (code->index >= MAX_FMTS) | |
1284 | return -EINVAL; | |
1285 | ||
1286 | code->code = MEDIA_BUS_FMT_SGRBG8_1X8; | |
1287 | return 0; | |
1288 | } | |
1289 | ||
1290 | static int gc0310_enum_frame_size(struct v4l2_subdev *sd, | |
1291 | struct v4l2_subdev_pad_config *cfg, | |
1292 | struct v4l2_subdev_frame_size_enum *fse) | |
1293 | { | |
1294 | int index = fse->index; | |
1295 | ||
1296 | if (index >= N_RES) | |
1297 | return -EINVAL; | |
1298 | ||
1299 | fse->min_width = gc0310_res[index].width; | |
1300 | fse->min_height = gc0310_res[index].height; | |
1301 | fse->max_width = gc0310_res[index].width; | |
1302 | fse->max_height = gc0310_res[index].height; | |
1303 | ||
1304 | return 0; | |
1305 | ||
1306 | } | |
1307 | ||
1308 | ||
1309 | static int gc0310_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) | |
1310 | { | |
1311 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1312 | ||
1313 | mutex_lock(&dev->input_lock); | |
1314 | *frames = gc0310_res[dev->fmt_idx].skip_frames; | |
1315 | mutex_unlock(&dev->input_lock); | |
1316 | ||
1317 | return 0; | |
1318 | } | |
1319 | ||
1320 | static const struct v4l2_subdev_sensor_ops gc0310_sensor_ops = { | |
1321 | .g_skip_frames = gc0310_g_skip_frames, | |
1322 | }; | |
1323 | ||
1324 | static const struct v4l2_subdev_video_ops gc0310_video_ops = { | |
1325 | .s_stream = gc0310_s_stream, | |
1326 | .g_parm = gc0310_g_parm, | |
1327 | .s_parm = gc0310_s_parm, | |
1328 | .g_frame_interval = gc0310_g_frame_interval, | |
1329 | }; | |
1330 | ||
1331 | static const struct v4l2_subdev_core_ops gc0310_core_ops = { | |
1332 | .s_power = gc0310_s_power, | |
1333 | .ioctl = gc0310_ioctl, | |
1334 | }; | |
1335 | ||
1336 | static const struct v4l2_subdev_pad_ops gc0310_pad_ops = { | |
1337 | .enum_mbus_code = gc0310_enum_mbus_code, | |
1338 | .enum_frame_size = gc0310_enum_frame_size, | |
1339 | .get_fmt = gc0310_get_fmt, | |
1340 | .set_fmt = gc0310_set_fmt, | |
1341 | }; | |
1342 | ||
1343 | static const struct v4l2_subdev_ops gc0310_ops = { | |
1344 | .core = &gc0310_core_ops, | |
1345 | .video = &gc0310_video_ops, | |
1346 | .pad = &gc0310_pad_ops, | |
1347 | .sensor = &gc0310_sensor_ops, | |
1348 | }; | |
1349 | ||
1350 | static int gc0310_remove(struct i2c_client *client) | |
1351 | { | |
1352 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | |
1353 | struct gc0310_device *dev = to_gc0310_sensor(sd); | |
1354 | dev_dbg(&client->dev, "gc0310_remove...\n"); | |
1355 | ||
1356 | if (dev->platform_data->platform_deinit) | |
1357 | dev->platform_data->platform_deinit(); | |
1358 | ||
1359 | dev->platform_data->csi_cfg(sd, 0); | |
1360 | ||
1361 | v4l2_device_unregister_subdev(sd); | |
1362 | media_entity_cleanup(&dev->sd.entity); | |
1363 | v4l2_ctrl_handler_free(&dev->ctrl_handler); | |
1364 | kfree(dev); | |
1365 | ||
1366 | return 0; | |
1367 | } | |
1368 | ||
e19c9205 | 1369 | static int gc0310_probe(struct i2c_client *client) |
a49d2536 AC |
1370 | { |
1371 | struct gc0310_device *dev; | |
1372 | int ret; | |
1373 | void *pdata; | |
1374 | unsigned int i; | |
1375 | ||
1376 | pr_info("%s S\n", __func__); | |
1377 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | |
309167b9 | 1378 | if (!dev) |
a49d2536 | 1379 | return -ENOMEM; |
a49d2536 AC |
1380 | |
1381 | mutex_init(&dev->input_lock); | |
1382 | ||
1383 | dev->fmt_idx = 0; | |
1384 | v4l2_i2c_subdev_init(&(dev->sd), client, &gc0310_ops); | |
1385 | ||
1386 | if (ACPI_COMPANION(&client->dev)) | |
1387 | pdata = gmin_camera_platform_data(&dev->sd, | |
1388 | ATOMISP_INPUT_FORMAT_RAW_8, | |
1389 | atomisp_bayer_order_grbg); | |
1390 | else | |
1391 | pdata = client->dev.platform_data; | |
1392 | ||
1393 | if (!pdata) { | |
1394 | ret = -EINVAL; | |
1395 | goto out_free; | |
1396 | } | |
1397 | ||
1398 | ret = gc0310_s_config(&dev->sd, client->irq, pdata); | |
1399 | if (ret) | |
1400 | goto out_free; | |
1401 | ||
1402 | ret = atomisp_register_i2c_module(&dev->sd, pdata, RAW_CAMERA); | |
1403 | if (ret) | |
1404 | goto out_free; | |
1405 | ||
1406 | dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | |
1407 | dev->pad.flags = MEDIA_PAD_FL_SOURCE; | |
1408 | dev->format.code = MEDIA_BUS_FMT_SGRBG8_1X8; | |
1409 | dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; | |
1410 | ret = | |
1411 | v4l2_ctrl_handler_init(&dev->ctrl_handler, | |
1412 | ARRAY_SIZE(gc0310_controls)); | |
1413 | if (ret) { | |
1414 | gc0310_remove(client); | |
1415 | return ret; | |
1416 | } | |
1417 | ||
1418 | for (i = 0; i < ARRAY_SIZE(gc0310_controls); i++) | |
1419 | v4l2_ctrl_new_custom(&dev->ctrl_handler, &gc0310_controls[i], | |
1420 | NULL); | |
1421 | ||
1422 | if (dev->ctrl_handler.error) { | |
1423 | gc0310_remove(client); | |
1424 | return dev->ctrl_handler.error; | |
1425 | } | |
1426 | ||
1427 | /* Use same lock for controls as for everything else. */ | |
1428 | dev->ctrl_handler.lock = &dev->input_lock; | |
1429 | dev->sd.ctrl_handler = &dev->ctrl_handler; | |
1430 | ||
1431 | ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad); | |
1432 | if (ret) | |
1433 | gc0310_remove(client); | |
1434 | ||
1435 | pr_info("%s E\n", __func__); | |
1436 | return ret; | |
1437 | out_free: | |
1438 | v4l2_device_unregister_subdev(&dev->sd); | |
1439 | kfree(dev); | |
1440 | return ret; | |
1441 | } | |
1442 | ||
83371ef2 | 1443 | static const struct acpi_device_id gc0310_acpi_match[] = { |
a49d2536 | 1444 | {"XXGC0310"}, |
6706e900 | 1445 | {"INT0310"}, |
a49d2536 AC |
1446 | {}, |
1447 | }; | |
a49d2536 AC |
1448 | MODULE_DEVICE_TABLE(acpi, gc0310_acpi_match); |
1449 | ||
a49d2536 AC |
1450 | static struct i2c_driver gc0310_driver = { |
1451 | .driver = { | |
e19c9205 AS |
1452 | .name = "gc0310", |
1453 | .acpi_match_table = gc0310_acpi_match, | |
a49d2536 | 1454 | }, |
e19c9205 | 1455 | .probe_new = gc0310_probe, |
a49d2536 | 1456 | .remove = gc0310_remove, |
a49d2536 | 1457 | }; |
2cb63c4c | 1458 | module_i2c_driver(gc0310_driver); |
a49d2536 AC |
1459 | |
1460 | MODULE_AUTHOR("Lai, Angie <angie.lai@intel.com>"); | |
1461 | MODULE_DESCRIPTION("A low-level driver for GalaxyCore GC0310 sensors"); | |
1462 | MODULE_LICENSE("GPL"); |