1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/module.h>
28#include <linux/types.h>
29#include <linux/slab.h>
30#include <linux/ioctl.h>
31#include <asm/uaccess.h>
32#include <linux/i2c.h>
33#include <linux/videodev2.h>
34#include <media/v4l2-device.h>
35
36MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
37MODULE_AUTHOR("Dave Perks");
38MODULE_LICENSE("GPL");
39
40static int debug;
41module_param(debug, int, 0);
42MODULE_PARM_DESC(debug, "Debug level (0-1)");
43
44
45
46
47struct saa7185 {
48 struct v4l2_subdev sd;
49 unsigned char reg[128];
50
51 v4l2_std_id norm;
52};
53
54static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd)
55{
56 return container_of(sd, struct saa7185, sd);
57}
58
59
60
61static inline int saa7185_read(struct v4l2_subdev *sd)
62{
63 struct i2c_client *client = v4l2_get_subdevdata(sd);
64
65 return i2c_smbus_read_byte(client);
66}
67
68static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
69{
70 struct i2c_client *client = v4l2_get_subdevdata(sd);
71 struct saa7185 *encoder = to_saa7185(sd);
72
73 v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value);
74 encoder->reg[reg] = value;
75 return i2c_smbus_write_byte_data(client, reg, value);
76}
77
78static int saa7185_write_block(struct v4l2_subdev *sd,
79 const u8 *data, unsigned int len)
80{
81 struct i2c_client *client = v4l2_get_subdevdata(sd);
82 struct saa7185 *encoder = to_saa7185(sd);
83 int ret = -1;
84 u8 reg;
85
86
87
88 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
89
90 u8 block_data[32];
91 int block_len;
92
93 while (len >= 2) {
94 block_len = 0;
95 block_data[block_len++] = reg = data[0];
96 do {
97 block_data[block_len++] =
98 encoder->reg[reg++] = data[1];
99 len -= 2;
100 data += 2;
101 } while (len >= 2 && data[0] == reg && block_len < 32);
102 ret = i2c_master_send(client, block_data, block_len);
103 if (ret < 0)
104 break;
105 }
106 } else {
107
108 while (len >= 2) {
109 reg = *data++;
110 ret = saa7185_write(sd, reg, *data++);
111 if (ret < 0)
112 break;
113 len -= 2;
114 }
115 }
116
117 return ret;
118}
119
120
121
122static const unsigned char init_common[] = {
123 0x3a, 0x0f,
124
125
126 0x42, 0x6b,
127 0x43, 0x00,
128 0x44, 0x00,
129 0x45, 0x22,
130 0x46, 0xac,
131 0x47, 0x0e,
132 0x48, 0x03,
133 0x49, 0x1d,
134 0x4a, 0xac,
135 0x4b, 0xf0,
136 0x4c, 0xc8,
137 0x4d, 0xb9,
138 0x4e, 0xd4,
139 0x4f, 0x38,
140 0x50, 0x47,
141 0x51, 0xc1,
142 0x52, 0xe3,
143 0x53, 0x54,
144 0x54, 0xa3,
145 0x55, 0x54,
146 0x56, 0xf2,
147 0x57, 0x90,
148 0x58, 0x00,
149 0x59, 0x00,
150
151 0x5a, 0x00,
152 0x5b, 0x76,
153 0x5c, 0xa5,
154 0x5d, 0x3c,
155 0x5e, 0x3a,
156 0x5f, 0x3a,
157 0x60, 0x00,
158
159
160
161 0x67, 0x00,
162 0x68, 0x00,
163 0x69, 0x00,
164 0x6a, 0x00,
165
166 0x6b, 0x91,
167 0x6c, 0x20,
168
169 0x6d, 0x00,
170
171 0x6e, 0x0e,
172
173 0x6f, 0x00,
174 0x70, 0x20,
175
176
177
178 0x71, 0x15,
179 0x72, 0x90,
180 0x73, 0x61,
181 0x74, 0x00,
182 0x75, 0x00,
183 0x76, 0x00,
184 0x77, 0x15,
185 0x78, 0x90,
186 0x79, 0x61,
187
188
189
190 0x7a, 0x70,
191
192
193
194 0x7b, 0x16,
195 0x7c, 0x35,
196 0x7d, 0x20,
197};
198
199static const unsigned char init_pal[] = {
200 0x61, 0x1e,
201
202 0x62, 0xc8,
203 0x63, 0xcb,
204 0x64, 0x8a,
205 0x65, 0x09,
206 0x66, 0x2a,
207};
208
209static const unsigned char init_ntsc[] = {
210 0x61, 0x1d,
211
212 0x62, 0xe6,
213 0x63, 0x1f,
214 0x64, 0x7c,
215 0x65, 0xf0,
216 0x66, 0x21,
217};
218
219
220static int saa7185_init(struct v4l2_subdev *sd, u32 val)
221{
222 struct saa7185 *encoder = to_saa7185(sd);
223
224 saa7185_write_block(sd, init_common, sizeof(init_common));
225 if (encoder->norm & V4L2_STD_NTSC)
226 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
227 else
228 saa7185_write_block(sd, init_pal, sizeof(init_pal));
229 return 0;
230}
231
232static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
233{
234 struct saa7185 *encoder = to_saa7185(sd);
235
236 if (std & V4L2_STD_NTSC)
237 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
238 else if (std & V4L2_STD_PAL)
239 saa7185_write_block(sd, init_pal, sizeof(init_pal));
240 else
241 return -EINVAL;
242 encoder->norm = std;
243 return 0;
244}
245
246static int saa7185_s_routing(struct v4l2_subdev *sd,
247 u32 input, u32 output, u32 config)
248{
249 struct saa7185 *encoder = to_saa7185(sd);
250
251
252
253
254 switch (input) {
255 case 0:
256
257 saa7185_write(sd, 0x3a, 0x0f);
258
259 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
260 saa7185_write(sd, 0x6e, 0x01);
261 break;
262
263 case 1:
264
265 saa7185_write(sd, 0x3a, 0x0f);
266
267 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
268
269 saa7185_write(sd, 0x6e, 0x00);
270 break;
271
272 case 2:
273
274 saa7185_write(sd, 0x3a, 0x8f);
275
276 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
277
278 saa7185_write(sd, 0x6e, 0x01);
279 break;
280
281 default:
282 return -EINVAL;
283 }
284 return 0;
285}
286
287
288
289static const struct v4l2_subdev_core_ops saa7185_core_ops = {
290 .init = saa7185_init,
291};
292
293static const struct v4l2_subdev_video_ops saa7185_video_ops = {
294 .s_std_output = saa7185_s_std_output,
295 .s_routing = saa7185_s_routing,
296};
297
298static const struct v4l2_subdev_ops saa7185_ops = {
299 .core = &saa7185_core_ops,
300 .video = &saa7185_video_ops,
301};
302
303
304
305
306static int saa7185_probe(struct i2c_client *client,
307 const struct i2c_device_id *id)
308{
309 int i;
310 struct saa7185 *encoder;
311 struct v4l2_subdev *sd;
312
313
314 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
315 return -ENODEV;
316
317 v4l_info(client, "chip found @ 0x%x (%s)\n",
318 client->addr << 1, client->adapter->name);
319
320 encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
321 if (encoder == NULL)
322 return -ENOMEM;
323 encoder->norm = V4L2_STD_NTSC;
324 sd = &encoder->sd;
325 v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
326
327 i = saa7185_write_block(sd, init_common, sizeof(init_common));
328 if (i >= 0)
329 i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
330 if (i < 0)
331 v4l2_dbg(1, debug, sd, "init error %d\n", i);
332 else
333 v4l2_dbg(1, debug, sd, "revision 0x%x\n",
334 saa7185_read(sd) >> 5);
335 return 0;
336}
337
338static int saa7185_remove(struct i2c_client *client)
339{
340 struct v4l2_subdev *sd = i2c_get_clientdata(client);
341 struct saa7185 *encoder = to_saa7185(sd);
342
343 v4l2_device_unregister_subdev(sd);
344
345 saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
346 return 0;
347}
348
349
350
351static const struct i2c_device_id saa7185_id[] = {
352 { "saa7185", 0 },
353 { }
354};
355MODULE_DEVICE_TABLE(i2c, saa7185_id);
356
357static struct i2c_driver saa7185_driver = {
358 .driver = {
359 .owner = THIS_MODULE,
360 .name = "saa7185",
361 },
362 .probe = saa7185_probe,
363 .remove = saa7185_remove,
364 .id_table = saa7185_id,
365};
366
367module_i2c_driver(saa7185_driver);
368