V4L/DVB (5474): SN9C1xx driver updates
[linux-2.6.git] / drivers / media / video / sn9c102 / sn9c102_ov7660.c
1 /***************************************************************************
2  * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera      *
3  * Controllers                                                             *
4  *                                                                         *
5  * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
6  *                                                                         *
7  * This program is free software; you can redistribute it and/or modify    *
8  * it under the terms of the GNU General Public License as published by    *
9  * the Free Software Foundation; either version 2 of the License, or       *
10  * (at your option) any later version.                                     *
11  *                                                                         *
12  * This program is distributed in the hope that it will be useful,         *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15  * GNU General Public License for more details.                            *
16  *                                                                         *
17  * You should have received a copy of the GNU General Public License       *
18  * along with this program; if not, write to the Free Software             *
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
20  ***************************************************************************/
21
22 #include "sn9c102_sensor.h"
23
24
25 static int ov7660_init(struct sn9c102_device* cam)
26 {
27         int err = 0;
28
29         err += sn9c102_write_reg(cam, 0x40, 0x02);
30         err += sn9c102_write_reg(cam, 0x00, 0x03);
31         err += sn9c102_write_reg(cam, 0x1a, 0x04);
32         err += sn9c102_write_reg(cam, 0x03, 0x10);
33         err += sn9c102_write_reg(cam, 0x08, 0x14);
34         err += sn9c102_write_reg(cam, 0x20, 0x17);
35         err += sn9c102_write_reg(cam, 0x8b, 0x18);
36         err += sn9c102_write_reg(cam, 0x00, 0x19);
37         err += sn9c102_write_reg(cam, 0x1d, 0x1a);
38         err += sn9c102_write_reg(cam, 0x10, 0x1b);
39         err += sn9c102_write_reg(cam, 0x02, 0x1c);
40         err += sn9c102_write_reg(cam, 0x03, 0x1d);
41         err += sn9c102_write_reg(cam, 0x0f, 0x1e);
42         err += sn9c102_write_reg(cam, 0x0c, 0x1f);
43         err += sn9c102_write_reg(cam, 0x00, 0x20);
44         err += sn9c102_write_reg(cam, 0x29, 0x21);
45         err += sn9c102_write_reg(cam, 0x40, 0x22);
46         err += sn9c102_write_reg(cam, 0x54, 0x23);
47         err += sn9c102_write_reg(cam, 0x66, 0x24);
48         err += sn9c102_write_reg(cam, 0x76, 0x25);
49         err += sn9c102_write_reg(cam, 0x85, 0x26);
50         err += sn9c102_write_reg(cam, 0x94, 0x27);
51         err += sn9c102_write_reg(cam, 0xa1, 0x28);
52         err += sn9c102_write_reg(cam, 0xae, 0x29);
53         err += sn9c102_write_reg(cam, 0xbb, 0x2a);
54         err += sn9c102_write_reg(cam, 0xc7, 0x2b);
55         err += sn9c102_write_reg(cam, 0xd3, 0x2c);
56         err += sn9c102_write_reg(cam, 0xde, 0x2d);
57         err += sn9c102_write_reg(cam, 0xea, 0x2e);
58         err += sn9c102_write_reg(cam, 0xf4, 0x2f);
59         err += sn9c102_write_reg(cam, 0xff, 0x30);
60         err += sn9c102_write_reg(cam, 0x00, 0x3F);
61         err += sn9c102_write_reg(cam, 0xC7, 0x40);
62         err += sn9c102_write_reg(cam, 0x01, 0x41);
63         err += sn9c102_write_reg(cam, 0x44, 0x42);
64         err += sn9c102_write_reg(cam, 0x00, 0x43);
65         err += sn9c102_write_reg(cam, 0x44, 0x44);
66         err += sn9c102_write_reg(cam, 0x00, 0x45);
67         err += sn9c102_write_reg(cam, 0x44, 0x46);
68         err += sn9c102_write_reg(cam, 0x00, 0x47);
69         err += sn9c102_write_reg(cam, 0xC7, 0x48);
70         err += sn9c102_write_reg(cam, 0x01, 0x49);
71         err += sn9c102_write_reg(cam, 0xC7, 0x4A);
72         err += sn9c102_write_reg(cam, 0x01, 0x4B);
73         err += sn9c102_write_reg(cam, 0xC7, 0x4C);
74         err += sn9c102_write_reg(cam, 0x01, 0x4D);
75         err += sn9c102_write_reg(cam, 0x44, 0x4E);
76         err += sn9c102_write_reg(cam, 0x00, 0x4F);
77         err += sn9c102_write_reg(cam, 0x44, 0x50);
78         err += sn9c102_write_reg(cam, 0x00, 0x51);
79         err += sn9c102_write_reg(cam, 0x44, 0x52);
80         err += sn9c102_write_reg(cam, 0x00, 0x53);
81         err += sn9c102_write_reg(cam, 0xC7, 0x54);
82         err += sn9c102_write_reg(cam, 0x01, 0x55);
83         err += sn9c102_write_reg(cam, 0xC7, 0x56);
84         err += sn9c102_write_reg(cam, 0x01, 0x57);
85         err += sn9c102_write_reg(cam, 0xC7, 0x58);
86         err += sn9c102_write_reg(cam, 0x01, 0x59);
87         err += sn9c102_write_reg(cam, 0x44, 0x5A);
88         err += sn9c102_write_reg(cam, 0x00, 0x5B);
89         err += sn9c102_write_reg(cam, 0x44, 0x5C);
90         err += sn9c102_write_reg(cam, 0x00, 0x5D);
91         err += sn9c102_write_reg(cam, 0x44, 0x5E);
92         err += sn9c102_write_reg(cam, 0x00, 0x5F);
93         err += sn9c102_write_reg(cam, 0xC7, 0x60);
94         err += sn9c102_write_reg(cam, 0x01, 0x61);
95         err += sn9c102_write_reg(cam, 0xC7, 0x62);
96         err += sn9c102_write_reg(cam, 0x01, 0x63);
97         err += sn9c102_write_reg(cam, 0xC7, 0x64);
98         err += sn9c102_write_reg(cam, 0x01, 0x65);
99         err += sn9c102_write_reg(cam, 0x44, 0x66);
100         err += sn9c102_write_reg(cam, 0x00, 0x67);
101         err += sn9c102_write_reg(cam, 0x44, 0x68);
102         err += sn9c102_write_reg(cam, 0x00, 0x69);
103         err += sn9c102_write_reg(cam, 0x44, 0x6A);
104         err += sn9c102_write_reg(cam, 0x00, 0x6B);
105         err += sn9c102_write_reg(cam, 0xC7, 0x6C);
106         err += sn9c102_write_reg(cam, 0x01, 0x6D);
107         err += sn9c102_write_reg(cam, 0xC7, 0x6E);
108         err += sn9c102_write_reg(cam, 0x01, 0x6F);
109         err += sn9c102_write_reg(cam, 0xC7, 0x70);
110         err += sn9c102_write_reg(cam, 0x01, 0x71);
111         err += sn9c102_write_reg(cam, 0x44, 0x72);
112         err += sn9c102_write_reg(cam, 0x00, 0x73);
113         err += sn9c102_write_reg(cam, 0x44, 0x74);
114         err += sn9c102_write_reg(cam, 0x00, 0x75);
115         err += sn9c102_write_reg(cam, 0x44, 0x76);
116         err += sn9c102_write_reg(cam, 0x00, 0x77);
117         err += sn9c102_write_reg(cam, 0xC7, 0x78);
118         err += sn9c102_write_reg(cam, 0x01, 0x79);
119         err += sn9c102_write_reg(cam, 0xC7, 0x7A);
120         err += sn9c102_write_reg(cam, 0x01, 0x7B);
121         err += sn9c102_write_reg(cam, 0xC7, 0x7C);
122         err += sn9c102_write_reg(cam, 0x01, 0x7D);
123         err += sn9c102_write_reg(cam, 0x44, 0x7E);
124         err += sn9c102_write_reg(cam, 0x00, 0x7F);
125         err += sn9c102_write_reg(cam, 0x14, 0x84);
126         err += sn9c102_write_reg(cam, 0x00, 0x85);
127         err += sn9c102_write_reg(cam, 0x27, 0x86);
128         err += sn9c102_write_reg(cam, 0x00, 0x87);
129         err += sn9c102_write_reg(cam, 0x07, 0x88);
130         err += sn9c102_write_reg(cam, 0x00, 0x89);
131         err += sn9c102_write_reg(cam, 0xEC, 0x8A);
132         err += sn9c102_write_reg(cam, 0x0f, 0x8B);
133         err += sn9c102_write_reg(cam, 0xD8, 0x8C);
134         err += sn9c102_write_reg(cam, 0x0f, 0x8D);
135         err += sn9c102_write_reg(cam, 0x3D, 0x8E);
136         err += sn9c102_write_reg(cam, 0x00, 0x8F);
137         err += sn9c102_write_reg(cam, 0x3D, 0x90);
138         err += sn9c102_write_reg(cam, 0x00, 0x91);
139         err += sn9c102_write_reg(cam, 0xCD, 0x92);
140         err += sn9c102_write_reg(cam, 0x0f, 0x93);
141         err += sn9c102_write_reg(cam, 0xf7, 0x94);
142         err += sn9c102_write_reg(cam, 0x0f, 0x95);
143         err += sn9c102_write_reg(cam, 0x0C, 0x96);
144         err += sn9c102_write_reg(cam, 0x00, 0x97);
145         err += sn9c102_write_reg(cam, 0x00, 0x98);
146         err += sn9c102_write_reg(cam, 0x66, 0x99);
147         err += sn9c102_write_reg(cam, 0x05, 0x9A);
148         err += sn9c102_write_reg(cam, 0x00, 0x9B);
149         err += sn9c102_write_reg(cam, 0x04, 0x9C);
150         err += sn9c102_write_reg(cam, 0x00, 0x9D);
151         err += sn9c102_write_reg(cam, 0x08, 0x9E);
152         err += sn9c102_write_reg(cam, 0x00, 0x9F);
153         err += sn9c102_write_reg(cam, 0x2D, 0xC0);
154         err += sn9c102_write_reg(cam, 0x2D, 0xC1);
155         err += sn9c102_write_reg(cam, 0x3A, 0xC2);
156         err += sn9c102_write_reg(cam, 0x05, 0xC3);
157         err += sn9c102_write_reg(cam, 0x04, 0xC4);
158         err += sn9c102_write_reg(cam, 0x3F, 0xC5);
159         err += sn9c102_write_reg(cam, 0x00, 0xC6);
160         err += sn9c102_write_reg(cam, 0x00, 0xC7);
161         err += sn9c102_write_reg(cam, 0x50, 0xC8);
162         err += sn9c102_write_reg(cam, 0x3C, 0xC9);
163         err += sn9c102_write_reg(cam, 0x28, 0xCA);
164         err += sn9c102_write_reg(cam, 0xD8, 0xCB);
165         err += sn9c102_write_reg(cam, 0x14, 0xCC);
166         err += sn9c102_write_reg(cam, 0xEC, 0xCD);
167         err += sn9c102_write_reg(cam, 0x32, 0xCE);
168         err += sn9c102_write_reg(cam, 0xDD, 0xCF);
169         err += sn9c102_write_reg(cam, 0x32, 0xD0);
170         err += sn9c102_write_reg(cam, 0xDD, 0xD1);
171         err += sn9c102_write_reg(cam, 0x6A, 0xD2);
172         err += sn9c102_write_reg(cam, 0x50, 0xD3);
173         err += sn9c102_write_reg(cam, 0x00, 0xD4);
174         err += sn9c102_write_reg(cam, 0x00, 0xD5);
175         err += sn9c102_write_reg(cam, 0x00, 0xD6);
176
177         err += sn9c102_i2c_write(cam, 0x12, 0x80);
178         err += sn9c102_i2c_write(cam, 0x11, 0x09);
179         err += sn9c102_i2c_write(cam, 0x00, 0x0A);
180         err += sn9c102_i2c_write(cam, 0x01, 0x78);
181         err += sn9c102_i2c_write(cam, 0x02, 0x90);
182         err += sn9c102_i2c_write(cam, 0x03, 0x00);
183         err += sn9c102_i2c_write(cam, 0x04, 0x00);
184         err += sn9c102_i2c_write(cam, 0x05, 0x08);
185         err += sn9c102_i2c_write(cam, 0x06, 0x0B);
186         err += sn9c102_i2c_write(cam, 0x07, 0x00);
187         err += sn9c102_i2c_write(cam, 0x08, 0x1C);
188         err += sn9c102_i2c_write(cam, 0x09, 0x01);
189         err += sn9c102_i2c_write(cam, 0x0A, 0x76);
190         err += sn9c102_i2c_write(cam, 0x0B, 0x60);
191         err += sn9c102_i2c_write(cam, 0x0C, 0x00);
192         err += sn9c102_i2c_write(cam, 0x0D, 0x08);
193         err += sn9c102_i2c_write(cam, 0x0E, 0x04);
194         err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
195         err += sn9c102_i2c_write(cam, 0x10, 0x20);
196         err += sn9c102_i2c_write(cam, 0x11, 0x03);
197         err += sn9c102_i2c_write(cam, 0x12, 0x05);
198         err += sn9c102_i2c_write(cam, 0x13, 0xF8);
199         err += sn9c102_i2c_write(cam, 0x14, 0x2C);
200         err += sn9c102_i2c_write(cam, 0x15, 0x00);
201         err += sn9c102_i2c_write(cam, 0x16, 0x02);
202         err += sn9c102_i2c_write(cam, 0x17, 0x10);
203         err += sn9c102_i2c_write(cam, 0x18, 0x60);
204         err += sn9c102_i2c_write(cam, 0x19, 0x02);
205         err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
206         err += sn9c102_i2c_write(cam, 0x1B, 0x02);
207         err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
208         err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
209         err += sn9c102_i2c_write(cam, 0x1E, 0x01);
210         err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
211         err += sn9c102_i2c_write(cam, 0x20, 0x05);
212         err += sn9c102_i2c_write(cam, 0x21, 0x05);
213         err += sn9c102_i2c_write(cam, 0x22, 0x05);
214         err += sn9c102_i2c_write(cam, 0x23, 0x05);
215         err += sn9c102_i2c_write(cam, 0x24, 0x68);
216         err += sn9c102_i2c_write(cam, 0x25, 0x58);
217         err += sn9c102_i2c_write(cam, 0x26, 0xD4);
218         err += sn9c102_i2c_write(cam, 0x27, 0x80);
219         err += sn9c102_i2c_write(cam, 0x28, 0x80);
220         err += sn9c102_i2c_write(cam, 0x29, 0x30);
221         err += sn9c102_i2c_write(cam, 0x2A, 0x00);
222         err += sn9c102_i2c_write(cam, 0x2B, 0x00);
223         err += sn9c102_i2c_write(cam, 0x2C, 0x80);
224         err += sn9c102_i2c_write(cam, 0x2D, 0x00);
225         err += sn9c102_i2c_write(cam, 0x2E, 0x00);
226         err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
227         err += sn9c102_i2c_write(cam, 0x30, 0x08);
228         err += sn9c102_i2c_write(cam, 0x31, 0x30);
229         err += sn9c102_i2c_write(cam, 0x32, 0xB4);
230         err += sn9c102_i2c_write(cam, 0x33, 0x00);
231         err += sn9c102_i2c_write(cam, 0x34, 0x07);
232         err += sn9c102_i2c_write(cam, 0x35, 0x84);
233         err += sn9c102_i2c_write(cam, 0x36, 0x00);
234         err += sn9c102_i2c_write(cam, 0x37, 0x0C);
235         err += sn9c102_i2c_write(cam, 0x38, 0x02);
236         err += sn9c102_i2c_write(cam, 0x39, 0x43);
237         err += sn9c102_i2c_write(cam, 0x3A, 0x00);
238         err += sn9c102_i2c_write(cam, 0x3B, 0x02);
239         err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
240         err += sn9c102_i2c_write(cam, 0x3D, 0x99);
241         err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
242         err += sn9c102_i2c_write(cam, 0x3F, 0x41);
243         err += sn9c102_i2c_write(cam, 0x40, 0xC1);
244         err += sn9c102_i2c_write(cam, 0x41, 0x22);
245         err += sn9c102_i2c_write(cam, 0x42, 0x08);
246         err += sn9c102_i2c_write(cam, 0x43, 0xF0);
247         err += sn9c102_i2c_write(cam, 0x44, 0x10);
248         err += sn9c102_i2c_write(cam, 0x45, 0x78);
249         err += sn9c102_i2c_write(cam, 0x46, 0xA8);
250         err += sn9c102_i2c_write(cam, 0x47, 0x60);
251         err += sn9c102_i2c_write(cam, 0x48, 0x80);
252         err += sn9c102_i2c_write(cam, 0x49, 0x00);
253         err += sn9c102_i2c_write(cam, 0x4A, 0x00);
254         err += sn9c102_i2c_write(cam, 0x4B, 0x00);
255         err += sn9c102_i2c_write(cam, 0x4C, 0x00);
256         err += sn9c102_i2c_write(cam, 0x4D, 0x00);
257         err += sn9c102_i2c_write(cam, 0x4E, 0x00);
258         err += sn9c102_i2c_write(cam, 0x4F, 0x46);
259         err += sn9c102_i2c_write(cam, 0x50, 0x36);
260         err += sn9c102_i2c_write(cam, 0x51, 0x0F);
261         err += sn9c102_i2c_write(cam, 0x52, 0x17);
262         err += sn9c102_i2c_write(cam, 0x53, 0x7F);
263         err += sn9c102_i2c_write(cam, 0x54, 0x96);
264         err += sn9c102_i2c_write(cam, 0x55, 0x40);
265         err += sn9c102_i2c_write(cam, 0x56, 0x40);
266         err += sn9c102_i2c_write(cam, 0x57, 0x40);
267         err += sn9c102_i2c_write(cam, 0x58, 0x0F);
268         err += sn9c102_i2c_write(cam, 0x59, 0xBA);
269         err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
270         err += sn9c102_i2c_write(cam, 0x5B, 0x22);
271         err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
272         err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
273         err += sn9c102_i2c_write(cam, 0x5E, 0x10);
274         err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
275         err += sn9c102_i2c_write(cam, 0x60, 0x05);
276         err += sn9c102_i2c_write(cam, 0x61, 0x60);
277         err += sn9c102_i2c_write(cam, 0x62, 0x00);
278         err += sn9c102_i2c_write(cam, 0x63, 0x00);
279         err += sn9c102_i2c_write(cam, 0x64, 0x50);
280         err += sn9c102_i2c_write(cam, 0x65, 0x30);
281         err += sn9c102_i2c_write(cam, 0x66, 0x00);
282         err += sn9c102_i2c_write(cam, 0x67, 0x80);
283         err += sn9c102_i2c_write(cam, 0x68, 0x7A);
284         err += sn9c102_i2c_write(cam, 0x69, 0x90);
285         err += sn9c102_i2c_write(cam, 0x6A, 0x80);
286         err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
287         err += sn9c102_i2c_write(cam, 0x6C, 0x30);
288         err += sn9c102_i2c_write(cam, 0x6D, 0x48);
289         err += sn9c102_i2c_write(cam, 0x6E, 0x80);
290         err += sn9c102_i2c_write(cam, 0x6F, 0x74);
291         err += sn9c102_i2c_write(cam, 0x70, 0x64);
292         err += sn9c102_i2c_write(cam, 0x71, 0x60);
293         err += sn9c102_i2c_write(cam, 0x72, 0x5C);
294         err += sn9c102_i2c_write(cam, 0x73, 0x58);
295         err += sn9c102_i2c_write(cam, 0x74, 0x54);
296         err += sn9c102_i2c_write(cam, 0x75, 0x4C);
297         err += sn9c102_i2c_write(cam, 0x76, 0x40);
298         err += sn9c102_i2c_write(cam, 0x77, 0x38);
299         err += sn9c102_i2c_write(cam, 0x78, 0x34);
300         err += sn9c102_i2c_write(cam, 0x79, 0x30);
301         err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
302         err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
303         err += sn9c102_i2c_write(cam, 0x7C, 0x03);
304         err += sn9c102_i2c_write(cam, 0x7D, 0x07);
305         err += sn9c102_i2c_write(cam, 0x7E, 0x17);
306         err += sn9c102_i2c_write(cam, 0x7F, 0x34);
307         err += sn9c102_i2c_write(cam, 0x80, 0x41);
308         err += sn9c102_i2c_write(cam, 0x81, 0x4D);
309         err += sn9c102_i2c_write(cam, 0x82, 0x58);
310         err += sn9c102_i2c_write(cam, 0x83, 0x63);
311         err += sn9c102_i2c_write(cam, 0x84, 0x6E);
312         err += sn9c102_i2c_write(cam, 0x85, 0x77);
313         err += sn9c102_i2c_write(cam, 0x86, 0x87);
314         err += sn9c102_i2c_write(cam, 0x87, 0x95);
315         err += sn9c102_i2c_write(cam, 0x88, 0xAF);
316         err += sn9c102_i2c_write(cam, 0x89, 0xC7);
317         err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
318         err += sn9c102_i2c_write(cam, 0x8B, 0x99);
319         err += sn9c102_i2c_write(cam, 0x8C, 0x99);
320         err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
321         err += sn9c102_i2c_write(cam, 0x8E, 0x20);
322         err += sn9c102_i2c_write(cam, 0x8F, 0x26);
323         err += sn9c102_i2c_write(cam, 0x90, 0x10);
324         err += sn9c102_i2c_write(cam, 0x91, 0x0C);
325         err += sn9c102_i2c_write(cam, 0x92, 0x25);
326         err += sn9c102_i2c_write(cam, 0x93, 0x00);
327         err += sn9c102_i2c_write(cam, 0x94, 0x50);
328         err += sn9c102_i2c_write(cam, 0x95, 0x50);
329         err += sn9c102_i2c_write(cam, 0x96, 0x00);
330         err += sn9c102_i2c_write(cam, 0x97, 0x01);
331         err += sn9c102_i2c_write(cam, 0x98, 0x10);
332         err += sn9c102_i2c_write(cam, 0x99, 0x40);
333         err += sn9c102_i2c_write(cam, 0x9A, 0x40);
334         err += sn9c102_i2c_write(cam, 0x9B, 0x20);
335         err += sn9c102_i2c_write(cam, 0x9C, 0x00);
336         err += sn9c102_i2c_write(cam, 0x9D, 0x99);
337         err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
338         err += sn9c102_i2c_write(cam, 0x9F, 0x00);
339         err += sn9c102_i2c_write(cam, 0xA0, 0x00);
340         err += sn9c102_i2c_write(cam, 0xA1, 0x00);
341
342         return err;
343 }
344
345
346 static int ov7660_get_ctrl(struct sn9c102_device* cam,
347                            struct v4l2_control* ctrl)
348 {
349         int err = 0;
350
351         switch (ctrl->id) {
352         case V4L2_CID_EXPOSURE:
353                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
354                         return -EIO;
355                 break;
356         case V4L2_CID_DO_WHITE_BALANCE:
357                 ctrl->value = sn9c102_pread_reg(cam, 0x02);
358                 ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
359                 break;
360         case V4L2_CID_RED_BALANCE:
361                 ctrl->value = sn9c102_pread_reg(cam, 0x05);
362                 ctrl->value &= 0x7f;
363                 break;
364         case V4L2_CID_BLUE_BALANCE:
365                 ctrl->value = sn9c102_pread_reg(cam, 0x06);
366                 ctrl->value &= 0x7f;
367                 break;
368         case SN9C102_V4L2_CID_GREEN_BALANCE:
369                 ctrl->value = sn9c102_pread_reg(cam, 0x07);
370                 ctrl->value &= 0x7f;
371                 break;
372         case V4L2_CID_GAIN:
373                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
374                         return -EIO;
375                 ctrl->value &= 0x7f;
376                 break;
377         case V4L2_CID_AUTOGAIN:
378                 if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
379                         return -EIO;
380                 ctrl->value &= 0x01;
381                 break;
382         default:
383                 return -EINVAL;
384         }
385
386         return err ? -EIO : 0;
387 }
388
389
390 static int ov7660_set_ctrl(struct sn9c102_device* cam,
391                            const struct v4l2_control* ctrl)
392 {
393         int err = 0;
394
395         switch (ctrl->id) {
396         case V4L2_CID_EXPOSURE:
397                 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
398                 break;
399         case V4L2_CID_DO_WHITE_BALANCE:
400                 err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
401                 break;
402         case V4L2_CID_RED_BALANCE:
403                 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
404                 break;
405         case V4L2_CID_BLUE_BALANCE:
406                 err += sn9c102_write_reg(cam, ctrl->value, 0x06);
407                 break;
408         case SN9C102_V4L2_CID_GREEN_BALANCE:
409                 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
410                 break;
411         case V4L2_CID_GAIN:
412                 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
413                 break;
414         case V4L2_CID_AUTOGAIN:
415                 err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
416                                                     (ctrl->value << 1));
417                 break;
418         default:
419                 return -EINVAL;
420         }
421
422         return err ? -EIO : 0;
423 }
424
425
426 static int ov7660_set_crop(struct sn9c102_device* cam,
427                            const struct v4l2_rect* rect)
428 {
429         struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
430         int err = 0;
431         u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
432            v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
433
434         err += sn9c102_write_reg(cam, h_start, 0x12);
435         err += sn9c102_write_reg(cam, v_start, 0x13);
436
437         return err;
438 }
439
440
441 static int ov7660_set_pix_format(struct sn9c102_device* cam,
442                                  const struct v4l2_pix_format* pix)
443 {
444         int r0, err = 0;
445
446         r0 = sn9c102_pread_reg(cam, 0x01);
447
448         if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
449                 err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
450                 err += sn9c102_write_reg(cam, 0xa2, 0x17);
451                 err += sn9c102_i2c_write(cam, 0x11, 0x00);
452         } else {
453                 err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
454                 err += sn9c102_write_reg(cam, 0xa2, 0x17);
455                 err += sn9c102_i2c_write(cam, 0x11, 0x0d);
456         }
457
458         return err;
459 }
460
461
462 static struct sn9c102_sensor ov7660 = {
463         .name = "OV7660",
464         .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
465         .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
466         .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
467         .frequency = SN9C102_I2C_100KHZ,
468         .interface = SN9C102_I2C_2WIRES,
469         .i2c_slave_id = 0x21,
470         .init = &ov7660_init,
471         .qctrl = {
472                 {
473                         .id = V4L2_CID_GAIN,
474                         .type = V4L2_CTRL_TYPE_INTEGER,
475                         .name = "global gain",
476                         .minimum = 0x00,
477                         .maximum = 0x7f,
478                         .step = 0x01,
479                         .default_value = 0x0a,
480                         .flags = 0,
481                 },
482                 {
483                         .id = V4L2_CID_EXPOSURE,
484                         .type = V4L2_CTRL_TYPE_INTEGER,
485                         .name = "exposure",
486                         .minimum = 0x00,
487                         .maximum = 0xff,
488                         .step = 0x01,
489                         .default_value = 0x50,
490                         .flags = 0,
491                 },
492                 {
493                         .id = V4L2_CID_DO_WHITE_BALANCE,
494                         .type = V4L2_CTRL_TYPE_BOOLEAN,
495                         .name = "night mode",
496                         .minimum = 0x00,
497                         .maximum = 0x01,
498                         .step = 0x01,
499                         .default_value = 0x00,
500                         .flags = 0,
501                 },
502                 {
503                         .id = V4L2_CID_RED_BALANCE,
504                         .type = V4L2_CTRL_TYPE_INTEGER,
505                         .name = "red balance",
506                         .minimum = 0x00,
507                         .maximum = 0x7f,
508                         .step = 0x01,
509                         .default_value = 0x1f,
510                         .flags = 0,
511                 },
512                 {
513                         .id = V4L2_CID_BLUE_BALANCE,
514                         .type = V4L2_CTRL_TYPE_INTEGER,
515                         .name = "blue balance",
516                         .minimum = 0x00,
517                         .maximum = 0x7f,
518                         .step = 0x01,
519                         .default_value = 0x1e,
520                         .flags = 0,
521                 },
522                 {
523                         .id = V4L2_CID_AUTOGAIN,
524                         .type = V4L2_CTRL_TYPE_BOOLEAN,
525                         .name = "auto adjust",
526                         .minimum = 0x00,
527                         .maximum = 0x01,
528                         .step = 0x01,
529                         .default_value = 0x00,
530                         .flags = 0,
531                 },
532                 {
533                         .id = SN9C102_V4L2_CID_GREEN_BALANCE,
534                         .type = V4L2_CTRL_TYPE_INTEGER,
535                         .name = "green balance",
536                         .minimum = 0x00,
537                         .maximum = 0x7f,
538                         .step = 0x01,
539                         .default_value = 0x20,
540                         .flags = 0,
541                 },
542         },
543         .get_ctrl = &ov7660_get_ctrl,
544         .set_ctrl = &ov7660_set_ctrl,
545         .cropcap = {
546                 .bounds = {
547                         .left = 0,
548                         .top = 0,
549                         .width = 640,
550                         .height = 480,
551                 },
552                 .defrect = {
553                         .left = 0,
554                         .top = 0,
555                         .width = 640,
556                         .height = 480,
557                 },
558         },
559         .set_crop = &ov7660_set_crop,
560         .pix_format = {
561                 .width = 640,
562                 .height = 480,
563                 .pixelformat = V4L2_PIX_FMT_JPEG,
564                 .priv = 8,
565         },
566         .set_pix_format = &ov7660_set_pix_format
567 };
568
569
570 int sn9c102_probe_ov7660(struct sn9c102_device* cam)
571 {
572         int pid, ver, err = 0;
573
574         err += sn9c102_write_reg(cam, 0x01, 0xf1);
575         err += sn9c102_write_reg(cam, 0x00, 0xf1);
576         err += sn9c102_write_reg(cam, 0x01, 0x01);
577         err += sn9c102_write_reg(cam, 0x00, 0x01);
578         err += sn9c102_write_reg(cam, 0x28, 0x17);
579
580         pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
581         ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
582         if (err || pid < 0 || ver < 0)
583                 return -EIO;
584         if (pid != 0x76 || ver != 0x60)
585                 return -ENODEV;
586         sn9c102_attach_sensor(cam, &ov7660);
587
588         return 0;
589 }