2 * Driver for Samsung S5K5BAF UXGA 1/5" 2M CMOS Image Sensor
3 * with embedded SoC ISP.
5 * Copyright (C) 2013, Samsung Electronics Co., Ltd.
6 * Andrzej Hajda <a.hajda@samsung.com>
8 * Based on S5K6AA driver authored by Sylwester Nawrocki
9 * Copyright (C) 2013, Samsung Electronics Co., Ltd.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
16 #include <linux/clk.h>
17 #include <linux/delay.h>
18 #include <linux/firmware.h>
19 #include <linux/gpio.h>
20 #include <linux/i2c.h>
21 #include <linux/media.h>
22 #include <linux/module.h>
23 #include <linux/of_gpio.h>
24 #include <linux/of_graph.h>
25 #include <linux/regulator/consumer.h>
26 #include <linux/slab.h>
28 #include <media/media-entity.h>
29 #include <media/v4l2-ctrls.h>
30 #include <media/v4l2-device.h>
31 #include <media/v4l2-subdev.h>
32 #include <media/v4l2-mediabus.h>
33 #include <media/v4l2-fwnode.h>
36 module_param(debug
, int, 0644);
38 #define S5K5BAF_DRIVER_NAME "s5k5baf"
39 #define S5K5BAF_DEFAULT_MCLK_FREQ 24000000U
40 #define S5K5BAF_CLK_NAME "mclk"
42 #define S5K5BAF_FW_FILENAME "s5k5baf-cfg.bin"
43 #define S5K5BAF_FW_TAG "SF00"
44 #define S5K5BAG_FW_TAG_LEN 2
45 #define S5K5BAG_FW_MAX_COUNT 16
47 #define S5K5BAF_CIS_WIDTH 1600
48 #define S5K5BAF_CIS_HEIGHT 1200
49 #define S5K5BAF_WIN_WIDTH_MIN 8
50 #define S5K5BAF_WIN_HEIGHT_MIN 8
51 #define S5K5BAF_GAIN_RED_DEF 127
52 #define S5K5BAF_GAIN_GREEN_DEF 95
53 #define S5K5BAF_GAIN_BLUE_DEF 180
54 /* Default number of MIPI CSI-2 data lanes used */
55 #define S5K5BAF_DEF_NUM_LANES 1
57 #define AHB_MSB_ADDR_PTR 0xfcfc
60 * Register interface pages (the most significant word of the address)
62 #define PAGE_IF_HW 0xd000
63 #define PAGE_IF_SW 0x7000
66 * H/W register Interface (PAGE_IF_HW)
68 #define REG_SW_LOAD_COMPLETE 0x0014
69 #define REG_CMDWR_PAGE 0x0028
70 #define REG_CMDWR_ADDR 0x002a
71 #define REG_CMDRD_PAGE 0x002c
72 #define REG_CMDRD_ADDR 0x002e
73 #define REG_CMD_BUF 0x0f12
74 #define REG_SET_HOST_INT 0x1000
75 #define REG_CLEAR_HOST_INT 0x1030
76 #define REG_PATTERN_SET 0x3100
77 #define REG_PATTERN_WIDTH 0x3118
78 #define REG_PATTERN_HEIGHT 0x311a
79 #define REG_PATTERN_PARAM 0x311c
82 * S/W register interface (PAGE_IF_SW)
85 /* Firmware revision information */
86 #define REG_FW_APIVER 0x012e
87 #define S5K5BAF_FW_APIVER 0x0001
88 #define REG_FW_REVISION 0x0130
89 #define REG_FW_SENSOR_ID 0x0152
91 /* Initialization parameters */
92 /* Master clock frequency in KHz */
93 #define REG_I_INCLK_FREQ_L 0x01b8
94 #define REG_I_INCLK_FREQ_H 0x01ba
95 #define MIN_MCLK_FREQ_KHZ 6000U
96 #define MAX_MCLK_FREQ_KHZ 48000U
97 #define REG_I_USE_NPVI_CLOCKS 0x01c6
99 #define REG_I_USE_NMIPI_CLOCKS 0x01c8
100 #define NMIPI_CLOCKS 1
101 #define REG_I_BLOCK_INTERNAL_PLL_CALC 0x01ca
103 /* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
104 #define REG_I_OPCLK_4KHZ(n) ((n) * 6 + 0x01cc)
105 #define REG_I_MIN_OUTRATE_4KHZ(n) ((n) * 6 + 0x01ce)
106 #define REG_I_MAX_OUTRATE_4KHZ(n) ((n) * 6 + 0x01d0)
107 #define SCLK_PVI_FREQ 24000
108 #define SCLK_MIPI_FREQ 48000
109 #define PCLK_MIN_FREQ 6000
110 #define PCLK_MAX_FREQ 48000
111 #define REG_I_USE_REGS_API 0x01de
112 #define REG_I_INIT_PARAMS_UPDATED 0x01e0
113 #define REG_I_ERROR_INFO 0x01e2
115 /* General purpose parameters */
116 #define REG_USER_BRIGHTNESS 0x01e4
117 #define REG_USER_CONTRAST 0x01e6
118 #define REG_USER_SATURATION 0x01e8
119 #define REG_USER_SHARPBLUR 0x01ea
121 #define REG_G_SPEC_EFFECTS 0x01ee
122 #define REG_G_ENABLE_PREV 0x01f0
123 #define REG_G_ENABLE_PREV_CHG 0x01f2
124 #define REG_G_NEW_CFG_SYNC 0x01f8
125 #define REG_G_PREVREQ_IN_WIDTH 0x01fa
126 #define REG_G_PREVREQ_IN_HEIGHT 0x01fc
127 #define REG_G_PREVREQ_IN_XOFFS 0x01fe
128 #define REG_G_PREVREQ_IN_YOFFS 0x0200
129 #define REG_G_PREVZOOM_IN_WIDTH 0x020a
130 #define REG_G_PREVZOOM_IN_HEIGHT 0x020c
131 #define REG_G_PREVZOOM_IN_XOFFS 0x020e
132 #define REG_G_PREVZOOM_IN_YOFFS 0x0210
133 #define REG_G_INPUTS_CHANGE_REQ 0x021a
134 #define REG_G_ACTIVE_PREV_CFG 0x021c
135 #define REG_G_PREV_CFG_CHG 0x021e
136 #define REG_G_PREV_OPEN_AFTER_CH 0x0220
137 #define REG_G_PREV_CFG_ERROR 0x0222
138 #define CFG_ERROR_RANGE 0x0b
139 #define REG_G_PREV_CFG_BYPASS_CHANGED 0x022a
140 #define REG_G_ACTUAL_P_FR_TIME 0x023a
141 #define REG_G_ACTUAL_P_OUT_RATE 0x023c
142 #define REG_G_ACTUAL_C_FR_TIME 0x023e
143 #define REG_G_ACTUAL_C_OUT_RATE 0x0240
145 /* Preview control section. n = 0...4. */
146 #define PREG(n, x) ((n) * 0x26 + x)
147 #define REG_P_OUT_WIDTH(n) PREG(n, 0x0242)
148 #define REG_P_OUT_HEIGHT(n) PREG(n, 0x0244)
149 #define REG_P_FMT(n) PREG(n, 0x0246)
150 #define REG_P_MAX_OUT_RATE(n) PREG(n, 0x0248)
151 #define REG_P_MIN_OUT_RATE(n) PREG(n, 0x024a)
152 #define REG_P_PVI_MASK(n) PREG(n, 0x024c)
153 #define PVI_MASK_MIPI 0x52
154 #define REG_P_CLK_INDEX(n) PREG(n, 0x024e)
155 #define CLK_PVI_INDEX 0
156 #define CLK_MIPI_INDEX NPVI_CLOCKS
157 #define REG_P_FR_RATE_TYPE(n) PREG(n, 0x0250)
158 #define FR_RATE_DYNAMIC 0
159 #define FR_RATE_FIXED 1
160 #define FR_RATE_FIXED_ACCURATE 2
161 #define REG_P_FR_RATE_Q_TYPE(n) PREG(n, 0x0252)
162 #define FR_RATE_Q_DYNAMIC 0
163 #define FR_RATE_Q_BEST_FRRATE 1 /* Binning enabled */
164 #define FR_RATE_Q_BEST_QUALITY 2 /* Binning disabled */
165 /* Frame period in 0.1 ms units */
166 #define REG_P_MAX_FR_TIME(n) PREG(n, 0x0254)
167 #define REG_P_MIN_FR_TIME(n) PREG(n, 0x0256)
168 #define S5K5BAF_MIN_FR_TIME 333 /* x100 us */
169 #define S5K5BAF_MAX_FR_TIME 6500 /* x100 us */
170 /* The below 5 registers are for "device correction" values */
171 #define REG_P_SATURATION(n) PREG(n, 0x0258)
172 #define REG_P_SHARP_BLUR(n) PREG(n, 0x025a)
173 #define REG_P_GLAMOUR(n) PREG(n, 0x025c)
174 #define REG_P_COLORTEMP(n) PREG(n, 0x025e)
175 #define REG_P_GAMMA_INDEX(n) PREG(n, 0x0260)
176 #define REG_P_PREV_MIRROR(n) PREG(n, 0x0262)
177 #define REG_P_CAP_MIRROR(n) PREG(n, 0x0264)
178 #define REG_P_CAP_ROTATION(n) PREG(n, 0x0266)
180 /* Extended image property controls */
181 /* Exposure time in 10 us units */
182 #define REG_SF_USR_EXPOSURE_L 0x03bc
183 #define REG_SF_USR_EXPOSURE_H 0x03be
184 #define REG_SF_USR_EXPOSURE_CHG 0x03c0
185 #define REG_SF_USR_TOT_GAIN 0x03c2
186 #define REG_SF_USR_TOT_GAIN_CHG 0x03c4
187 #define REG_SF_RGAIN 0x03c6
188 #define REG_SF_RGAIN_CHG 0x03c8
189 #define REG_SF_GGAIN 0x03ca
190 #define REG_SF_GGAIN_CHG 0x03cc
191 #define REG_SF_BGAIN 0x03ce
192 #define REG_SF_BGAIN_CHG 0x03d0
193 #define REG_SF_WBGAIN_CHG 0x03d2
194 #define REG_SF_FLICKER_QUANT 0x03d4
195 #define REG_SF_FLICKER_QUANT_CHG 0x03d6
197 /* Output interface (parallel/MIPI) setup */
198 #define REG_OIF_EN_MIPI_LANES 0x03f2
199 #define REG_OIF_EN_PACKETS 0x03f4
200 #define EN_PACKETS_CSI2 0xc3
201 #define REG_OIF_CFG_CHG 0x03f6
203 /* Auto-algorithms enable mask */
204 #define REG_DBG_AUTOALG_EN 0x03f8
205 #define AALG_ALL_EN BIT(0)
206 #define AALG_AE_EN BIT(1)
207 #define AALG_DIVLEI_EN BIT(2)
208 #define AALG_WB_EN BIT(3)
209 #define AALG_USE_WB_FOR_ISP BIT(4)
210 #define AALG_FLICKER_EN BIT(5)
211 #define AALG_FIT_EN BIT(6)
212 #define AALG_WRHW_EN BIT(7)
214 /* Pointers to color correction matrices */
215 #define REG_PTR_CCM_HORIZON 0x06d0
216 #define REG_PTR_CCM_INCANDESCENT 0x06d4
217 #define REG_PTR_CCM_WARM_WHITE 0x06d8
218 #define REG_PTR_CCM_COOL_WHITE 0x06dc
219 #define REG_PTR_CCM_DL50 0x06e0
220 #define REG_PTR_CCM_DL65 0x06e4
221 #define REG_PTR_CCM_OUTDOOR 0x06ec
223 #define REG_ARR_CCM(n) (0x2800 + 36 * (n))
225 static const char * const s5k5baf_supply_names
[] = {
226 "vdda", /* Analog power supply 2.8V (2.6V to 3.0V) */
227 "vddreg", /* Regulator input power supply 1.8V (1.7V to 1.9V)
228 or 2.8V (2.6V to 3.0) */
229 "vddio", /* I/O power supply 1.8V (1.65V to 1.95V)
230 or 2.8V (2.5V to 3.1V) */
232 #define S5K5BAF_NUM_SUPPLIES ARRAY_SIZE(s5k5baf_supply_names)
234 struct s5k5baf_gpio
{
239 enum s5k5baf_gpio_id
{
247 #define NUM_CIS_PADS 1
248 #define NUM_ISP_PADS 2
250 struct s5k5baf_pixfmt
{
253 /* REG_P_FMT(x) register value */
257 struct s5k5baf_ctrls
{
258 struct v4l2_ctrl_handler handler
;
259 struct { /* Auto / manual white balance cluster */
260 struct v4l2_ctrl
*awb
;
261 struct v4l2_ctrl
*gain_red
;
262 struct v4l2_ctrl
*gain_blue
;
264 struct { /* Mirror cluster */
265 struct v4l2_ctrl
*hflip
;
266 struct v4l2_ctrl
*vflip
;
268 struct { /* Auto exposure / manual exposure and gain cluster */
269 struct v4l2_ctrl
*auto_exp
;
270 struct v4l2_ctrl
*exposure
;
271 struct v4l2_ctrl
*gain
;
291 struct s5k5baf_gpio gpios
[NUM_GPIOS
];
292 enum v4l2_mbus_type bus_type
;
294 struct regulator_bulk_data supplies
[S5K5BAF_NUM_SUPPLIES
];
299 struct s5k5baf_fw
*fw
;
301 struct v4l2_subdev cis_sd
;
302 struct media_pad cis_pad
;
304 struct v4l2_subdev sd
;
305 struct media_pad pads
[NUM_ISP_PADS
];
307 /* protects the struct members below */
312 struct v4l2_rect crop_sink
;
313 struct v4l2_rect compose
;
314 struct v4l2_rect crop_source
;
315 /* index to s5k5baf_formats array */
317 /* actual frame interval in 100us */
319 /* requested frame interval in 100us */
321 /* cache for REG_DBG_AUTOALG_EN register */
324 struct s5k5baf_ctrls ctrls
;
326 unsigned int streaming
:1;
327 unsigned int apply_cfg
:1;
328 unsigned int apply_crop
:1;
329 unsigned int valid_auto_alg
:1;
333 static const struct s5k5baf_pixfmt s5k5baf_formats
[] = {
334 { MEDIA_BUS_FMT_VYUY8_2X8
, V4L2_COLORSPACE_JPEG
, 5 },
336 { MEDIA_BUS_FMT_VYUY8_2X8
, V4L2_COLORSPACE_REC709
, 6 },
337 { MEDIA_BUS_FMT_RGB565_2X8_BE
, V4L2_COLORSPACE_JPEG
, 0 },
340 static struct v4l2_rect s5k5baf_cis_rect
= {
341 0, 0, S5K5BAF_CIS_WIDTH
, S5K5BAF_CIS_HEIGHT
344 /* Setfile contains set of I2C command sequences. Each sequence has its ID.
347 * u16 count; number of sequences
349 * u16 id; sequence id
350 * u16 offset; sequence offset in data array
352 * u16 data[*]; array containing sequences
355 static int s5k5baf_fw_parse(struct device
*dev
, struct s5k5baf_fw
**fw
,
356 size_t count
, const __le16
*data
)
358 struct s5k5baf_fw
*f
;
362 if (count
< S5K5BAG_FW_TAG_LEN
+ 1) {
363 dev_err(dev
, "firmware file too short (%zu)\n", count
);
367 ret
= memcmp(data
, S5K5BAF_FW_TAG
, S5K5BAG_FW_TAG_LEN
* sizeof(u16
));
369 dev_err(dev
, "invalid firmware magic number\n");
373 data
+= S5K5BAG_FW_TAG_LEN
;
374 count
-= S5K5BAG_FW_TAG_LEN
;
376 d
= devm_kzalloc(dev
, count
* sizeof(u16
), GFP_KERNEL
);
380 for (i
= 0; i
< count
; ++i
)
381 d
[i
] = le16_to_cpu(data
[i
]);
383 f
= (struct s5k5baf_fw
*)d
;
384 if (count
< 1 + 2 * f
->count
) {
385 dev_err(dev
, "invalid firmware header (count=%d size=%zu)\n",
386 f
->count
, 2 * (count
+ S5K5BAG_FW_TAG_LEN
));
390 d
+= 1 + 2 * f
->count
;
392 for (i
= 0; i
< f
->count
; ++i
) {
393 if (f
->seq
[i
].offset
+ d
<= end
)
395 dev_err(dev
, "invalid firmware header (seq=%d)\n", i
);
404 static inline struct v4l2_subdev
*ctrl_to_sd(struct v4l2_ctrl
*ctrl
)
406 return &container_of(ctrl
->handler
, struct s5k5baf
, ctrls
.handler
)->sd
;
409 static inline bool s5k5baf_is_cis_subdev(struct v4l2_subdev
*sd
)
411 return sd
->entity
.function
== MEDIA_ENT_F_CAM_SENSOR
;
414 static inline struct s5k5baf
*to_s5k5baf(struct v4l2_subdev
*sd
)
416 if (s5k5baf_is_cis_subdev(sd
))
417 return container_of(sd
, struct s5k5baf
, cis_sd
);
419 return container_of(sd
, struct s5k5baf
, sd
);
422 static u16
s5k5baf_i2c_read(struct s5k5baf
*state
, u16 addr
)
424 struct i2c_client
*c
= v4l2_get_subdevdata(&state
->sd
);
427 struct i2c_msg msg
[] = {
428 { .addr
= c
->addr
, .flags
= 0,
429 .len
= 2, .buf
= (u8
*)&w
},
430 { .addr
= c
->addr
, .flags
= I2C_M_RD
,
431 .len
= 2, .buf
= (u8
*)&r
},
438 w
= cpu_to_be16(addr
);
439 ret
= i2c_transfer(c
->adapter
, msg
, 2);
440 res
= be16_to_cpu(r
);
442 v4l2_dbg(3, debug
, c
, "i2c_read: 0x%04x : 0x%04x\n", addr
, res
);
445 v4l2_err(c
, "i2c_read: error during transfer (%d)\n", ret
);
451 static void s5k5baf_i2c_write(struct s5k5baf
*state
, u16 addr
, u16 val
)
453 u8 buf
[4] = { addr
>> 8, addr
& 0xFF, val
>> 8, val
& 0xFF };
454 struct i2c_client
*c
= v4l2_get_subdevdata(&state
->sd
);
460 ret
= i2c_master_send(c
, buf
, 4);
461 v4l2_dbg(3, debug
, c
, "i2c_write: 0x%04x : 0x%04x\n", addr
, val
);
464 v4l2_err(c
, "i2c_write: error during transfer (%d)\n", ret
);
469 static u16
s5k5baf_read(struct s5k5baf
*state
, u16 addr
)
471 s5k5baf_i2c_write(state
, REG_CMDRD_ADDR
, addr
);
472 return s5k5baf_i2c_read(state
, REG_CMD_BUF
);
475 static void s5k5baf_write(struct s5k5baf
*state
, u16 addr
, u16 val
)
477 s5k5baf_i2c_write(state
, REG_CMDWR_ADDR
, addr
);
478 s5k5baf_i2c_write(state
, REG_CMD_BUF
, val
);
481 static void s5k5baf_write_arr_seq(struct s5k5baf
*state
, u16 addr
,
482 u16 count
, const u16
*seq
)
484 struct i2c_client
*c
= v4l2_get_subdevdata(&state
->sd
);
487 s5k5baf_i2c_write(state
, REG_CMDWR_ADDR
, addr
);
491 v4l2_dbg(3, debug
, c
, "i2c_write_seq(count=%d): %*ph\n", count
,
492 min(2 * count
, 64), seq
);
494 buf
[0] = cpu_to_be16(REG_CMD_BUF
);
497 int n
= min_t(int, count
, ARRAY_SIZE(buf
) - 1);
500 for (i
= 1; i
<= n
; ++i
)
501 buf
[i
] = cpu_to_be16(*seq
++);
504 ret
= i2c_master_send(c
, (char *)buf
, i
);
506 v4l2_err(c
, "i2c_write_seq: error during transfer (%d)\n", ret
);
515 #define s5k5baf_write_seq(state, addr, seq...) \
516 s5k5baf_write_arr_seq(state, addr, sizeof((char[]){ seq }), \
517 (const u16 []){ seq });
519 /* add items count at the beginning of the list */
520 #define NSEQ(seq...) sizeof((char[]){ seq }), seq
523 * s5k5baf_write_nseq() - Writes sequences of values to sensor memory via i2c
524 * @nseq: sequence of u16 words in format:
525 * (N, address, value[1]...value[N-1])*,0
527 * u16 seq[] = { NSEQ(0x4000, 1, 1), NSEQ(0x4010, 640, 480), 0 };
528 * ret = s5k5baf_write_nseq(c, seq);
530 static void s5k5baf_write_nseq(struct s5k5baf
*state
, const u16
*nseq
)
534 while ((count
= *nseq
++)) {
538 s5k5baf_write_arr_seq(state
, addr
, count
, nseq
);
543 static void s5k5baf_synchronize(struct s5k5baf
*state
, int timeout
, u16 addr
)
545 unsigned long end
= jiffies
+ msecs_to_jiffies(timeout
);
548 s5k5baf_write(state
, addr
, 1);
550 reg
= s5k5baf_read(state
, addr
);
551 if (state
->error
|| !reg
)
553 usleep_range(5000, 10000);
554 } while (time_is_after_jiffies(end
));
556 v4l2_err(&state
->sd
, "timeout on register synchronize (%#x)\n", addr
);
557 state
->error
= -ETIMEDOUT
;
560 static u16
*s5k5baf_fw_get_seq(struct s5k5baf
*state
, u16 seq_id
)
562 struct s5k5baf_fw
*fw
= state
->fw
;
569 data
= fw
->data
+ 2 * fw
->count
;
571 for (i
= 0; i
< fw
->count
; ++i
) {
572 if (fw
->seq
[i
].id
== seq_id
)
573 return data
+ fw
->seq
[i
].offset
;
579 static void s5k5baf_hw_patch(struct s5k5baf
*state
)
581 u16
*seq
= s5k5baf_fw_get_seq(state
, S5K5BAF_FW_ID_PATCH
);
584 s5k5baf_write_nseq(state
, seq
);
587 static void s5k5baf_hw_set_clocks(struct s5k5baf
*state
)
589 unsigned long mclk
= state
->mclk_frequency
/ 1000;
591 static const u16 nseq_clk_cfg
[] = {
592 NSEQ(REG_I_USE_NPVI_CLOCKS
,
593 NPVI_CLOCKS
, NMIPI_CLOCKS
, 0,
594 SCLK_PVI_FREQ
/ 4, PCLK_MIN_FREQ
/ 4, PCLK_MAX_FREQ
/ 4,
595 SCLK_MIPI_FREQ
/ 4, PCLK_MIN_FREQ
/ 4, PCLK_MAX_FREQ
/ 4),
596 NSEQ(REG_I_USE_REGS_API
, 1),
600 s5k5baf_write_seq(state
, REG_I_INCLK_FREQ_L
, mclk
& 0xffff, mclk
>> 16);
601 s5k5baf_write_nseq(state
, nseq_clk_cfg
);
603 s5k5baf_synchronize(state
, 250, REG_I_INIT_PARAMS_UPDATED
);
604 status
= s5k5baf_read(state
, REG_I_ERROR_INFO
);
605 if (!state
->error
&& status
) {
606 v4l2_err(&state
->sd
, "error configuring PLL (%d)\n", status
);
607 state
->error
= -EINVAL
;
611 /* set custom color correction matrices for various illuminations */
612 static void s5k5baf_hw_set_ccm(struct s5k5baf
*state
)
614 u16
*seq
= s5k5baf_fw_get_seq(state
, S5K5BAF_FW_ID_CCM
);
617 s5k5baf_write_nseq(state
, seq
);
620 /* CIS sensor tuning, based on undocumented android driver code */
621 static void s5k5baf_hw_set_cis(struct s5k5baf
*state
)
623 u16
*seq
= s5k5baf_fw_get_seq(state
, S5K5BAF_FW_ID_CIS
);
628 s5k5baf_i2c_write(state
, REG_CMDWR_PAGE
, PAGE_IF_HW
);
629 s5k5baf_write_nseq(state
, seq
);
630 s5k5baf_i2c_write(state
, REG_CMDWR_PAGE
, PAGE_IF_SW
);
633 static void s5k5baf_hw_sync_cfg(struct s5k5baf
*state
)
635 s5k5baf_write(state
, REG_G_PREV_CFG_CHG
, 1);
636 if (state
->apply_crop
) {
637 s5k5baf_write(state
, REG_G_INPUTS_CHANGE_REQ
, 1);
638 s5k5baf_write(state
, REG_G_PREV_CFG_BYPASS_CHANGED
, 1);
640 s5k5baf_synchronize(state
, 500, REG_G_NEW_CFG_SYNC
);
642 /* Set horizontal and vertical image flipping */
643 static void s5k5baf_hw_set_mirror(struct s5k5baf
*state
)
645 u16 flip
= state
->ctrls
.vflip
->val
| (state
->ctrls
.vflip
->val
<< 1);
647 s5k5baf_write(state
, REG_P_PREV_MIRROR(0), flip
);
648 if (state
->streaming
)
649 s5k5baf_hw_sync_cfg(state
);
652 static void s5k5baf_hw_set_alg(struct s5k5baf
*state
, u16 alg
, bool enable
)
654 u16 cur_alg
, new_alg
;
656 if (!state
->valid_auto_alg
)
657 cur_alg
= s5k5baf_read(state
, REG_DBG_AUTOALG_EN
);
659 cur_alg
= state
->auto_alg
;
661 new_alg
= enable
? (cur_alg
| alg
) : (cur_alg
& ~alg
);
663 if (new_alg
!= cur_alg
)
664 s5k5baf_write(state
, REG_DBG_AUTOALG_EN
, new_alg
);
669 state
->valid_auto_alg
= 1;
670 state
->auto_alg
= new_alg
;
673 /* Configure auto/manual white balance and R/G/B gains */
674 static void s5k5baf_hw_set_awb(struct s5k5baf
*state
, int awb
)
676 struct s5k5baf_ctrls
*ctrls
= &state
->ctrls
;
679 s5k5baf_write_seq(state
, REG_SF_RGAIN
,
680 ctrls
->gain_red
->val
, 1,
681 S5K5BAF_GAIN_GREEN_DEF
, 1,
682 ctrls
->gain_blue
->val
, 1,
685 s5k5baf_hw_set_alg(state
, AALG_WB_EN
, awb
);
688 /* Program FW with exposure time, 'exposure' in us units */
689 static void s5k5baf_hw_set_user_exposure(struct s5k5baf
*state
, int exposure
)
691 unsigned int time
= exposure
/ 10;
693 s5k5baf_write_seq(state
, REG_SF_USR_EXPOSURE_L
,
694 time
& 0xffff, time
>> 16, 1);
697 static void s5k5baf_hw_set_user_gain(struct s5k5baf
*state
, int gain
)
699 s5k5baf_write_seq(state
, REG_SF_USR_TOT_GAIN
, gain
, 1);
702 /* Set auto/manual exposure and total gain */
703 static void s5k5baf_hw_set_auto_exposure(struct s5k5baf
*state
, int value
)
705 if (value
== V4L2_EXPOSURE_AUTO
) {
706 s5k5baf_hw_set_alg(state
, AALG_AE_EN
| AALG_DIVLEI_EN
, true);
708 unsigned int exp_time
= state
->ctrls
.exposure
->val
;
710 s5k5baf_hw_set_user_exposure(state
, exp_time
);
711 s5k5baf_hw_set_user_gain(state
, state
->ctrls
.gain
->val
);
712 s5k5baf_hw_set_alg(state
, AALG_AE_EN
| AALG_DIVLEI_EN
, false);
716 static void s5k5baf_hw_set_anti_flicker(struct s5k5baf
*state
, int v
)
718 if (v
== V4L2_CID_POWER_LINE_FREQUENCY_AUTO
) {
719 s5k5baf_hw_set_alg(state
, AALG_FLICKER_EN
, true);
721 /* The V4L2_CID_LINE_FREQUENCY control values match
722 * the register values */
723 s5k5baf_write_seq(state
, REG_SF_FLICKER_QUANT
, v
, 1);
724 s5k5baf_hw_set_alg(state
, AALG_FLICKER_EN
, false);
728 static void s5k5baf_hw_set_colorfx(struct s5k5baf
*state
, int val
)
730 static const u16 colorfx
[] = {
731 [V4L2_COLORFX_NONE
] = 0,
732 [V4L2_COLORFX_BW
] = 1,
733 [V4L2_COLORFX_NEGATIVE
] = 2,
734 [V4L2_COLORFX_SEPIA
] = 3,
735 [V4L2_COLORFX_SKY_BLUE
] = 4,
736 [V4L2_COLORFX_SKETCH
] = 5,
739 s5k5baf_write(state
, REG_G_SPEC_EFFECTS
, colorfx
[val
]);
742 static int s5k5baf_find_pixfmt(struct v4l2_mbus_framefmt
*mf
)
746 for (i
= 0; i
< ARRAY_SIZE(s5k5baf_formats
); i
++) {
747 if (mf
->colorspace
!= s5k5baf_formats
[i
].colorspace
)
749 if (mf
->code
== s5k5baf_formats
[i
].code
)
754 return (c
< 0) ? 0 : c
;
757 static int s5k5baf_clear_error(struct s5k5baf
*state
)
759 int ret
= state
->error
;
765 static int s5k5baf_hw_set_video_bus(struct s5k5baf
*state
)
769 if (state
->bus_type
== V4L2_MBUS_CSI2
)
770 en_pkts
= EN_PACKETS_CSI2
;
774 s5k5baf_write_seq(state
, REG_OIF_EN_MIPI_LANES
,
775 state
->nlanes
, en_pkts
, 1);
777 return s5k5baf_clear_error(state
);
780 static u16
s5k5baf_get_cfg_error(struct s5k5baf
*state
)
782 u16 err
= s5k5baf_read(state
, REG_G_PREV_CFG_ERROR
);
784 s5k5baf_write(state
, REG_G_PREV_CFG_ERROR
, 0);
788 static void s5k5baf_hw_set_fiv(struct s5k5baf
*state
, u16 fiv
)
790 s5k5baf_write(state
, REG_P_MAX_FR_TIME(0), fiv
);
791 s5k5baf_hw_sync_cfg(state
);
794 static void s5k5baf_hw_find_min_fiv(struct s5k5baf
*state
)
799 fiv
= s5k5baf_read(state
, REG_G_ACTUAL_P_FR_TIME
);
803 for (n
= 5; n
> 0; --n
) {
804 s5k5baf_hw_set_fiv(state
, fiv
);
805 err
= s5k5baf_get_cfg_error(state
);
809 case CFG_ERROR_RANGE
:
814 v4l2_info(&state
->sd
,
815 "found valid frame interval: %d00us\n", fiv
);
819 "error setting frame interval: %d\n", err
);
820 state
->error
= -EINVAL
;
823 v4l2_err(&state
->sd
, "cannot find correct frame interval\n");
824 state
->error
= -ERANGE
;
827 static void s5k5baf_hw_validate_cfg(struct s5k5baf
*state
)
831 err
= s5k5baf_get_cfg_error(state
);
837 state
->apply_cfg
= 1;
839 case CFG_ERROR_RANGE
:
840 s5k5baf_hw_find_min_fiv(state
);
842 state
->apply_cfg
= 1;
846 "error setting format: %d\n", err
);
847 state
->error
= -EINVAL
;
851 static void s5k5baf_rescale(struct v4l2_rect
*r
, const struct v4l2_rect
*v
,
852 const struct v4l2_rect
*n
,
853 const struct v4l2_rect
*d
)
855 r
->left
= v
->left
* n
->width
/ d
->width
;
856 r
->top
= v
->top
* n
->height
/ d
->height
;
857 r
->width
= v
->width
* n
->width
/ d
->width
;
858 r
->height
= v
->height
* n
->height
/ d
->height
;
861 static int s5k5baf_hw_set_crop_rects(struct s5k5baf
*state
)
863 struct v4l2_rect
*p
, r
;
867 p
= &state
->crop_sink
;
868 s5k5baf_write_seq(state
, REG_G_PREVREQ_IN_WIDTH
, p
->width
, p
->height
,
871 s5k5baf_rescale(&r
, &state
->crop_source
, &state
->crop_sink
,
873 s5k5baf_write_seq(state
, REG_G_PREVZOOM_IN_WIDTH
, r
.width
, r
.height
,
876 s5k5baf_synchronize(state
, 500, REG_G_INPUTS_CHANGE_REQ
);
877 s5k5baf_synchronize(state
, 500, REG_G_PREV_CFG_BYPASS_CHANGED
);
878 err
= s5k5baf_get_cfg_error(state
);
879 ret
= s5k5baf_clear_error(state
);
886 case CFG_ERROR_RANGE
:
887 /* retry crop with frame interval set to max */
888 s5k5baf_hw_set_fiv(state
, S5K5BAF_MAX_FR_TIME
);
889 err
= s5k5baf_get_cfg_error(state
);
890 ret
= s5k5baf_clear_error(state
);
895 "crop error on max frame interval: %d\n", err
);
896 state
->error
= -EINVAL
;
898 s5k5baf_hw_set_fiv(state
, state
->req_fiv
);
899 s5k5baf_hw_validate_cfg(state
);
902 v4l2_err(&state
->sd
, "crop error: %d\n", err
);
906 if (!state
->apply_cfg
)
909 p
= &state
->crop_source
;
910 s5k5baf_write_seq(state
, REG_P_OUT_WIDTH(0), p
->width
, p
->height
);
911 s5k5baf_hw_set_fiv(state
, state
->req_fiv
);
912 s5k5baf_hw_validate_cfg(state
);
914 return s5k5baf_clear_error(state
);
917 static void s5k5baf_hw_set_config(struct s5k5baf
*state
)
919 u16 reg_fmt
= s5k5baf_formats
[state
->pixfmt
].reg_p_fmt
;
920 struct v4l2_rect
*r
= &state
->crop_source
;
922 s5k5baf_write_seq(state
, REG_P_OUT_WIDTH(0),
923 r
->width
, r
->height
, reg_fmt
,
924 PCLK_MAX_FREQ
>> 2, PCLK_MIN_FREQ
>> 2,
925 PVI_MASK_MIPI
, CLK_MIPI_INDEX
,
926 FR_RATE_FIXED
, FR_RATE_Q_DYNAMIC
,
927 state
->req_fiv
, S5K5BAF_MIN_FR_TIME
);
928 s5k5baf_hw_sync_cfg(state
);
929 s5k5baf_hw_validate_cfg(state
);
933 static void s5k5baf_hw_set_test_pattern(struct s5k5baf
*state
, int id
)
935 s5k5baf_i2c_write(state
, REG_PATTERN_WIDTH
, 800);
936 s5k5baf_i2c_write(state
, REG_PATTERN_HEIGHT
, 511);
937 s5k5baf_i2c_write(state
, REG_PATTERN_PARAM
, 0);
938 s5k5baf_i2c_write(state
, REG_PATTERN_SET
, id
);
941 static void s5k5baf_gpio_assert(struct s5k5baf
*state
, int id
)
943 struct s5k5baf_gpio
*gpio
= &state
->gpios
[id
];
945 gpio_set_value(gpio
->gpio
, gpio
->level
);
948 static void s5k5baf_gpio_deassert(struct s5k5baf
*state
, int id
)
950 struct s5k5baf_gpio
*gpio
= &state
->gpios
[id
];
952 gpio_set_value(gpio
->gpio
, !gpio
->level
);
955 static int s5k5baf_power_on(struct s5k5baf
*state
)
959 ret
= regulator_bulk_enable(S5K5BAF_NUM_SUPPLIES
, state
->supplies
);
963 ret
= clk_set_rate(state
->clock
, state
->mclk_frequency
);
967 ret
= clk_prepare_enable(state
->clock
);
971 v4l2_dbg(1, debug
, &state
->sd
, "clock frequency: %ld\n",
972 clk_get_rate(state
->clock
));
974 s5k5baf_gpio_deassert(state
, STBY
);
975 usleep_range(50, 100);
976 s5k5baf_gpio_deassert(state
, RST
);
980 regulator_bulk_disable(S5K5BAF_NUM_SUPPLIES
, state
->supplies
);
982 v4l2_err(&state
->sd
, "%s() failed (%d)\n", __func__
, ret
);
986 static int s5k5baf_power_off(struct s5k5baf
*state
)
990 state
->streaming
= 0;
991 state
->apply_cfg
= 0;
992 state
->apply_crop
= 0;
994 s5k5baf_gpio_assert(state
, RST
);
995 s5k5baf_gpio_assert(state
, STBY
);
997 if (!IS_ERR(state
->clock
))
998 clk_disable_unprepare(state
->clock
);
1000 ret
= regulator_bulk_disable(S5K5BAF_NUM_SUPPLIES
,
1003 v4l2_err(&state
->sd
, "failed to disable regulators\n");
1008 static void s5k5baf_hw_init(struct s5k5baf
*state
)
1010 s5k5baf_i2c_write(state
, AHB_MSB_ADDR_PTR
, PAGE_IF_HW
);
1011 s5k5baf_i2c_write(state
, REG_CLEAR_HOST_INT
, 0);
1012 s5k5baf_i2c_write(state
, REG_SW_LOAD_COMPLETE
, 1);
1013 s5k5baf_i2c_write(state
, REG_CMDRD_PAGE
, PAGE_IF_SW
);
1014 s5k5baf_i2c_write(state
, REG_CMDWR_PAGE
, PAGE_IF_SW
);
1018 * V4L2 subdev core and video operations
1021 static void s5k5baf_initialize_data(struct s5k5baf
*state
)
1024 state
->req_fiv
= 10000 / 15;
1025 state
->fiv
= state
->req_fiv
;
1026 state
->valid_auto_alg
= 0;
1029 static int s5k5baf_load_setfile(struct s5k5baf
*state
)
1031 struct i2c_client
*c
= v4l2_get_subdevdata(&state
->sd
);
1032 const struct firmware
*fw
;
1035 ret
= request_firmware(&fw
, S5K5BAF_FW_FILENAME
, &c
->dev
);
1037 dev_warn(&c
->dev
, "firmware file (%s) not loaded\n",
1038 S5K5BAF_FW_FILENAME
);
1042 ret
= s5k5baf_fw_parse(&c
->dev
, &state
->fw
, fw
->size
/ 2,
1043 (__le16
*)fw
->data
);
1045 release_firmware(fw
);
1050 static int s5k5baf_set_power(struct v4l2_subdev
*sd
, int on
)
1052 struct s5k5baf
*state
= to_s5k5baf(sd
);
1055 mutex_lock(&state
->lock
);
1057 if (state
->power
!= !on
)
1061 if (state
->fw
== NULL
)
1062 s5k5baf_load_setfile(state
);
1064 s5k5baf_initialize_data(state
);
1065 ret
= s5k5baf_power_on(state
);
1069 s5k5baf_hw_init(state
);
1070 s5k5baf_hw_patch(state
);
1071 s5k5baf_i2c_write(state
, REG_SET_HOST_INT
, 1);
1072 s5k5baf_hw_set_clocks(state
);
1074 ret
= s5k5baf_hw_set_video_bus(state
);
1078 s5k5baf_hw_set_cis(state
);
1079 s5k5baf_hw_set_ccm(state
);
1081 ret
= s5k5baf_clear_error(state
);
1085 s5k5baf_power_off(state
);
1090 mutex_unlock(&state
->lock
);
1093 ret
= v4l2_ctrl_handler_setup(&state
->ctrls
.handler
);
1098 static void s5k5baf_hw_set_stream(struct s5k5baf
*state
, int enable
)
1100 s5k5baf_write_seq(state
, REG_G_ENABLE_PREV
, enable
, 1);
1103 static int s5k5baf_s_stream(struct v4l2_subdev
*sd
, int on
)
1105 struct s5k5baf
*state
= to_s5k5baf(sd
);
1108 mutex_lock(&state
->lock
);
1110 if (state
->streaming
== !!on
) {
1116 s5k5baf_hw_set_config(state
);
1117 ret
= s5k5baf_hw_set_crop_rects(state
);
1120 s5k5baf_hw_set_stream(state
, 1);
1121 s5k5baf_i2c_write(state
, 0xb0cc, 0x000b);
1123 s5k5baf_hw_set_stream(state
, 0);
1125 ret
= s5k5baf_clear_error(state
);
1127 state
->streaming
= !state
->streaming
;
1130 mutex_unlock(&state
->lock
);
1135 static int s5k5baf_g_frame_interval(struct v4l2_subdev
*sd
,
1136 struct v4l2_subdev_frame_interval
*fi
)
1138 struct s5k5baf
*state
= to_s5k5baf(sd
);
1140 mutex_lock(&state
->lock
);
1141 fi
->interval
.numerator
= state
->fiv
;
1142 fi
->interval
.denominator
= 10000;
1143 mutex_unlock(&state
->lock
);
1148 static void s5k5baf_set_frame_interval(struct s5k5baf
*state
,
1149 struct v4l2_subdev_frame_interval
*fi
)
1151 struct v4l2_fract
*i
= &fi
->interval
;
1153 if (fi
->interval
.denominator
== 0)
1154 state
->req_fiv
= S5K5BAF_MAX_FR_TIME
;
1156 state
->req_fiv
= clamp_t(u32
,
1157 i
->numerator
* 10000 / i
->denominator
,
1158 S5K5BAF_MIN_FR_TIME
,
1159 S5K5BAF_MAX_FR_TIME
);
1161 state
->fiv
= state
->req_fiv
;
1162 if (state
->apply_cfg
) {
1163 s5k5baf_hw_set_fiv(state
, state
->req_fiv
);
1164 s5k5baf_hw_validate_cfg(state
);
1166 *i
= (struct v4l2_fract
){ state
->fiv
, 10000 };
1167 if (state
->fiv
== state
->req_fiv
)
1168 v4l2_info(&state
->sd
, "frame interval changed to %d00us\n",
1172 static int s5k5baf_s_frame_interval(struct v4l2_subdev
*sd
,
1173 struct v4l2_subdev_frame_interval
*fi
)
1175 struct s5k5baf
*state
= to_s5k5baf(sd
);
1177 mutex_lock(&state
->lock
);
1178 s5k5baf_set_frame_interval(state
, fi
);
1179 mutex_unlock(&state
->lock
);
1184 * V4L2 subdev pad level and video operations
1186 static int s5k5baf_enum_frame_interval(struct v4l2_subdev
*sd
,
1187 struct v4l2_subdev_pad_config
*cfg
,
1188 struct v4l2_subdev_frame_interval_enum
*fie
)
1190 if (fie
->index
> S5K5BAF_MAX_FR_TIME
- S5K5BAF_MIN_FR_TIME
||
1191 fie
->pad
!= PAD_CIS
)
1194 v4l_bound_align_image(&fie
->width
, S5K5BAF_WIN_WIDTH_MIN
,
1195 S5K5BAF_CIS_WIDTH
, 1,
1196 &fie
->height
, S5K5BAF_WIN_HEIGHT_MIN
,
1197 S5K5BAF_CIS_HEIGHT
, 1, 0);
1199 fie
->interval
.numerator
= S5K5BAF_MIN_FR_TIME
+ fie
->index
;
1200 fie
->interval
.denominator
= 10000;
1205 static int s5k5baf_enum_mbus_code(struct v4l2_subdev
*sd
,
1206 struct v4l2_subdev_pad_config
*cfg
,
1207 struct v4l2_subdev_mbus_code_enum
*code
)
1209 if (code
->pad
== PAD_CIS
) {
1210 if (code
->index
> 0)
1212 code
->code
= MEDIA_BUS_FMT_FIXED
;
1216 if (code
->index
>= ARRAY_SIZE(s5k5baf_formats
))
1219 code
->code
= s5k5baf_formats
[code
->index
].code
;
1223 static int s5k5baf_enum_frame_size(struct v4l2_subdev
*sd
,
1224 struct v4l2_subdev_pad_config
*cfg
,
1225 struct v4l2_subdev_frame_size_enum
*fse
)
1232 if (fse
->pad
== PAD_CIS
) {
1233 fse
->code
= MEDIA_BUS_FMT_FIXED
;
1234 fse
->min_width
= S5K5BAF_CIS_WIDTH
;
1235 fse
->max_width
= S5K5BAF_CIS_WIDTH
;
1236 fse
->min_height
= S5K5BAF_CIS_HEIGHT
;
1237 fse
->max_height
= S5K5BAF_CIS_HEIGHT
;
1241 i
= ARRAY_SIZE(s5k5baf_formats
);
1243 if (fse
->code
== s5k5baf_formats
[i
].code
)
1245 fse
->code
= s5k5baf_formats
[i
].code
;
1246 fse
->min_width
= S5K5BAF_WIN_WIDTH_MIN
;
1247 fse
->max_width
= S5K5BAF_CIS_WIDTH
;
1248 fse
->max_height
= S5K5BAF_WIN_HEIGHT_MIN
;
1249 fse
->min_height
= S5K5BAF_CIS_HEIGHT
;
1254 static void s5k5baf_try_cis_format(struct v4l2_mbus_framefmt
*mf
)
1256 mf
->width
= S5K5BAF_CIS_WIDTH
;
1257 mf
->height
= S5K5BAF_CIS_HEIGHT
;
1258 mf
->code
= MEDIA_BUS_FMT_FIXED
;
1259 mf
->colorspace
= V4L2_COLORSPACE_JPEG
;
1260 mf
->field
= V4L2_FIELD_NONE
;
1263 static int s5k5baf_try_isp_format(struct v4l2_mbus_framefmt
*mf
)
1267 v4l_bound_align_image(&mf
->width
, S5K5BAF_WIN_WIDTH_MIN
,
1268 S5K5BAF_CIS_WIDTH
, 1,
1269 &mf
->height
, S5K5BAF_WIN_HEIGHT_MIN
,
1270 S5K5BAF_CIS_HEIGHT
, 1, 0);
1272 pixfmt
= s5k5baf_find_pixfmt(mf
);
1274 mf
->colorspace
= s5k5baf_formats
[pixfmt
].colorspace
;
1275 mf
->code
= s5k5baf_formats
[pixfmt
].code
;
1276 mf
->field
= V4L2_FIELD_NONE
;
1281 static int s5k5baf_get_fmt(struct v4l2_subdev
*sd
, struct v4l2_subdev_pad_config
*cfg
,
1282 struct v4l2_subdev_format
*fmt
)
1284 struct s5k5baf
*state
= to_s5k5baf(sd
);
1285 const struct s5k5baf_pixfmt
*pixfmt
;
1286 struct v4l2_mbus_framefmt
*mf
;
1288 if (fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1289 mf
= v4l2_subdev_get_try_format(sd
, cfg
, fmt
->pad
);
1295 if (fmt
->pad
== PAD_CIS
) {
1296 s5k5baf_try_cis_format(mf
);
1299 mf
->field
= V4L2_FIELD_NONE
;
1300 mutex_lock(&state
->lock
);
1301 pixfmt
= &s5k5baf_formats
[state
->pixfmt
];
1302 mf
->width
= state
->crop_source
.width
;
1303 mf
->height
= state
->crop_source
.height
;
1304 mf
->code
= pixfmt
->code
;
1305 mf
->colorspace
= pixfmt
->colorspace
;
1306 mutex_unlock(&state
->lock
);
1311 static int s5k5baf_set_fmt(struct v4l2_subdev
*sd
, struct v4l2_subdev_pad_config
*cfg
,
1312 struct v4l2_subdev_format
*fmt
)
1314 struct v4l2_mbus_framefmt
*mf
= &fmt
->format
;
1315 struct s5k5baf
*state
= to_s5k5baf(sd
);
1316 const struct s5k5baf_pixfmt
*pixfmt
;
1319 mf
->field
= V4L2_FIELD_NONE
;
1321 if (fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1322 *v4l2_subdev_get_try_format(sd
, cfg
, fmt
->pad
) = *mf
;
1326 if (fmt
->pad
== PAD_CIS
) {
1327 s5k5baf_try_cis_format(mf
);
1331 mutex_lock(&state
->lock
);
1333 if (state
->streaming
) {
1334 mutex_unlock(&state
->lock
);
1338 state
->pixfmt
= s5k5baf_try_isp_format(mf
);
1339 pixfmt
= &s5k5baf_formats
[state
->pixfmt
];
1340 mf
->code
= pixfmt
->code
;
1341 mf
->colorspace
= pixfmt
->colorspace
;
1342 mf
->width
= state
->crop_source
.width
;
1343 mf
->height
= state
->crop_source
.height
;
1345 mutex_unlock(&state
->lock
);
1349 enum selection_rect
{ R_CIS
, R_CROP_SINK
, R_COMPOSE
, R_CROP_SOURCE
, R_INVALID
};
1351 static enum selection_rect
s5k5baf_get_sel_rect(u32 pad
, u32 target
)
1354 case V4L2_SEL_TGT_CROP_BOUNDS
:
1355 return pad
? R_COMPOSE
: R_CIS
;
1356 case V4L2_SEL_TGT_CROP
:
1357 return pad
? R_CROP_SOURCE
: R_CROP_SINK
;
1358 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
1359 return pad
? R_INVALID
: R_CROP_SINK
;
1360 case V4L2_SEL_TGT_COMPOSE
:
1361 return pad
? R_INVALID
: R_COMPOSE
;
1367 static int s5k5baf_is_bound_target(u32 target
)
1369 return target
== V4L2_SEL_TGT_CROP_BOUNDS
||
1370 target
== V4L2_SEL_TGT_COMPOSE_BOUNDS
;
1373 static int s5k5baf_get_selection(struct v4l2_subdev
*sd
,
1374 struct v4l2_subdev_pad_config
*cfg
,
1375 struct v4l2_subdev_selection
*sel
)
1377 enum selection_rect rtype
;
1378 struct s5k5baf
*state
= to_s5k5baf(sd
);
1380 rtype
= s5k5baf_get_sel_rect(sel
->pad
, sel
->target
);
1386 sel
->r
= s5k5baf_cis_rect
;
1392 if (sel
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1393 if (rtype
== R_COMPOSE
)
1394 sel
->r
= *v4l2_subdev_get_try_compose(sd
, cfg
, sel
->pad
);
1396 sel
->r
= *v4l2_subdev_get_try_crop(sd
, cfg
, sel
->pad
);
1400 mutex_lock(&state
->lock
);
1403 sel
->r
= state
->crop_sink
;
1406 sel
->r
= state
->compose
;
1409 sel
->r
= state
->crop_source
;
1414 if (s5k5baf_is_bound_target(sel
->target
)) {
1418 mutex_unlock(&state
->lock
);
1423 /* bounds range [start, start+len) to [0, max) and aligns to 2 */
1424 static void s5k5baf_bound_range(u32
*start
, u32
*len
, u32 max
)
1428 if (*start
+ *len
> max
)
1429 *start
= max
- *len
;
1432 if (*len
< S5K5BAF_WIN_WIDTH_MIN
)
1433 *len
= S5K5BAF_WIN_WIDTH_MIN
;
1436 static void s5k5baf_bound_rect(struct v4l2_rect
*r
, u32 width
, u32 height
)
1438 s5k5baf_bound_range(&r
->left
, &r
->width
, width
);
1439 s5k5baf_bound_range(&r
->top
, &r
->height
, height
);
1442 static void s5k5baf_set_rect_and_adjust(struct v4l2_rect
**rects
,
1443 enum selection_rect first
,
1444 struct v4l2_rect
*v
)
1446 struct v4l2_rect
*r
, *br
;
1447 enum selection_rect i
= first
;
1453 s5k5baf_bound_rect(r
, br
->width
, br
->height
);
1454 } while (++i
!= R_INVALID
);
1458 static bool s5k5baf_cmp_rect(const struct v4l2_rect
*r1
,
1459 const struct v4l2_rect
*r2
)
1461 return !memcmp(r1
, r2
, sizeof(*r1
));
1464 static int s5k5baf_set_selection(struct v4l2_subdev
*sd
,
1465 struct v4l2_subdev_pad_config
*cfg
,
1466 struct v4l2_subdev_selection
*sel
)
1468 static enum selection_rect rtype
;
1469 struct s5k5baf
*state
= to_s5k5baf(sd
);
1470 struct v4l2_rect
**rects
;
1473 rtype
= s5k5baf_get_sel_rect(sel
->pad
, sel
->target
);
1474 if (rtype
== R_INVALID
|| s5k5baf_is_bound_target(sel
->target
))
1477 /* allow only scaling on compose */
1478 if (rtype
== R_COMPOSE
) {
1483 if (sel
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1484 rects
= (struct v4l2_rect
* []) {
1486 v4l2_subdev_get_try_crop(sd
, cfg
, PAD_CIS
),
1487 v4l2_subdev_get_try_compose(sd
, cfg
, PAD_CIS
),
1488 v4l2_subdev_get_try_crop(sd
, cfg
, PAD_OUT
)
1490 s5k5baf_set_rect_and_adjust(rects
, rtype
, &sel
->r
);
1494 rects
= (struct v4l2_rect
* []) {
1500 mutex_lock(&state
->lock
);
1501 if (state
->streaming
) {
1502 /* adjust sel->r to avoid output resolution change */
1503 if (rtype
< R_CROP_SOURCE
) {
1504 if (sel
->r
.width
< state
->crop_source
.width
)
1505 sel
->r
.width
= state
->crop_source
.width
;
1506 if (sel
->r
.height
< state
->crop_source
.height
)
1507 sel
->r
.height
= state
->crop_source
.height
;
1509 sel
->r
.width
= state
->crop_source
.width
;
1510 sel
->r
.height
= state
->crop_source
.height
;
1513 s5k5baf_set_rect_and_adjust(rects
, rtype
, &sel
->r
);
1514 if (!s5k5baf_cmp_rect(&state
->crop_sink
, &s5k5baf_cis_rect
) ||
1515 !s5k5baf_cmp_rect(&state
->compose
, &s5k5baf_cis_rect
))
1516 state
->apply_crop
= 1;
1517 if (state
->streaming
)
1518 ret
= s5k5baf_hw_set_crop_rects(state
);
1519 mutex_unlock(&state
->lock
);
1524 static const struct v4l2_subdev_pad_ops s5k5baf_cis_pad_ops
= {
1525 .enum_mbus_code
= s5k5baf_enum_mbus_code
,
1526 .enum_frame_size
= s5k5baf_enum_frame_size
,
1527 .get_fmt
= s5k5baf_get_fmt
,
1528 .set_fmt
= s5k5baf_set_fmt
,
1531 static const struct v4l2_subdev_pad_ops s5k5baf_pad_ops
= {
1532 .enum_mbus_code
= s5k5baf_enum_mbus_code
,
1533 .enum_frame_size
= s5k5baf_enum_frame_size
,
1534 .enum_frame_interval
= s5k5baf_enum_frame_interval
,
1535 .get_fmt
= s5k5baf_get_fmt
,
1536 .set_fmt
= s5k5baf_set_fmt
,
1537 .get_selection
= s5k5baf_get_selection
,
1538 .set_selection
= s5k5baf_set_selection
,
1541 static const struct v4l2_subdev_video_ops s5k5baf_video_ops
= {
1542 .g_frame_interval
= s5k5baf_g_frame_interval
,
1543 .s_frame_interval
= s5k5baf_s_frame_interval
,
1544 .s_stream
= s5k5baf_s_stream
,
1548 * V4L2 subdev controls
1551 static int s5k5baf_s_ctrl(struct v4l2_ctrl
*ctrl
)
1553 struct v4l2_subdev
*sd
= ctrl_to_sd(ctrl
);
1554 struct s5k5baf
*state
= to_s5k5baf(sd
);
1557 v4l2_dbg(1, debug
, sd
, "ctrl: %s, value: %d\n", ctrl
->name
, ctrl
->val
);
1559 mutex_lock(&state
->lock
);
1561 if (state
->power
== 0)
1565 case V4L2_CID_AUTO_WHITE_BALANCE
:
1566 s5k5baf_hw_set_awb(state
, ctrl
->val
);
1569 case V4L2_CID_BRIGHTNESS
:
1570 s5k5baf_write(state
, REG_USER_BRIGHTNESS
, ctrl
->val
);
1573 case V4L2_CID_COLORFX
:
1574 s5k5baf_hw_set_colorfx(state
, ctrl
->val
);
1577 case V4L2_CID_CONTRAST
:
1578 s5k5baf_write(state
, REG_USER_CONTRAST
, ctrl
->val
);
1581 case V4L2_CID_EXPOSURE_AUTO
:
1582 s5k5baf_hw_set_auto_exposure(state
, ctrl
->val
);
1585 case V4L2_CID_HFLIP
:
1586 s5k5baf_hw_set_mirror(state
);
1589 case V4L2_CID_POWER_LINE_FREQUENCY
:
1590 s5k5baf_hw_set_anti_flicker(state
, ctrl
->val
);
1593 case V4L2_CID_SATURATION
:
1594 s5k5baf_write(state
, REG_USER_SATURATION
, ctrl
->val
);
1597 case V4L2_CID_SHARPNESS
:
1598 s5k5baf_write(state
, REG_USER_SHARPBLUR
, ctrl
->val
);
1601 case V4L2_CID_WHITE_BALANCE_TEMPERATURE
:
1602 s5k5baf_write(state
, REG_P_COLORTEMP(0), ctrl
->val
);
1603 if (state
->apply_cfg
)
1604 s5k5baf_hw_sync_cfg(state
);
1607 case V4L2_CID_TEST_PATTERN
:
1608 s5k5baf_hw_set_test_pattern(state
, ctrl
->val
);
1612 ret
= s5k5baf_clear_error(state
);
1613 mutex_unlock(&state
->lock
);
1617 static const struct v4l2_ctrl_ops s5k5baf_ctrl_ops
= {
1618 .s_ctrl
= s5k5baf_s_ctrl
,
1621 static const char * const s5k5baf_test_pattern_menu
[] = {
1631 static int s5k5baf_initialize_ctrls(struct s5k5baf
*state
)
1633 const struct v4l2_ctrl_ops
*ops
= &s5k5baf_ctrl_ops
;
1634 struct s5k5baf_ctrls
*ctrls
= &state
->ctrls
;
1635 struct v4l2_ctrl_handler
*hdl
= &ctrls
->handler
;
1638 ret
= v4l2_ctrl_handler_init(hdl
, 16);
1640 v4l2_err(&state
->sd
, "cannot init ctrl handler (%d)\n", ret
);
1644 /* Auto white balance cluster */
1645 ctrls
->awb
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_AUTO_WHITE_BALANCE
,
1647 ctrls
->gain_red
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_RED_BALANCE
,
1648 0, 255, 1, S5K5BAF_GAIN_RED_DEF
);
1649 ctrls
->gain_blue
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_BLUE_BALANCE
,
1650 0, 255, 1, S5K5BAF_GAIN_BLUE_DEF
);
1651 v4l2_ctrl_auto_cluster(3, &ctrls
->awb
, 0, false);
1653 ctrls
->hflip
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_HFLIP
, 0, 1, 1, 0);
1654 ctrls
->vflip
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_VFLIP
, 0, 1, 1, 0);
1655 v4l2_ctrl_cluster(2, &ctrls
->hflip
);
1657 ctrls
->auto_exp
= v4l2_ctrl_new_std_menu(hdl
, ops
,
1658 V4L2_CID_EXPOSURE_AUTO
,
1659 V4L2_EXPOSURE_MANUAL
, 0, V4L2_EXPOSURE_AUTO
);
1660 /* Exposure time: x 1 us */
1661 ctrls
->exposure
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_EXPOSURE
,
1662 0, 6000000U, 1, 100000U);
1663 /* Total gain: 256 <=> 1x */
1664 ctrls
->gain
= v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_GAIN
,
1666 v4l2_ctrl_auto_cluster(3, &ctrls
->auto_exp
, 0, false);
1668 v4l2_ctrl_new_std_menu(hdl
, ops
, V4L2_CID_POWER_LINE_FREQUENCY
,
1669 V4L2_CID_POWER_LINE_FREQUENCY_AUTO
, 0,
1670 V4L2_CID_POWER_LINE_FREQUENCY_AUTO
);
1672 v4l2_ctrl_new_std_menu(hdl
, ops
, V4L2_CID_COLORFX
,
1673 V4L2_COLORFX_SKY_BLUE
, ~0x6f, V4L2_COLORFX_NONE
);
1675 v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_WHITE_BALANCE_TEMPERATURE
,
1678 v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_SATURATION
, -127, 127, 1, 0);
1679 v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_BRIGHTNESS
, -127, 127, 1, 0);
1680 v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_CONTRAST
, -127, 127, 1, 0);
1681 v4l2_ctrl_new_std(hdl
, ops
, V4L2_CID_SHARPNESS
, -127, 127, 1, 0);
1683 v4l2_ctrl_new_std_menu_items(hdl
, ops
, V4L2_CID_TEST_PATTERN
,
1684 ARRAY_SIZE(s5k5baf_test_pattern_menu
) - 1,
1685 0, 0, s5k5baf_test_pattern_menu
);
1688 v4l2_err(&state
->sd
, "error creating controls (%d)\n",
1691 v4l2_ctrl_handler_free(hdl
);
1695 state
->sd
.ctrl_handler
= hdl
;
1700 * V4L2 subdev internal operations
1702 static int s5k5baf_open(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
1704 struct v4l2_mbus_framefmt
*mf
;
1706 mf
= v4l2_subdev_get_try_format(sd
, fh
->pad
, PAD_CIS
);
1707 s5k5baf_try_cis_format(mf
);
1709 if (s5k5baf_is_cis_subdev(sd
))
1712 mf
= v4l2_subdev_get_try_format(sd
, fh
->pad
, PAD_OUT
);
1713 mf
->colorspace
= s5k5baf_formats
[0].colorspace
;
1714 mf
->code
= s5k5baf_formats
[0].code
;
1715 mf
->width
= s5k5baf_cis_rect
.width
;
1716 mf
->height
= s5k5baf_cis_rect
.height
;
1717 mf
->field
= V4L2_FIELD_NONE
;
1719 *v4l2_subdev_get_try_crop(sd
, fh
->pad
, PAD_CIS
) = s5k5baf_cis_rect
;
1720 *v4l2_subdev_get_try_compose(sd
, fh
->pad
, PAD_CIS
) = s5k5baf_cis_rect
;
1721 *v4l2_subdev_get_try_crop(sd
, fh
->pad
, PAD_OUT
) = s5k5baf_cis_rect
;
1726 static int s5k5baf_check_fw_revision(struct s5k5baf
*state
)
1728 u16 api_ver
= 0, fw_rev
= 0, s_id
= 0;
1731 api_ver
= s5k5baf_read(state
, REG_FW_APIVER
);
1732 fw_rev
= s5k5baf_read(state
, REG_FW_REVISION
) & 0xff;
1733 s_id
= s5k5baf_read(state
, REG_FW_SENSOR_ID
);
1734 ret
= s5k5baf_clear_error(state
);
1738 v4l2_info(&state
->sd
, "FW API=%#x, revision=%#x sensor_id=%#x\n",
1739 api_ver
, fw_rev
, s_id
);
1741 if (api_ver
!= S5K5BAF_FW_APIVER
) {
1742 v4l2_err(&state
->sd
, "FW API version not supported\n");
1749 static int s5k5baf_registered(struct v4l2_subdev
*sd
)
1751 struct s5k5baf
*state
= to_s5k5baf(sd
);
1754 ret
= v4l2_device_register_subdev(sd
->v4l2_dev
, &state
->cis_sd
);
1756 v4l2_err(sd
, "failed to register subdev %s\n",
1757 state
->cis_sd
.name
);
1759 ret
= media_create_pad_link(&state
->cis_sd
.entity
, PAD_CIS
,
1760 &state
->sd
.entity
, PAD_CIS
,
1761 MEDIA_LNK_FL_IMMUTABLE
|
1762 MEDIA_LNK_FL_ENABLED
);
1766 static void s5k5baf_unregistered(struct v4l2_subdev
*sd
)
1768 struct s5k5baf
*state
= to_s5k5baf(sd
);
1769 v4l2_device_unregister_subdev(&state
->cis_sd
);
1772 static const struct v4l2_subdev_ops s5k5baf_cis_subdev_ops
= {
1773 .pad
= &s5k5baf_cis_pad_ops
,
1776 static const struct v4l2_subdev_internal_ops s5k5baf_cis_subdev_internal_ops
= {
1777 .open
= s5k5baf_open
,
1780 static const struct v4l2_subdev_internal_ops s5k5baf_subdev_internal_ops
= {
1781 .registered
= s5k5baf_registered
,
1782 .unregistered
= s5k5baf_unregistered
,
1783 .open
= s5k5baf_open
,
1786 static const struct v4l2_subdev_core_ops s5k5baf_core_ops
= {
1787 .s_power
= s5k5baf_set_power
,
1788 .log_status
= v4l2_ctrl_subdev_log_status
,
1791 static const struct v4l2_subdev_ops s5k5baf_subdev_ops
= {
1792 .core
= &s5k5baf_core_ops
,
1793 .pad
= &s5k5baf_pad_ops
,
1794 .video
= &s5k5baf_video_ops
,
1797 static int s5k5baf_configure_gpios(struct s5k5baf
*state
)
1799 static const char * const name
[] = { "S5K5BAF_STBY", "S5K5BAF_RST" };
1800 struct i2c_client
*c
= v4l2_get_subdevdata(&state
->sd
);
1801 struct s5k5baf_gpio
*g
= state
->gpios
;
1804 for (i
= 0; i
< NUM_GPIOS
; ++i
) {
1805 int flags
= GPIOF_DIR_OUT
;
1807 flags
|= GPIOF_INIT_HIGH
;
1808 ret
= devm_gpio_request_one(&c
->dev
, g
[i
].gpio
, flags
, name
[i
]);
1810 v4l2_err(c
, "failed to request gpio %s\n", name
[i
]);
1817 static int s5k5baf_parse_gpios(struct s5k5baf_gpio
*gpios
, struct device
*dev
)
1819 static const char * const names
[] = {
1823 struct device_node
*node
= dev
->of_node
;
1824 enum of_gpio_flags flags
;
1827 for (i
= 0; i
< NUM_GPIOS
; ++i
) {
1828 ret
= of_get_named_gpio_flags(node
, names
[i
], 0, &flags
);
1830 dev_err(dev
, "no %s GPIO pin provided\n", names
[i
]);
1833 gpios
[i
].gpio
= ret
;
1834 gpios
[i
].level
= !(flags
& OF_GPIO_ACTIVE_LOW
);
1840 static int s5k5baf_parse_device_node(struct s5k5baf
*state
, struct device
*dev
)
1842 struct device_node
*node
= dev
->of_node
;
1843 struct device_node
*node_ep
;
1844 struct v4l2_fwnode_endpoint ep
;
1848 dev_err(dev
, "no device-tree node provided\n");
1852 ret
= of_property_read_u32(node
, "clock-frequency",
1853 &state
->mclk_frequency
);
1855 state
->mclk_frequency
= S5K5BAF_DEFAULT_MCLK_FREQ
;
1856 dev_info(dev
, "using default %u Hz clock frequency\n",
1857 state
->mclk_frequency
);
1860 ret
= s5k5baf_parse_gpios(state
->gpios
, dev
);
1864 node_ep
= of_graph_get_next_endpoint(node
, NULL
);
1866 dev_err(dev
, "no endpoint defined at node %pOF\n", node
);
1870 ret
= v4l2_fwnode_endpoint_parse(of_fwnode_handle(node_ep
), &ep
);
1871 of_node_put(node_ep
);
1875 state
->bus_type
= ep
.bus_type
;
1877 switch (state
->bus_type
) {
1878 case V4L2_MBUS_CSI2
:
1879 state
->nlanes
= ep
.bus
.mipi_csi2
.num_data_lanes
;
1881 case V4L2_MBUS_PARALLEL
:
1884 dev_err(dev
, "unsupported bus in endpoint defined at node %pOF\n",
1892 static int s5k5baf_configure_subdevs(struct s5k5baf
*state
,
1893 struct i2c_client
*c
)
1895 struct v4l2_subdev
*sd
;
1898 sd
= &state
->cis_sd
;
1899 v4l2_subdev_init(sd
, &s5k5baf_cis_subdev_ops
);
1900 sd
->owner
= THIS_MODULE
;
1901 v4l2_set_subdevdata(sd
, state
);
1902 snprintf(sd
->name
, sizeof(sd
->name
), "S5K5BAF-CIS %d-%04x",
1903 i2c_adapter_id(c
->adapter
), c
->addr
);
1905 sd
->internal_ops
= &s5k5baf_cis_subdev_internal_ops
;
1906 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
1908 state
->cis_pad
.flags
= MEDIA_PAD_FL_SOURCE
;
1909 sd
->entity
.function
= MEDIA_ENT_F_CAM_SENSOR
;
1910 ret
= media_entity_pads_init(&sd
->entity
, NUM_CIS_PADS
, &state
->cis_pad
);
1915 v4l2_i2c_subdev_init(sd
, c
, &s5k5baf_subdev_ops
);
1916 snprintf(sd
->name
, sizeof(sd
->name
), "S5K5BAF-ISP %d-%04x",
1917 i2c_adapter_id(c
->adapter
), c
->addr
);
1919 sd
->internal_ops
= &s5k5baf_subdev_internal_ops
;
1920 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
1922 state
->pads
[PAD_CIS
].flags
= MEDIA_PAD_FL_SINK
;
1923 state
->pads
[PAD_OUT
].flags
= MEDIA_PAD_FL_SOURCE
;
1924 sd
->entity
.function
= MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN
;
1925 ret
= media_entity_pads_init(&sd
->entity
, NUM_ISP_PADS
, state
->pads
);
1930 media_entity_cleanup(&state
->cis_sd
.entity
);
1932 dev_err(&c
->dev
, "cannot init media entity %s\n", sd
->name
);
1936 static int s5k5baf_configure_regulators(struct s5k5baf
*state
)
1938 struct i2c_client
*c
= v4l2_get_subdevdata(&state
->sd
);
1942 for (i
= 0; i
< S5K5BAF_NUM_SUPPLIES
; i
++)
1943 state
->supplies
[i
].supply
= s5k5baf_supply_names
[i
];
1945 ret
= devm_regulator_bulk_get(&c
->dev
, S5K5BAF_NUM_SUPPLIES
,
1948 v4l2_err(c
, "failed to get regulators\n");
1952 static int s5k5baf_probe(struct i2c_client
*c
,
1953 const struct i2c_device_id
*id
)
1955 struct s5k5baf
*state
;
1958 state
= devm_kzalloc(&c
->dev
, sizeof(*state
), GFP_KERNEL
);
1962 mutex_init(&state
->lock
);
1963 state
->crop_sink
= s5k5baf_cis_rect
;
1964 state
->compose
= s5k5baf_cis_rect
;
1965 state
->crop_source
= s5k5baf_cis_rect
;
1967 ret
= s5k5baf_parse_device_node(state
, &c
->dev
);
1971 ret
= s5k5baf_configure_subdevs(state
, c
);
1975 ret
= s5k5baf_configure_gpios(state
);
1979 ret
= s5k5baf_configure_regulators(state
);
1983 state
->clock
= devm_clk_get(state
->sd
.dev
, S5K5BAF_CLK_NAME
);
1984 if (IS_ERR(state
->clock
)) {
1985 ret
= -EPROBE_DEFER
;
1989 ret
= s5k5baf_power_on(state
);
1991 ret
= -EPROBE_DEFER
;
1994 s5k5baf_hw_init(state
);
1995 ret
= s5k5baf_check_fw_revision(state
);
1997 s5k5baf_power_off(state
);
2001 ret
= s5k5baf_initialize_ctrls(state
);
2005 ret
= v4l2_async_register_subdev(&state
->sd
);
2012 v4l2_ctrl_handler_free(state
->sd
.ctrl_handler
);
2014 media_entity_cleanup(&state
->sd
.entity
);
2015 media_entity_cleanup(&state
->cis_sd
.entity
);
2019 static int s5k5baf_remove(struct i2c_client
*c
)
2021 struct v4l2_subdev
*sd
= i2c_get_clientdata(c
);
2022 struct s5k5baf
*state
= to_s5k5baf(sd
);
2024 v4l2_async_unregister_subdev(sd
);
2025 v4l2_ctrl_handler_free(sd
->ctrl_handler
);
2026 media_entity_cleanup(&sd
->entity
);
2028 sd
= &state
->cis_sd
;
2029 v4l2_device_unregister_subdev(sd
);
2030 media_entity_cleanup(&sd
->entity
);
2035 static const struct i2c_device_id s5k5baf_id
[] = {
2036 { S5K5BAF_DRIVER_NAME
, 0 },
2039 MODULE_DEVICE_TABLE(i2c
, s5k5baf_id
);
2041 static const struct of_device_id s5k5baf_of_match
[] = {
2042 { .compatible
= "samsung,s5k5baf" },
2045 MODULE_DEVICE_TABLE(of
, s5k5baf_of_match
);
2047 static struct i2c_driver s5k5baf_i2c_driver
= {
2049 .of_match_table
= s5k5baf_of_match
,
2050 .name
= S5K5BAF_DRIVER_NAME
2052 .probe
= s5k5baf_probe
,
2053 .remove
= s5k5baf_remove
,
2054 .id_table
= s5k5baf_id
,
2057 module_i2c_driver(s5k5baf_i2c_driver
);
2059 MODULE_DESCRIPTION("Samsung S5K5BAF(X) UXGA camera driver");
2060 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
2061 MODULE_LICENSE("GPL v2");