1/*
2 * vpx3220a, vpx3216b & vpx3214c video decoder driver version 0.0.1
3 *
4 * Copyright (C) 2001 Laurent Pinchart <lpinchart@freegates.be>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/types.h>
25#include <linux/slab.h>
26
27#include <linux/byteorder/swab.h>
28
29#include <asm/io.h>
30#include <asm/uaccess.h>
31
32#include <linux/i2c.h>
33
34#define I2C_NAME(x) (x)->name
35
36#include <linux/videodev.h>
37#include <media/v4l2-common.h>
38#include <linux/video_decoder.h>
39
40#define I2C_VPX3220        0x86
41#define VPX3220_DEBUG	KERN_DEBUG "vpx3220: "
42
43static int debug = 0;
44module_param(debug, int, 0);
45MODULE_PARM_DESC(debug, "Debug level (0-1)");
46
47#define dprintk(num, format, args...) \
48	do { \
49		if (debug >= num) \
50			printk(format, ##args); \
51	} while (0)
52
53#define VPX_TIMEOUT_COUNT  10
54
55/* ----------------------------------------------------------------------- */
56
57struct vpx3220 {
58	unsigned char reg[255];
59
60	int norm;
61	int input;
62	int enable;
63	int bright;
64	int contrast;
65	int hue;
66	int sat;
67};
68
69static char *inputs[] = { "internal", "composite", "svideo" };
70
71/* ----------------------------------------------------------------------- */
72static inline int
73vpx3220_write (struct i2c_client *client,
74	       u8                 reg,
75	       u8                 value)
76{
77	struct vpx3220 *decoder = i2c_get_clientdata(client);
78
79	decoder->reg[reg] = value;
80	return i2c_smbus_write_byte_data(client, reg, value);
81}
82
83static inline int
84vpx3220_read (struct i2c_client *client,
85	      u8                 reg)
86{
87	return i2c_smbus_read_byte_data(client, reg);
88}
89
90static int
91vpx3220_fp_status (struct i2c_client *client)
92{
93	unsigned char status;
94	unsigned int i;
95
96	for (i = 0; i < VPX_TIMEOUT_COUNT; i++) {
97		status = vpx3220_read(client, 0x29);
98
99		if (!(status & 4))
100			return 0;
101
102		udelay(10);
103
104		if (need_resched())
105			cond_resched();
106	}
107
108	return -1;
109}
110
111static int
112vpx3220_fp_write (struct i2c_client *client,
113		  u8                 fpaddr,
114		  u16                data)
115{
116	/* Write the 16-bit address to the FPWR register */
117	if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
118		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
119		return -1;
120	}
121
122	if (vpx3220_fp_status(client) < 0)
123		return -1;
124
125	/* Write the 16-bit data to the FPDAT register */
126	if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
127		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
128		return -1;
129	}
130
131	return 0;
132}
133
134static u16
135vpx3220_fp_read (struct i2c_client *client,
136		 u16                fpaddr)
137{
138	s16 data;
139
140	/* Write the 16-bit address to the FPRD register */
141	if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
142		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
143		return -1;
144	}
145
146	if (vpx3220_fp_status(client) < 0)
147		return -1;
148
149	/* Read the 16-bit data from the FPDAT register */
150	data = i2c_smbus_read_word_data(client, 0x28);
151	if (data == -1) {
152		dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__);
153		return -1;
154	}
155
156	return swab16(data);
157}
158
159static int
160vpx3220_write_block (struct i2c_client *client,
161		     const u8          *data,
162		     unsigned int       len)
163{
164	u8 reg;
165	int ret = -1;
166
167	while (len >= 2) {
168		reg = *data++;
169		if ((ret =
170		     vpx3220_write(client, reg, *data++)) < 0)
171			break;
172		len -= 2;
173	}
174
175	return ret;
176}
177
178static int
179vpx3220_write_fp_block (struct i2c_client *client,
180			const u16         *data,
181			unsigned int       len)
182{
183	u8 reg;
184	int ret = 0;
185
186	while (len > 1) {
187		reg = *data++;
188		ret |= vpx3220_fp_write(client, reg, *data++);
189		len -= 2;
190	}
191
192	return ret;
193}
194
195/* ---------------------------------------------------------------------- */
196
197static const unsigned short init_ntsc[] = {
198	0x1c, 0x00,		/* NTSC tint angle */
199	0x88, 17,		/* Window 1 vertical */
200	0x89, 240,		/* Vertical lines in */
201	0x8a, 240,		/* Vertical lines out */
202	0x8b, 000,		/* Horizontal begin */
203	0x8c, 640,		/* Horizontal length */
204	0x8d, 640,		/* Number of pixels */
205	0x8f, 0xc00,		/* Disable window 2 */
206	0xf0, 0x73,		/* 13.5 MHz transport, Forced
207				 * mode, latch windows */
208	0xf2, 0x13,		/* NTSC M, composite input */
209	0xe7, 0x1e1,		/* Enable vertical standard
210				 * locking @ 240 lines */
211};
212
213static const unsigned short init_pal[] = {
214	0x88, 23,		/* Window 1 vertical begin */
215	0x89, 288,		/* Vertical lines in (16 lines
216				 * skipped by the VFE) */
217	0x8a, 288,		/* Vertical lines out (16 lines
218				 * skipped by the VFE) */
219	0x8b, 16,		/* Horizontal begin */
220	0x8c, 768,		/* Horizontal length */
221	0x8d, 784, 		/* Number of pixels
222				 * Must be >= Horizontal begin + Horizontal length */
223	0x8f, 0xc00,		/* Disable window 2 */
224	0xf0, 0x77,		/* 13.5 MHz transport, Forced
225				 * mode, latch windows */
226	0xf2, 0x3d1,		/* PAL B,G,H,I, composite input */
227	0xe7, 0x241,		/* PAL/SECAM set to 288 lines */
228};
229
230static const unsigned short init_secam[] = {
231	0x88, 23,		/* Window 1 vertical begin */
232	0x89, 288,		/* Vertical lines in (16 lines
233				 * skipped by the VFE) */
234	0x8a, 288,		/* Vertical lines out (16 lines
235				 * skipped by the VFE) */
236	0x8b, 16,		/* Horizontal begin */
237	0x8c, 768,		/* Horizontal length */
238	0x8d, 784,		/* Number of pixels
239				 * Must be >= Horizontal begin + Horizontal length */
240	0x8f, 0xc00,		/* Disable window 2 */
241	0xf0, 0x77,		/* 13.5 MHz transport, Forced
242				 * mode, latch windows */
243	0xf2, 0x3d5,		/* SECAM, composite input */
244	0xe7, 0x241,		/* PAL/SECAM set to 288 lines */
245};
246
247static const unsigned char init_common[] = {
248	0xf2, 0x00,		/* Disable all outputs */
249	0x33, 0x0d,		/* Luma : VIN2, Chroma : CIN
250				 * (clamp off) */
251	0xd8, 0xa8,		/* HREF/VREF active high, VREF
252				 * pulse = 2, Odd/Even flag */
253	0x20, 0x03,		/* IF compensation 0dB/oct */
254	0xe0, 0xff,		/* Open up all comparators */
255	0xe1, 0x00,
256	0xe2, 0x7f,
257	0xe3, 0x80,
258	0xe4, 0x7f,
259	0xe5, 0x80,
260	0xe6, 0x00,		/* Brightness set to 0 */
261	0xe7, 0xe0,		/* Contrast to 1.0, noise shaping
262				 * 10 to 8 2-bit error diffusion */
263	0xe8, 0xf8,		/* YUV422, CbCr binary offset,
264				 * ... (p.32) */
265	0xea, 0x18,		/* LLC2 connected, output FIFO
266				 * reset with VACTintern */
267	0xf0, 0x8a,		/* Half full level to 10, bus
268				 * shuffler [7:0, 23:16, 15:8] */
269	0xf1, 0x18,		/* Single clock, sync mode, no
270				 * FE delay, no HLEN counter */
271	0xf8, 0x12,		/* Port A, PIXCLK, HF# & FE#
272				 * strength to 2 */
273	0xf9, 0x24,		/* Port B, HREF, VREF, PREF &
274				 * ALPHA strength to 4 */
275};
276
277static const unsigned short init_fp[] = {
278	0x59, 0,
279	0xa0, 2070,		/* ACC reference */
280	0xa3, 0,
281	0xa4, 0,
282	0xa8, 30,
283	0xb2, 768,
284	0xbe, 27,
285	0x58, 0,
286	0x26, 0,
287	0x4b, 0x298,		/* PLL gain */
288};
289
290static void
291vpx3220_dump_i2c (struct i2c_client *client)
292{
293	int len = sizeof(init_common);
294	const unsigned char *data = init_common;
295
296	while (len > 1) {
297		dprintk(1,
298			KERN_DEBUG "vpx3216b i2c reg 0x%02x data 0x%02x\n",
299			*data, vpx3220_read(client, *data));
300		data += 2;
301		len -= 2;
302	}
303}
304
305static int
306vpx3220_command (struct i2c_client *client,
307		 unsigned int       cmd,
308		 void              *arg)
309{
310	struct vpx3220 *decoder = i2c_get_clientdata(client);
311
312	switch (cmd) {
313	case 0:
314	{
315		vpx3220_write_block(client, init_common,
316				    sizeof(init_common));
317		vpx3220_write_fp_block(client, init_fp,
318				       sizeof(init_fp) >> 1);
319		switch (decoder->norm) {
320
321		case VIDEO_MODE_NTSC:
322			vpx3220_write_fp_block(client, init_ntsc,
323					       sizeof(init_ntsc) >> 1);
324			break;
325
326		case VIDEO_MODE_PAL:
327			vpx3220_write_fp_block(client, init_pal,
328					       sizeof(init_pal) >> 1);
329			break;
330		case VIDEO_MODE_SECAM:
331			vpx3220_write_fp_block(client, init_secam,
332					       sizeof(init_secam) >> 1);
333			break;
334		default:
335			vpx3220_write_fp_block(client, init_pal,
336					       sizeof(init_pal) >> 1);
337			break;
338		}
339	}
340		break;
341
342	case DECODER_DUMP:
343	{
344		vpx3220_dump_i2c(client);
345	}
346		break;
347
348	case DECODER_GET_CAPABILITIES:
349	{
350		struct video_decoder_capability *cap = arg;
351
352		dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n",
353			I2C_NAME(client));
354
355		cap->flags = VIDEO_DECODER_PAL |
356			     VIDEO_DECODER_NTSC |
357			     VIDEO_DECODER_SECAM |
358			     VIDEO_DECODER_AUTO |
359			     VIDEO_DECODER_CCIR;
360		cap->inputs = 3;
361		cap->outputs = 1;
362	}
363		break;
364
365	case DECODER_GET_STATUS:
366	{
367		int res = 0, status;
368
369		dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n",
370			I2C_NAME(client));
371
372		status = vpx3220_fp_read(client, 0x0f3);
373
374		dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client),
375			status);
376
377		if (status < 0)
378			return status;
379
380		if ((status & 0x20) == 0) {
381			res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;
382
383			switch (status & 0x18) {
384
385			case 0x00:
386			case 0x10:
387			case 0x14:
388			case 0x18:
389				res |= DECODER_STATUS_PAL;
390				break;
391
392			case 0x08:
393				res |= DECODER_STATUS_SECAM;
394				break;
395
396			case 0x04:
397			case 0x0c:
398			case 0x1c:
399				res |= DECODER_STATUS_NTSC;
400				break;
401			}
402		}
403
404		*(int *) arg = res;
405	}
406		break;
407
408	case DECODER_SET_NORM:
409	{
410		int *iarg = arg, data;
411		int temp_input;
412
413		/* Here we back up the input selection because it gets
414		   overwritten when we fill the registers with the
415		   choosen video norm */
416		temp_input = vpx3220_fp_read(client, 0xf2);
417
418		dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n",
419			I2C_NAME(client), *iarg);
420		switch (*iarg) {
421
422		case VIDEO_MODE_NTSC:
423			vpx3220_write_fp_block(client, init_ntsc,
424					       sizeof(init_ntsc) >> 1);
425			dprintk(1, KERN_INFO "%s: norm switched to NTSC\n",
426				I2C_NAME(client));
427			break;
428
429		case VIDEO_MODE_PAL:
430			vpx3220_write_fp_block(client, init_pal,
431					       sizeof(init_pal) >> 1);
432			dprintk(1, KERN_INFO "%s: norm switched to PAL\n",
433				I2C_NAME(client));
434			break;
435
436		case VIDEO_MODE_SECAM:
437			vpx3220_write_fp_block(client, init_secam,
438					       sizeof(init_secam) >> 1);
439			dprintk(1, KERN_INFO "%s: norm switched to SECAM\n",
440				I2C_NAME(client));
441			break;
442
443		case VIDEO_MODE_AUTO:
444			data = vpx3220_fp_read(client, 0xf2) & 0x20;
445			vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
446			dprintk(1, KERN_INFO "%s: norm switched to Auto\n",
447				I2C_NAME(client));
448			break;
449
450		default:
451			return -EINVAL;
452
453		}
454		decoder->norm = *iarg;
455
456		/* And here we set the backed up video input again */
457		vpx3220_fp_write(client, 0xf2, temp_input | 0x0010);
458		udelay(10);
459	}
460		break;
461
462	case DECODER_SET_INPUT:
463	{
464		int *iarg = arg, data;
465
466		/* RJ:  *iarg = 0: ST8 (PCTV) input
467		 *iarg = 1: COMPOSITE  input
468		 *iarg = 2: SVHS       input  */
469
470		const int input[3][2] = {
471			{0x0c, 0},
472			{0x0d, 0},
473			{0x0e, 1}
474		};
475
476		if (*iarg < 0 || *iarg > 2)
477			return -EINVAL;
478
479		dprintk(1, KERN_INFO "%s: input switched to %s\n",
480			I2C_NAME(client), inputs[*iarg]);
481
482		vpx3220_write(client, 0x33, input[*iarg][0]);
483
484		data = vpx3220_fp_read(client, 0xf2) & ~(0x0020);
485		if (data < 0)
486			return data;
487		/* 0x0010 is required to latch the setting */
488		vpx3220_fp_write(client, 0xf2,
489				 data | (input[*iarg][1] << 5) | 0x0010);
490
491		udelay(10);
492	}
493		break;
494
495	case DECODER_SET_OUTPUT:
496	{
497		int *iarg = arg;
498
499		/* not much choice of outputs */
500		if (*iarg != 0) {
501			return -EINVAL;
502		}
503	}
504		break;
505
506	case DECODER_ENABLE_OUTPUT:
507	{
508		int *iarg = arg;
509
510		dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n",
511			I2C_NAME(client), *iarg);
512
513		vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
514	}
515		break;
516
517	case DECODER_SET_PICTURE:
518	{
519		struct video_picture *pic = arg;
520
521		if (decoder->bright != pic->brightness) {
522			/* We want -128 to 128 we get 0-65535 */
523			decoder->bright = pic->brightness;
524			vpx3220_write(client, 0xe6,
525				      (decoder->bright - 32768) >> 8);
526		}
527		if (decoder->contrast != pic->contrast) {
528			/* We want 0 to 64 we get 0-65535 */
529			/* Bit 7 and 8 is for noise shaping */
530			decoder->contrast = pic->contrast;
531			vpx3220_write(client, 0xe7,
532				      (decoder->contrast >> 10) + 192);
533		}
534		if (decoder->sat != pic->colour) {
535			/* We want 0 to 4096 we get 0-65535 */
536			decoder->sat = pic->colour;
537			vpx3220_fp_write(client, 0xa0,
538					 decoder->sat >> 4);
539		}
540		if (decoder->hue != pic->hue) {
541			/* We want -512 to 512 we get 0-65535 */
542			decoder->hue = pic->hue;
543			vpx3220_fp_write(client, 0x1c,
544					 ((decoder->hue - 32768) >> 6) & 0xFFF);
545		}
546	}
547		break;
548
549	default:
550		return -EINVAL;
551	}
552
553	return 0;
554}
555
556static int
557vpx3220_init_client (struct i2c_client *client)
558{
559	vpx3220_write_block(client, init_common, sizeof(init_common));
560	vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1);
561	/* Default to PAL */
562	vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1);
563
564	return 0;
565}
566
567/* -----------------------------------------------------------------------
568 * Client managment code
569 */
570
571/*
572 * Generic i2c probe
573 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
574 */
575static unsigned short normal_i2c[] =
576    { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
577	I2C_CLIENT_END
578};
579
580static unsigned short ignore = I2C_CLIENT_END;
581
582static struct i2c_client_address_data addr_data = {
583	.normal_i2c		= normal_i2c,
584	.probe			= &ignore,
585	.ignore			= &ignore,
586};
587
588static struct i2c_driver vpx3220_i2c_driver;
589
590static int
591vpx3220_detach_client (struct i2c_client *client)
592{
593	struct vpx3220 *decoder = i2c_get_clientdata(client);
594	int err;
595
596	err = i2c_detach_client(client);
597	if (err) {
598		return err;
599	}
600
601	kfree(decoder);
602	kfree(client);
603
604	return 0;
605}
606
607static int
608vpx3220_detect_client (struct i2c_adapter *adapter,
609		       int                 address,
610		       int                 kind)
611{
612	int err;
613	struct i2c_client *client;
614	struct vpx3220 *decoder;
615
616	dprintk(1, VPX3220_DEBUG "%s\n", __func__);
617
618	/* Check if the adapter supports the needed features */
619	if (!i2c_check_functionality
620	    (adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
621		return 0;
622
623	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
624	if (client == NULL) {
625		return -ENOMEM;
626	}
627
628	client->addr = address;
629	client->adapter = adapter;
630	client->driver = &vpx3220_i2c_driver;
631
632	/* Check for manufacture ID and part number */
633	if (kind < 0) {
634		u8 id;
635		u16 pn;
636
637		id = vpx3220_read(client, 0x00);
638		if (id != 0xec) {
639			dprintk(1,
640				KERN_INFO
641				"vpx3220_attach: Wrong manufacturer ID (0x%02x)\n",
642				id);
643			kfree(client);
644			return 0;
645		}
646
647		pn = (vpx3220_read(client, 0x02) << 8) +
648		    vpx3220_read(client, 0x01);
649		switch (pn) {
650		case 0x4680:
651			strlcpy(I2C_NAME(client), "vpx3220a",
652				sizeof(I2C_NAME(client)));
653			break;
654		case 0x4260:
655			strlcpy(I2C_NAME(client), "vpx3216b",
656				sizeof(I2C_NAME(client)));
657			break;
658		case 0x4280:
659			strlcpy(I2C_NAME(client), "vpx3214c",
660				sizeof(I2C_NAME(client)));
661			break;
662		default:
663			dprintk(1,
664				KERN_INFO
665				"%s: Wrong part number (0x%04x)\n",
666				__func__, pn);
667			kfree(client);
668			return 0;
669		}
670	} else {
671		strlcpy(I2C_NAME(client), "forced vpx32xx",
672			sizeof(I2C_NAME(client)));
673	}
674
675	decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
676	if (decoder == NULL) {
677		kfree(client);
678		return -ENOMEM;
679	}
680	decoder->norm = VIDEO_MODE_PAL;
681	decoder->input = 0;
682	decoder->enable = 1;
683	decoder->bright = 32768;
684	decoder->contrast = 32768;
685	decoder->hue = 32768;
686	decoder->sat = 32768;
687	i2c_set_clientdata(client, decoder);
688
689	err = i2c_attach_client(client);
690	if (err) {
691		kfree(client);
692		kfree(decoder);
693		return err;
694	}
695
696	dprintk(1, KERN_INFO "%s: vpx32xx client found at address 0x%02x\n",
697		I2C_NAME(client), client->addr << 1);
698
699	vpx3220_init_client(client);
700
701	return 0;
702}
703
704static int
705vpx3220_attach_adapter (struct i2c_adapter *adapter)
706{
707	int ret;
708
709	ret = i2c_probe(adapter, &addr_data, &vpx3220_detect_client);
710	dprintk(1, VPX3220_DEBUG "%s: i2c_probe returned %d\n",
711		__func__, ret);
712	return ret;
713}
714
715/* -----------------------------------------------------------------------
716 * Driver initialization and cleanup code
717 */
718
719static struct i2c_driver vpx3220_i2c_driver = {
720	.driver = {
721		.name = "vpx3220",
722	},
723
724	.id = I2C_DRIVERID_VPX3220,
725
726	.attach_adapter = vpx3220_attach_adapter,
727	.detach_client = vpx3220_detach_client,
728	.command = vpx3220_command,
729};
730
731static int __init
732vpx3220_init (void)
733{
734	return i2c_add_driver(&vpx3220_i2c_driver);
735}
736
737static void __exit
738vpx3220_cleanup (void)
739{
740	i2c_del_driver(&vpx3220_i2c_driver);
741}
742
743module_init(vpx3220_init);
744module_exit(vpx3220_cleanup);
745
746MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
747MODULE_AUTHOR("Laurent Pinchart");
748MODULE_LICENSE("GPL");
749