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