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("Analog Devices ADV7175 video encoder driver");
37MODULE_AUTHOR("Dave Perks");
38MODULE_LICENSE("GPL");
39
40#define I2C_ADV7175 0xd4
41#define I2C_ADV7176 0x54
42
43
44static int debug;
45module_param(debug, int, 0);
46MODULE_PARM_DESC(debug, "Debug level (0-1)");
47
48
49
50struct adv7175 {
51 struct v4l2_subdev sd;
52 v4l2_std_id norm;
53 int input;
54};
55
56static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd)
57{
58 return container_of(sd, struct adv7175, sd);
59}
60
61static char *inputs[] = { "pass_through", "play_back", "color_bar" };
62
63static enum v4l2_mbus_pixelcode adv7175_codes[] = {
64 V4L2_MBUS_FMT_UYVY8_2X8,
65 V4L2_MBUS_FMT_UYVY8_1X16,
66};
67
68
69
70static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
71{
72 struct i2c_client *client = v4l2_get_subdevdata(sd);
73
74 return i2c_smbus_write_byte_data(client, reg, value);
75}
76
77static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg)
78{
79 struct i2c_client *client = v4l2_get_subdevdata(sd);
80
81 return i2c_smbus_read_byte_data(client, reg);
82}
83
84static int adv7175_write_block(struct v4l2_subdev *sd,
85 const u8 *data, unsigned int len)
86{
87 struct i2c_client *client = v4l2_get_subdevdata(sd);
88 int ret = -1;
89 u8 reg;
90
91
92
93 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
94
95 u8 block_data[32];
96 int block_len;
97
98 while (len >= 2) {
99 block_len = 0;
100 block_data[block_len++] = reg = data[0];
101 do {
102 block_data[block_len++] = data[1];
103 reg++;
104 len -= 2;
105 data += 2;
106 } while (len >= 2 && data[0] == reg && block_len < 32);
107 ret = i2c_master_send(client, block_data, block_len);
108 if (ret < 0)
109 break;
110 }
111 } else {
112
113 while (len >= 2) {
114 reg = *data++;
115 ret = adv7175_write(sd, reg, *data++);
116 if (ret < 0)
117 break;
118 len -= 2;
119 }
120 }
121
122 return ret;
123}
124
125static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through)
126{
127
128
129 if (pass_through)
130 adv7175_write(sd, 0x02, 0x00);
131 else
132 adv7175_write(sd, 0x02, 0x55);
133
134 adv7175_write(sd, 0x03, 0x55);
135 adv7175_write(sd, 0x04, 0x55);
136 adv7175_write(sd, 0x05, 0x25);
137}
138
139
140
141
142#define MR050 0x11
143#define MR060 0x14
144
145
146
147#define TR0MODE 0x46
148#define TR0RST 0x80
149
150#define TR1CAPT 0x80
151#define TR1PLAY 0x00
152
153static const unsigned char init_common[] = {
154
155 0x00, MR050,
156 0x01, 0x00,
157 0x02, 0x0c,
158 0x03, 0x8c,
159 0x04, 0x79,
160 0x05, 0x26,
161 0x06, 0x40,
162
163 0x07, TR0MODE,
164 0x08, 0x21,
165 0x09, 0x00,
166 0x0a, 0x00,
167 0x0b, 0x00,
168 0x0c, TR1CAPT,
169 0x0d, 0x4f,
170 0x0e, 0x00,
171 0x0f, 0x00,
172 0x10, 0x00,
173 0x11, 0x00,
174};
175
176static const unsigned char init_pal[] = {
177 0x00, MR050,
178 0x01, 0x00,
179 0x02, 0x0c,
180 0x03, 0x8c,
181 0x04, 0x79,
182 0x05, 0x26,
183 0x06, 0x40,
184};
185
186static const unsigned char init_ntsc[] = {
187 0x00, MR060,
188 0x01, 0x00,
189 0x02, 0x55,
190 0x03, 0x55,
191 0x04, 0x55,
192 0x05, 0x25,
193 0x06, 0x1a,
194};
195
196static int adv7175_init(struct v4l2_subdev *sd, u32 val)
197{
198
199 adv7175_write_block(sd, init_common, sizeof(init_common));
200 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
201 adv7175_write(sd, 0x07, TR0MODE);
202 return 0;
203}
204
205static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
206{
207 struct adv7175 *encoder = to_adv7175(sd);
208
209 if (std & V4L2_STD_NTSC) {
210 adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc));
211 if (encoder->input == 0)
212 adv7175_write(sd, 0x0d, 0x4f);
213 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
214 adv7175_write(sd, 0x07, TR0MODE);
215 } else if (std & V4L2_STD_PAL) {
216 adv7175_write_block(sd, init_pal, sizeof(init_pal));
217 if (encoder->input == 0)
218 adv7175_write(sd, 0x0d, 0x4f);
219 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
220 adv7175_write(sd, 0x07, TR0MODE);
221 } else if (std & V4L2_STD_SECAM) {
222
223
224
225
226
227
228 adv7175_write_block(sd, init_pal, sizeof(init_pal));
229 if (encoder->input == 0)
230 adv7175_write(sd, 0x0d, 0x49);
231 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
232 adv7175_write(sd, 0x07, TR0MODE);
233 } else {
234 v4l2_dbg(1, debug, sd, "illegal norm: %llx\n",
235 (unsigned long long)std);
236 return -EINVAL;
237 }
238 v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std);
239 encoder->norm = std;
240 return 0;
241}
242
243static int adv7175_s_routing(struct v4l2_subdev *sd,
244 u32 input, u32 output, u32 config)
245{
246 struct adv7175 *encoder = to_adv7175(sd);
247
248
249
250
251
252 switch (input) {
253 case 0:
254 adv7175_write(sd, 0x01, 0x00);
255
256 if (encoder->norm & V4L2_STD_NTSC)
257 set_subcarrier_freq(sd, 1);
258
259 adv7175_write(sd, 0x0c, TR1CAPT);
260 if (encoder->norm & V4L2_STD_SECAM)
261 adv7175_write(sd, 0x0d, 0x49);
262 else
263 adv7175_write(sd, 0x0d, 0x4f);
264 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
265 adv7175_write(sd, 0x07, TR0MODE);
266
267 break;
268
269 case 1:
270 adv7175_write(sd, 0x01, 0x00);
271
272 if (encoder->norm & V4L2_STD_NTSC)
273 set_subcarrier_freq(sd, 0);
274
275 adv7175_write(sd, 0x0c, TR1PLAY);
276 adv7175_write(sd, 0x0d, 0x49);
277 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
278 adv7175_write(sd, 0x07, TR0MODE);
279
280 break;
281
282 case 2:
283 adv7175_write(sd, 0x01, 0x80);
284
285 if (encoder->norm & V4L2_STD_NTSC)
286 set_subcarrier_freq(sd, 0);
287
288 adv7175_write(sd, 0x0d, 0x49);
289 adv7175_write(sd, 0x07, TR0MODE | TR0RST);
290 adv7175_write(sd, 0x07, TR0MODE);
291
292 break;
293
294 default:
295 v4l2_dbg(1, debug, sd, "illegal input: %d\n", input);
296 return -EINVAL;
297 }
298 v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]);
299 encoder->input = input;
300 return 0;
301}
302
303static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
304 enum v4l2_mbus_pixelcode *code)
305{
306 if (index >= ARRAY_SIZE(adv7175_codes))
307 return -EINVAL;
308
309 *code = adv7175_codes[index];
310 return 0;
311}
312
313static int adv7175_g_fmt(struct v4l2_subdev *sd,
314 struct v4l2_mbus_framefmt *mf)
315{
316 u8 val = adv7175_read(sd, 0x7);
317
318 if ((val & 0x40) == (1 << 6))
319 mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
320 else
321 mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
322
323 mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
324 mf->width = 0;
325 mf->height = 0;
326 mf->field = V4L2_FIELD_ANY;
327
328 return 0;
329}
330
331static int adv7175_s_fmt(struct v4l2_subdev *sd,
332 struct v4l2_mbus_framefmt *mf)
333{
334 u8 val = adv7175_read(sd, 0x7);
335 int ret;
336
337 switch (mf->code) {
338 case V4L2_MBUS_FMT_UYVY8_2X8:
339 val &= ~0x40;
340 break;
341
342 case V4L2_MBUS_FMT_UYVY8_1X16:
343 val |= 0x40;
344 break;
345
346 default:
347 v4l2_dbg(1, debug, sd,
348 "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
349 return -EINVAL;
350 }
351
352 ret = adv7175_write(sd, 0x7, val);
353
354 return ret;
355}
356
357static int adv7175_s_power(struct v4l2_subdev *sd, int on)
358{
359 if (on)
360 adv7175_write(sd, 0x01, 0x00);
361 else
362 adv7175_write(sd, 0x01, 0x78);
363
364 return 0;
365}
366
367
368
369static const struct v4l2_subdev_core_ops adv7175_core_ops = {
370 .init = adv7175_init,
371 .s_power = adv7175_s_power,
372};
373
374static const struct v4l2_subdev_video_ops adv7175_video_ops = {
375 .s_std_output = adv7175_s_std_output,
376 .s_routing = adv7175_s_routing,
377 .s_mbus_fmt = adv7175_s_fmt,
378 .g_mbus_fmt = adv7175_g_fmt,
379 .enum_mbus_fmt = adv7175_enum_fmt,
380};
381
382static const struct v4l2_subdev_ops adv7175_ops = {
383 .core = &adv7175_core_ops,
384 .video = &adv7175_video_ops,
385};
386
387
388
389static int adv7175_probe(struct i2c_client *client,
390 const struct i2c_device_id *id)
391{
392 int i;
393 struct adv7175 *encoder;
394 struct v4l2_subdev *sd;
395
396
397 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
398 return -ENODEV;
399
400 v4l_info(client, "chip found @ 0x%x (%s)\n",
401 client->addr << 1, client->adapter->name);
402
403 encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
404 if (encoder == NULL)
405 return -ENOMEM;
406 sd = &encoder->sd;
407 v4l2_i2c_subdev_init(sd, client, &adv7175_ops);
408 encoder->norm = V4L2_STD_NTSC;
409 encoder->input = 0;
410
411 i = adv7175_write_block(sd, init_common, sizeof(init_common));
412 if (i >= 0) {
413 i = adv7175_write(sd, 0x07, TR0MODE | TR0RST);
414 i = adv7175_write(sd, 0x07, TR0MODE);
415 i = adv7175_read(sd, 0x12);
416 v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
417 }
418 if (i < 0)
419 v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
420 return 0;
421}
422
423static int adv7175_remove(struct i2c_client *client)
424{
425 struct v4l2_subdev *sd = i2c_get_clientdata(client);
426
427 v4l2_device_unregister_subdev(sd);
428 return 0;
429}
430
431
432
433static const struct i2c_device_id adv7175_id[] = {
434 { "adv7175", 0 },
435 { "adv7176", 0 },
436 { }
437};
438MODULE_DEVICE_TABLE(i2c, adv7175_id);
439
440static struct i2c_driver adv7175_driver = {
441 .driver = {
442 .owner = THIS_MODULE,
443 .name = "adv7175",
444 },
445 .probe = adv7175_probe,
446 .remove = adv7175_remove,
447 .id_table = adv7175_id,
448};
449
450module_i2c_driver(adv7175_driver);
451