1 /*
2    saa7114h - Philips SAA7114H video decoder driver
3 
4    Copyright (C) 2001,2002,2003 Broadcom Corporation
5 
6    From saa7111.c:
7      Copyright (C) 1998 Dave Perks <dperks@ibm.net>
8    From cpia.c:
9      (C) Copyright 1999-2000 Peter Pregler
10      (C) Copyright 1999-2000 Scott J. Bertin
11      (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
12 
13    This program is free software; you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation; either version 2 of the License, or
16    (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
21    GNU General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 
28 /*
29  * Important note: this driver is reasonably functional, and has been
30  * tested with the "camserv" v4l application.  But it primarily a
31  * proof-of-concept, and example for setting up FIFO-mode.
32  */
33 
34 #include <linux/init.h>
35 #include <linux/module.h>
36 #include <linux/delay.h>
37 #include <linux/errno.h>
38 #include <linux/ctype.h>
39 #include <linux/fs.h>
40 #include <linux/vmalloc.h>
41 #include <linux/kernel.h>
42 #include <linux/major.h>
43 #include <linux/slab.h>
44 #include <linux/mm.h>
45 #include <linux/pci.h>
46 #include <linux/signal.h>
47 #include <linux/proc_fs.h>
48 #include <asm/io.h>
49 #include <asm/pgtable.h>
50 #include <asm/page.h>
51 #include <linux/sched.h>
52 #include <asm/segment.h>
53 #include <linux/types.h>
54 #include <linux/wrapper.h>
55 #include <linux/smp_lock.h>
56 #include <asm/hardirq.h>
57 
58 #include <linux/i2c.h>
59 #include <linux/videodev.h>
60 #include <linux/version.h>
61 #include <asm/uaccess.h>
62 
63 #include <linux/i2c-algo-sibyte.h>
64 
65 #include <asm/sibyte/64bit.h>
66 #include <asm/sibyte/sb1250_regs.h>
67 #include <asm/sibyte/sb1250_int.h>
68 #include <asm/sibyte/sb1250_mac.h>
69 #include <asm/sibyte/sb1250_dma.h>
70 
71 #define SAA_BRIGHTNESS	 0x0a
72 #define SAA_CONTRAST	 0x0b
73 #define SAA_SATURATION	 0x0c
74 #define SAA_HUE		 0x0d
75 
76 #define DECODER_STATUS	 0x1f
77 #define SLICER_STATUS_0	 0x60
78 #define SLICER_STATUS_1	 0x61
79 #define SLICER_STATUS_2	 0x62
80 #define SCALER_STATUS	 0x8f
81 
82 #define NUM_FRAME	 2
83 #define MAX_HORIZ	 720
84 #define MAX_VERT	 480
85 #define MIN_HORIZ	 180
86 #define MIN_VERT	 120
87 #define MAX_PER_PIXEL	 3
88 #define MAX_FRAME_SIZE	 (MAX_HORIZ*MAX_VERT*MAX_PER_PIXEL)
89 #define MAX_MMAP_SIZE	 (PAGE_ALIGN(MAX_FRAME_SIZE*NUM_FRAME))
90 #define RAW_PER_PIXEL	 2
91 #define RAW_LINE_PAD	 8
92 #define RAW_LINE_SIZE	 (((MAX_HORIZ*RAW_PER_PIXEL)+RAW_LINE_PAD+0x1f) & ~0x1f)
93 #define RAW_FRAME_SIZE	 (RAW_LINE_SIZE*MAX_VERT)
94 
95 #define NUM_DESCR	 64
96 #define INTR_PKT_CNT	 8
97 
98 /* Extensions to videodev.h IOCTL definitions */
99 #define VIDIOREADREG	_IOR('v', 50, int)
100 #define VIDIOWRITEREG	_IOW('v', 50, int)
101 #define VIDIOGRABFRAME	_IOR('v', 51, int)
102 #define VIDIOSHOWEAV	_IOR('v', 52, int)
103 
104 #define IF_NAME "saa7114h"
105 
106 #define MAC2_CSR(r)	   (KSEG1 + A_MAC_REGISTER(2, r))
107 #define MAC2_DMARX0_CSR(r) (KSEG1 + A_MAC_DMA_REGISTER(2, DMA_RX, 0, r))
108 
109 /* Options */
110 #define DMA_DEINTERLACE	 1
111 #define LAZY_READ	 1
112 #define NULL_DMA	 0
113 
114 /* Debug filters */
115 #define DBG_NULL	 0x0000
116 #define DBG_IO		 0x0001
117 #define DBG_DESCR	 0x0002
118 #define DBG_INTR	 0x0004
119 #define DBG_CONVERT	 0x0008
120 #define DBG_FRAMING	 0x0010
121 #define DBG_REGISTER	 0x0020
122 #define DBG_CALL	 0x0040
123 #define DBG_FRAMING_LOUD 0x0080
124 
125 /* XXXKW make this settable through /proc... */
126 #define DEBUG_LVL	 (DBG_NULL)
127 
128 #if DEBUG_LVL
129 #define DBG(l, p) do { if (DEBUG_LVL & l) p; } while (0)
130 #else
131 #define DBG(l, p)
132 #endif
133 
134 /* ----------------------------------------------------------------------- */
135 
136 enum {
137 	FRAME_READY,		/* Ready to grab into */
138 	FRAME_GRABBING,		/* In the process of being grabbed into */
139 	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
140 	FRAME_UNUSED,		/* Unused (belongs to driver, but can't be used) */
141 };
142 
143 struct saa_frame {
144 	uint8_t		 *data;
145 	uint8_t		 *pos;
146 	int		  width;
147 	int		  height;
148 	uint32_t	  size;
149 	volatile int	  state;
150 	wait_queue_head_t read_wait;
151 };
152 
153 typedef struct fifo_descr_s {
154 	uint64_t descr_a;
155 	uint64_t descr_b;
156 } fifo_descr_t;
157 
158 typedef unsigned long paddr_t;
159 
160 typedef struct fifo_s {
161 	unsigned	 ringsz;
162 	fifo_descr_t	*descrtab;
163 	fifo_descr_t	*descrtab_end;
164 	fifo_descr_t	*next_descr;
165 	paddr_t		 descrtab_phys;
166 	void		*dma_buf;	    /* DMA buffer */
167 } fifo_t;
168 
169 struct saa7114h {
170 	struct i2c_client    *client;
171 	struct video_device  *vd;
172 	struct video_window   vw;
173 	struct video_picture  vp;
174 	uint8_t		      reg[256];
175 
176 	fifo_t		 ff;
177 	void		*frame_buf; /* hold frames for the client */
178 	struct saa_frame frame[NUM_FRAME]; /* point into frame_buf */
179 	int		 hwframe;
180 	int		 swframe;
181 
182 	uint16_t depth;
183 	uint16_t palette;
184 	uint8_t	 bright;
185 	uint8_t	 contrast;
186 	uint8_t	 hue;
187 	uint8_t	 sat;
188 
189 	struct proc_dir_entry *proc_entry;
190 	struct semaphore       param_lock;
191 	struct semaphore       busy_lock;
192 
193 	int	dma_enable;
194 	int	opened;
195 	int	irq;
196 	int	interlaced;
197 };
198 
199 static int saa7114h_probe(struct i2c_adapter *adap);
200 static int saa7114h_detach(struct i2c_client *device);
201 
202 struct i2c_driver i2c_driver_saa7114h =
203 {
204 	name:		"saa7114h",		/* name */
205 	id:		I2C_DRIVERID_SAA7114H,	/* ID */
206 	flags:		I2C_DF_NOTIFY,		/* XXXKW do I care? */
207 	attach_adapter: saa7114h_probe,
208 	detach_client:	saa7114h_detach
209 };
210 
211 /* -----------------------------------------------------------------------
212  * VM assist for MMAPed space
213  * ----------------------------------------------------------------------- */
214 
215 /* Given PGD from the address space's page table, return the kernel
216  * virtual mapping of the physical memory mapped at ADR.
217  */
uvirt_to_kva(pgd_t * pgd,unsigned long adr)218 static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
219 {
220 	unsigned long ret = 0UL;
221 	pmd_t *pmd;
222 	pte_t *ptep, pte;
223 
224 	if (!pgd_none(*pgd)) {
225 		pmd = pmd_offset(pgd, adr);
226 		if (!pmd_none(*pmd)) {
227 			ptep = pte_offset(pmd, adr);
228 			pte = *ptep;
229 			if (pte_present(pte)) {
230 				ret = (unsigned long) page_address(pte_page(pte));
231 				ret |= (adr & (PAGE_SIZE-1));
232 			}
233 		}
234 	}
235 	return ret;
236 }
237 
238 /* Here we want the physical address of the memory.
239  * This is used when initializing the contents of the
240  * area and marking the pages as reserved.
241  */
kvirt_to_pa(unsigned long adr)242 static inline unsigned long kvirt_to_pa(unsigned long adr)
243 {
244 	unsigned long va, kva, ret;
245 
246 	va = VMALLOC_VMADDR(adr);
247 	kva = uvirt_to_kva(pgd_offset_k(va), va);
248 	ret = __pa(kva);
249 	return ret;
250 }
251 
rvmalloc(unsigned long size)252 static void *rvmalloc(unsigned long size)
253 {
254 	void *mem;
255 	unsigned long adr, page;
256 
257 	/* Round it off to PAGE_SIZE */
258 	size += (PAGE_SIZE - 1);
259 	size &= ~(PAGE_SIZE - 1);
260 
261 	mem = vmalloc_32(size);
262 	if (!mem)
263 		return NULL;
264 
265 	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
266 	adr = (unsigned long) mem;
267 	while (size > 0) {
268 		page = kvirt_to_pa(adr);
269 		mem_map_reserve(virt_to_page(__va(page)));
270 		adr += PAGE_SIZE;
271 		if (size > PAGE_SIZE)
272 			size -= PAGE_SIZE;
273 		else
274 			size = 0;
275 	}
276 
277 	return mem;
278 }
279 
rvfree(void * mem,unsigned long size)280 static void rvfree(void *mem, unsigned long size)
281 {
282 	unsigned long adr, page;
283 
284 	if (!mem)
285 		return;
286 
287 	size += (PAGE_SIZE - 1);
288 	size &= ~(PAGE_SIZE - 1);
289 
290 	adr = (unsigned long) mem;
291 	while (size > 0) {
292 		page = kvirt_to_pa(adr);
293 		mem_map_unreserve(virt_to_page(__va(page)));
294 		adr += PAGE_SIZE;
295 		if (size > PAGE_SIZE)
296 			size -= PAGE_SIZE;
297 		else
298 			size = 0;
299 	}
300 	vfree(mem);
301 }
302 
303 /* -----------------------------------------------------------------------
304  * Control interface (i2c)
305  * ----------------------------------------------------------------------- */
306 
saa7114h_reg_read(struct saa7114h * dev,unsigned char subaddr)307 static int saa7114h_reg_read(struct saa7114h *dev, unsigned char subaddr)
308 {
309 	return i2c_smbus_read_byte_data(dev->client, subaddr);
310 }
311 
saa7114h_reg_write(struct saa7114h * dev,unsigned char subaddr,int data)312 static int saa7114h_reg_write(struct saa7114h *dev, unsigned char subaddr, int data)
313 {
314 	return i2c_smbus_write_byte_data(dev->client, subaddr, data & 0xff);
315 }
316 
saa7114h_reg_init(struct saa7114h * dev,unsigned const char * data,unsigned int len)317 static int saa7114h_reg_init(struct saa7114h *dev, unsigned const char *data, unsigned int len)
318 {
319 	int rc = 0;
320 	int val;
321 
322 	while (len && !rc) {
323 		dev->reg[data[0]] = data[1];
324 		rc = saa7114h_reg_write(dev, data[0], data[1]);
325 		if (!rc && (data[0] != 0)) {
326 			val = saa7114h_reg_read(dev, data[0]);
327 			if ((val < 0) || (val != data[1])) {
328 				printk(KERN_ERR
329 				       IF_NAME ": init readback mismatch reg %02x = %02x (should be %02x)\n",
330 				       data[0], val, data[1]);
331 			}
332 		}
333 		len -= 2;
334 		data += 2;
335 	}
336 	return rc;
337 }
338 
339 /* -----------------------------------------------------------------------
340  * /proc interface
341  * ----------------------------------------------------------------------- */
342 
343 #ifdef CONFIG_PROC_FS
344 static struct proc_dir_entry *saa7114h_proc_root=NULL;
345 
decoder_read_proc(char * page,char ** start,off_t off,int count,int * eof,void * data)346 static int decoder_read_proc(char *page, char **start, off_t off,
347 			     int count, int *eof, void *data)
348 {
349 	char *out = page;
350 	int len, status;
351 	struct saa7114h *decoder = data;
352 
353 	out += sprintf(out, "  SWARM saa7114h\n------------------\n");
354 	status = saa7114h_reg_read(decoder, DECODER_STATUS);
355 	out += sprintf(out, "  Decoder status = %02x\n", status);
356 	if (status & 0x80)
357 		out += sprintf(out, "	 interlaced\n");
358 	if (status & 0x40)
359 		out += sprintf(out, "	 not locked\n");
360 	if (status & 0x02)
361 		out += sprintf(out, "	 Macrovision detected\n");
362 	if (status & 0x01)
363 		out += sprintf(out, "	 color\n");
364 	out += sprintf(out, "  Brightness = %02x\n", decoder->bright);
365 	out += sprintf(out, "  Contrast	  = %02x\n", decoder->contrast);
366 	out += sprintf(out, "  Saturation = %02x\n", decoder->sat);
367 	out += sprintf(out, "  Hue	  = %02x\n\n", decoder->hue);
368 
369 	out += sprintf(out, "  Scaler status  = %02x\n",
370 		       (int)saa7114h_reg_read(decoder, SCALER_STATUS));
371 
372 	len = out - page;
373 	len -= off;
374 	if (len < count) {
375 		*eof = 1;
376 		if (len <= 0) return 0;
377 	} else
378 		len = count;
379 
380 	*start = page + off;
381 	return len;
382 }
383 
decoder_write_proc(struct file * file,const char * buffer,unsigned long count,void * data)384 static int decoder_write_proc(struct file *file, const char *buffer,
385 			       unsigned long count, void *data)
386 {
387 	struct saa7114h *d = data;
388 	int retval;
389 	unsigned int cmd, reg, reg_val;
390 
391 	if (down_interruptible(&d->param_lock))
392 		return -ERESTARTSYS;
393 
394 #define VALUE \
395 	({ \
396 		char *_p; \
397 		unsigned long int _ret; \
398 		while (count && isspace(*buffer)) { \
399 			buffer++; \
400 			count--; \
401 		} \
402 		_ret = simple_strtoul(buffer, &_p, 16); \
403 		if (_p == buffer) \
404 			retval = -EINVAL; \
405 		else { \
406 			count -= _p - buffer; \
407 			buffer = _p; \
408 		} \
409 		_ret; \
410 	})
411 
412 	retval = 0;
413 	while (count && !retval) {
414 		cmd = VALUE;
415 		if (retval)
416 			break;
417 		switch (cmd) {
418 		case 1:
419 			reg = VALUE;
420 			if (retval)
421 				break;
422 			reg_val = VALUE;
423 			if (retval)
424 				break;
425 			printk(IF_NAME ": write reg %x <- %x\n", reg, reg_val);
426 			if (saa7114h_reg_write(d, reg, reg_val) == -1)
427 				retval = -EINVAL;
428 			break;
429 		case 2:
430 			reg = VALUE;
431 			if (retval)
432 				break;
433 			reg_val = saa7114h_reg_read(d, reg);
434 			if (reg_val == -1)
435 				retval = -EINVAL;
436 			else
437 				printk(IF_NAME ": read reg %x -> %x\n", reg, reg_val);
438 			break;
439 		default:
440 			break;
441 		}
442 	}
443 	up(&d->param_lock);
444 
445 	return retval;
446 }
447 
create_proc_decoder(struct saa7114h * decoder)448 static void create_proc_decoder(struct saa7114h *decoder)
449 {
450 	char name[8];
451 	struct proc_dir_entry *ent;
452 
453 	if (!saa7114h_proc_root || !decoder)
454 		return;
455 
456 	sprintf(name, "video%d", decoder->vd->minor);
457 
458 	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, saa7114h_proc_root);
459 	if (!ent) {
460 		printk(KERN_INFO IF_NAME ": Unable to initialize /proc/saa7114h/%s\n", name);
461 		return;
462 	}
463 
464 	ent->data = decoder;
465 	ent->read_proc = decoder_read_proc;
466 	ent->write_proc = decoder_write_proc;
467 	ent->size = 3626;	/* XXXKW ??? */
468 	decoder->proc_entry = ent;
469 }
470 
destroy_proc_decoder(struct saa7114h * decoder)471 static void destroy_proc_decoder(struct saa7114h *decoder)
472 {
473 	char name[7];
474 
475 	if (!decoder || !decoder->proc_entry)
476 		return;
477 
478 	sprintf(name, "video%d", decoder->vd->minor);
479 	remove_proc_entry(name, saa7114h_proc_root);
480 	decoder->proc_entry = NULL;
481 }
482 
proc_saa7114h_create(void)483 static void proc_saa7114h_create(void)
484 {
485 	saa7114h_proc_root = create_proc_entry("saa7114h", S_IFDIR, 0);
486 
487 	if (saa7114h_proc_root)
488 		saa7114h_proc_root->owner = THIS_MODULE;
489 	else
490 		printk(KERN_INFO IF_NAME ": Unable to initialize /proc/saa7114h\n");
491 }
492 
proc_saa7114h_destroy(void)493 static void proc_saa7114h_destroy(void)
494 {
495 	remove_proc_entry("saa7114h", 0);
496 }
497 #endif /* CONFIG_PROC_FS */
498 
499 
500 /* -----------------------------------------------------------------------
501  * Initialization
502  * ----------------------------------------------------------------------- */
503 
dma_setup(struct saa7114h * d)504 static int dma_setup(struct saa7114h *d)
505 {
506 	int i;
507 	void *curbuf;
508 
509 	/* Reset the port */
510 	out64(M_MAC_PORT_RESET, MAC2_CSR(R_MAC_ENABLE));
511 	in64(MAC2_CSR(R_MAC_ENABLE));
512 
513 	/* Zero everything out, disable filters */
514 	out64(0, MAC2_CSR(R_MAC_TXD_CTL));
515 	out64(M_MAC_ALLPKT_EN, MAC2_CSR(R_MAC_ADFILTER_CFG));
516 	out64(V_MAC_RX_RD_THRSH(4) | V_MAC_RX_RL_THRSH(4),
517 	      MAC2_CSR(R_MAC_THRSH_CFG));
518 	for (i=0; i<MAC_CHMAP_COUNT; i++) {
519 		out64(0, MAC2_CSR(R_MAC_CHLO0_BASE+(i*8)));
520 		out64(0, MAC2_CSR(R_MAC_CHUP0_BASE+(i*8)));
521 	}
522 	for (i=0; i<MAC_HASH_COUNT; i++) {
523 		out64(0, MAC2_CSR(R_MAC_HASH_BASE+(i*8)));
524 	}
525 	for (i=0; i<MAC_ADDR_COUNT; i++) {
526 		out64(0, MAC2_CSR(R_MAC_ADDR_BASE+(i*8)));
527 	}
528 
529 	out64(V_MAC_MAX_FRAMESZ(16*1024) | V_MAC_MIN_FRAMESZ(0),
530 	      MAC2_CSR(R_MAC_FRAMECFG));
531 
532 	/* Select bypass mode */
533 	out64((M_MAC_BYPASS_SEL | V_MAC_BYPASS_CFG(K_MAC_BYPASS_EOP) |
534 	       M_MAC_FC_SEL | M_MAC_SS_EN | V_MAC_SPEED_SEL_1000MBPS),
535 	      MAC2_CSR(R_MAC_CFG));
536 
537 	/* Set up the descriptor table */
538 	d->ff.descrtab = kmalloc(NUM_DESCR * sizeof(fifo_descr_t), GFP_KERNEL);
539 	d->ff.descrtab_phys = __pa(d->ff.descrtab);
540 	d->ff.descrtab_end = d->ff.descrtab + NUM_DESCR;
541 	d->ff.next_descr = d->ff.descrtab;
542 	d->ff.ringsz = NUM_DESCR;
543 #if 0
544 	/* XXXKW this won't work because the physical may not be
545 	   contiguous; how do I handle a bigger alloc then? */
546 	d->ff.dma_buf = rvmalloc(RAW_LINE_SIZE*NUM_DESCR);
547 	printk(KERN_DEBUG IF_NAME ": DMA buffer allocated (%p)\n",
548 	       d->ff.dma_buf);
549 #else
550 	d->ff.dma_buf = kmalloc(RAW_LINE_SIZE*NUM_DESCR, GFP_KERNEL);
551 #endif
552 	if (!d->ff.dma_buf) {
553 		printk(KERN_ERR IF_NAME ": couldn't allocate DMA buffer\n");
554 		return -ENOMEM;
555 	}
556 	memset(d->ff.dma_buf, 0, RAW_LINE_SIZE*NUM_DESCR);
557 
558 	for (i=0, curbuf=d->ff.dma_buf; i<d->ff.ringsz; i++, curbuf+=RAW_LINE_SIZE) {
559 		d->ff.descrtab[i].descr_a = (__pa(curbuf) |
560 					     V_DMA_DSCRA_A_SIZE(RAW_LINE_SIZE >> 5));
561 		d->ff.descrtab[i].descr_b = 0;
562 	}
563 
564 	out64(V_DMA_INT_PKTCNT(INTR_PKT_CNT) | M_DMA_EOP_INT_EN |
565 	      V_DMA_RINGSZ(d->ff.ringsz) | M_DMA_TDX_EN,
566 	      MAC2_DMARX0_CSR(R_MAC_DMA_CONFIG0));
567 	out64(M_DMA_L2CA, MAC2_DMARX0_CSR(R_MAC_DMA_CONFIG1));
568 	out64(d->ff.descrtab_phys, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_BASE));
569 
570 	/* Enable interrupts and DMA */
571 	out64(M_MAC_INT_EOP_COUNT<<S_MAC_RX_CH0, MAC2_CSR(R_MAC_INT_MASK));
572 	out64(M_MAC_RXDMA_EN0 | M_MAC_BYP_RX_ENABLE, MAC2_CSR(R_MAC_ENABLE));
573 
574 	return 0;
575 }
576 
577 /* -----------------------------------------------------------------------
578  * v4linux helpers - color conversion, etc  (taken from cpia.c)
579  * ----------------------------------------------------------------------- */
580 
581 #define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
582 
yuvconvert_inplace(uint8_t * data,uint32_t in_uyvy,int out_fmt,int mmap)583 static void yuvconvert_inplace(uint8_t *data, uint32_t in_uyvy, int out_fmt, int mmap)
584 {
585 	int y, u, v, r, g, b, y1;
586 	uint8_t *src, *dst;
587 
588 	if (out_fmt == VIDEO_PALETTE_RGB24) {
589 		src = (uint8_t *)((int)data + in_uyvy);
590 		dst = (uint8_t *)((int)data + in_uyvy + (in_uyvy >> 1));
591 		DBG(DBG_CONVERT, printk(KERN_DEBUG "inplace: %p %p %p\n", data, src, dst));
592 		while (src > data) {
593 			if ((int)(src-data) < 4)
594 				break;
595 				//printk("freaky %p %p\n", src, data);
596 			y1 = (*(--src) - 16) * 76310;
597 			v = *(--src) - 128;
598 			y = (*(--src) - 16) * 76310;
599 			u = *(--src) - 128;
600 			r = 104635 * v;
601 			g = -25690 * u + -53294 * v;
602 			b = 132278 * u;
603 			/* XXXKW what on earth is up with mmap? */
604 			if (mmap) {
605 				*(--dst) = LIMIT(r+y1);
606 				*(--dst) = LIMIT(g+y1);
607 				*(--dst) = LIMIT(b+y1);
608 				*(--dst) = LIMIT(r+y);
609 				*(--dst) = LIMIT(g+y);
610 				*(--dst) = LIMIT(b+y);
611 			} else {
612 				*(--dst) = LIMIT(b+y1);
613 				*(--dst) = LIMIT(g+y1);
614 				*(--dst) = LIMIT(r+y1);
615 				*(--dst) = LIMIT(b+y);
616 				*(--dst) = LIMIT(g+y);
617 				*(--dst) = LIMIT(r+y);
618 			}
619 		}
620 	}
621 }
622 
saa7114h_get_cparams(struct saa7114h * decoder)623 static int saa7114h_get_cparams(struct saa7114h *decoder)
624 {
625 	/* XXX check for error code */
626 	decoder->bright	    = saa7114h_reg_read(decoder, SAA_BRIGHTNESS);
627 	decoder->contrast   = saa7114h_reg_read(decoder, SAA_CONTRAST);
628 	decoder->sat	    = saa7114h_reg_read(decoder, SAA_SATURATION);
629 	decoder->hue	    = saa7114h_reg_read(decoder, SAA_HUE);
630 
631 	decoder->vp.brightness = (uint16_t)decoder->bright << 8;
632 	decoder->vp.contrast   = (uint16_t)decoder->contrast << 9;
633 	decoder->vp.colour     = decoder->sat << 9;
634 	decoder->vp.hue	       = ((int16_t)decoder->hue + 128) << 8;
635 	return 0;
636 }
637 
saa7114h_set_cparams(struct saa7114h * decoder)638 static int saa7114h_set_cparams(struct saa7114h *decoder)
639 {
640 	decoder->bright	  = decoder->vp.brightness >> 8;
641 	decoder->contrast = decoder->vp.contrast >> 9;
642 	decoder->sat	  = decoder->vp.colour >> 9;
643 	decoder->hue	  = (uint8_t)((int8_t)(decoder->vp.hue >> 8) - 128);
644 
645 	return (saa7114h_reg_write(decoder, SAA_BRIGHTNESS, decoder->bright) ||
646 		saa7114h_reg_write(decoder, SAA_CONTRAST, decoder->contrast) ||
647 		saa7114h_reg_write(decoder, SAA_SATURATION, decoder->sat) ||
648 		saa7114h_reg_write(decoder, SAA_HUE, decoder->hue));
649 }
650 
651 /* -----------------------------------------------------------------------
652  * Custom IOCTL support
653  * ----------------------------------------------------------------------- */
654 
655 unsigned char eav[625][2];
grab_frame(struct saa7114h * d,void * user_buf,int print_eav)656 static int grab_frame(struct saa7114h *d, void *user_buf, int print_eav)
657 {
658 	int cur_idx = 0;
659 	int to_go = 625;
660 	int delta;
661 	int i, len, eav_val, sav_val;
662 	int started = 0;
663 	uint8_t *buf;
664 	fifo_descr_t *cur_d;
665 	int swptr = d->ff.next_descr - d->ff.descrtab;
666 	int hwptr;
667 
668 	DBG(DBG_CALL, printk(IF_NAME ": grabbing frame\n"));
669 
670 	/* Check for Macrovision -- if it's on, DMA won't happen */
671 	if (saa7114h_reg_read(d, DECODER_STATUS) & 0x2)
672 		return -EACCES;
673 
674 	out64(d->ff.ringsz, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
675 	do {
676 		hwptr = (unsigned) (((in64(MAC2_DMARX0_CSR(R_MAC_DMA_CUR_DSCRADDR)) &
677 				      M_DMA_CURDSCR_ADDR) -
678 				     d->ff.descrtab_phys) /
679 				    sizeof(fifo_descr_t));
680 		delta = (hwptr + d->ff.ringsz - swptr) % d->ff.ringsz;
681 
682 		if (delta == 0) {
683 #if 0
684 			uint64_t val = in64(MAC2_DMARX0_CSR(R_MAC_STATUS));
685 			printk("mac status: %08x%08x\n",
686 			       (u32)(val >> 32), (u32)(val&0xffffffff));
687 #endif
688 		}
689 
690 		for (i=0; i<delta; i++) {
691 			cur_d = d->ff.next_descr;
692 			if (++d->ff.next_descr == d->ff.descrtab_end)
693 				d->ff.next_descr = d->ff.descrtab;
694 
695 			if (!(cur_d->descr_a & M_DMA_ETHRX_SOP)) {
696 				printk("bogus RX\n");
697 				continue;
698 			}
699 			cur_d->descr_a &= ~M_DMA_ETHRX_SOP;
700 			len = G_DMA_DSCRB_PKT_SIZE(cur_d->descr_b);
701 			buf = (uint8_t *)__va(cur_d->descr_a & M_DMA_DSCRA_A_ADDR);
702 			if (len != (d->vw.width*RAW_PER_PIXEL)+RAW_LINE_PAD) {
703 				printk("funny size %d\n", len);
704 				continue;
705 			}
706 			eav_val = buf[1];
707 			sav_val = buf[5];
708 			if (eav_val == 0xf1) { /* end of field 2, V-blank */
709 				if (started) {
710 					started = 0;
711 					delta = to_go = 0;
712 					/* just let DMA finish in background */
713 				} else {
714 					started = 1;
715 				}
716 			}
717 			if (started) {
718 				eav[cur_idx][0] = eav_val;
719 				eav[cur_idx++][1] = sav_val;
720 				if (copy_to_user(user_buf, &buf[6], 1440))
721 					return -EFAULT;
722 				user_buf += 1440;
723 			}
724 		}
725 		swptr = hwptr;
726 		if (delta) {
727 			if (started)
728 				to_go -= delta;
729 			if (delta > to_go)
730 				delta = to_go;
731 			out64(delta, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
732 		}
733 	} while (to_go);
734 
735 	if (print_eav) {
736 		for (i=0; i<cur_idx; i++) {
737 			printk("%3d: %02x | %02x\n", i, eav[i][0], eav[i][1]);
738 		}
739 	}
740 
741 	return cur_idx;
742 }
743 
744 /* -----------------------------------------------------------------------
745  * Interrupt handler
746  * ----------------------------------------------------------------------- */
747 
748 unsigned long int_count = 0;
749 
saa7114h_interrupt(int irq,void * dev_id,struct pt_regs * regs)750 static void saa7114h_interrupt(int irq, void *dev_id, struct pt_regs *regs)
751 {
752 	struct saa7114h *d = dev_id;
753 	uint64_t status_val;
754 	fifo_descr_t *cur_d;
755 	int i, delta, len;
756 	uint8_t *buf, eav_val;
757 	int swptr = d->ff.next_descr - d->ff.descrtab;
758 	int hwptr;
759 
760 	status_val = in64(MAC2_CSR(R_MAC_STATUS));
761 
762 	/* Process finished decsriptors */
763 	hwptr = (unsigned) (((in64(MAC2_DMARX0_CSR(R_MAC_DMA_CUR_DSCRADDR)) &
764 			      M_DMA_CURDSCR_ADDR) - d->ff.descrtab_phys) /
765 			    sizeof(fifo_descr_t));
766 	delta = (hwptr + d->ff.ringsz - swptr) % d->ff.ringsz;
767 	if (!delta) {
768 		if (status_val & M_MAC_INT_EOP_SEEN<<S_MAC_RX_CH0) {
769 			/* Must have wrapped since the last interrupt */
770 			delta = d->ff.ringsz;
771 		} else {
772 			/* XXXKW why would this happen? */
773 			return;
774 		}
775 	}
776 
777 	for (i=0; i<delta; i++) {
778 		cur_d = d->ff.next_descr;
779 		if (++d->ff.next_descr == d->ff.descrtab_end)
780 			d->ff.next_descr = d->ff.descrtab;
781 
782 		if (!(cur_d->descr_a & M_DMA_ETHRX_SOP)) {
783 			printk(KERN_DEBUG "bogus RX\n");
784 			continue;
785 		}
786 		cur_d->descr_a &= ~M_DMA_ETHRX_SOP;
787 		if (!d->dma_enable)
788 			continue;
789 
790 		len = G_DMA_DSCRB_PKT_SIZE(cur_d->descr_b);
791 		buf = (uint8_t *)__va(cur_d->descr_a & M_DMA_DSCRA_A_ADDR);
792 		if (len != (d->vw.width*RAW_PER_PIXEL)+RAW_LINE_PAD) {
793 			printk(KERN_DEBUG "funny size %d\n", len);
794 //				  continue;
795 		}
796 		len -= RAW_LINE_PAD;
797 		eav_val = buf[1];
798 		DBG(DBG_FRAMING_LOUD,
799 		    printk(KERN_DEBUG "eav: %02x len: %d\n", eav_val, len));
800 		if (eav_val == 0xf1) { /* end of field 2, V-blank: start-of-frame */
801 			switch (d->frame[d->hwframe].state) {
802 			case FRAME_UNUSED:
803 				DBG(DBG_FRAMING,
804 				    printk(KERN_ERR "capture to unused frame %d\n",
805 					   d->hwframe));
806 				break;
807 			case FRAME_READY:
808 				DBG(DBG_FRAMING,
809 				    printk(KERN_DEBUG "frame started %d\n",
810 					   d->hwframe));
811 				/* start this frame (skip eav/sav) */
812 				memcpy(d->frame[d->hwframe].pos, &buf[6], len);
813 #if DMA_DEINTERLACE
814 				if (!d->interlaced)
815 					memcpy(d->frame[d->hwframe].pos-len, &buf[6], len);
816 				d->frame[d->hwframe].pos += len*2;
817 #else
818 				d->frame[d->hwframe].pos += len;
819 #endif
820 				d->frame[d->hwframe].state = FRAME_GRABBING;
821 				/* XXXKW check pos overflow */
822 				break;
823 			case FRAME_GRABBING:
824 				/* kick over to new frame */
825 				d->frame[d->hwframe].size = d->frame[d->hwframe].pos -
826 					d->frame[d->hwframe].data;
827 				d->frame[d->hwframe].state = FRAME_DONE;
828 				DBG(DBG_FRAMING,
829 				    printk(KERN_DEBUG "frame finished %d\n",
830 					   d->frame[d->hwframe].size));
831 				/* wake up a waiting reader */
832 				DBG(DBG_IO, printk(KERN_DEBUG "wakeup\n"));
833 				wake_up(&d->frame[d->hwframe].read_wait);
834 				d->hwframe = (d->hwframe + 1) % NUM_FRAME;
835 				if (d->frame[d->hwframe].state == FRAME_READY) {
836 					/* start this frame */
837 					DBG(DBG_FRAMING,
838 					    printk(KERN_DEBUG "frame bumped %d\n",
839 						   d->hwframe));
840 					memcpy(d->frame[d->hwframe].pos, &buf[6], len);
841 #if DMA_DEINTERLACE
842 					if (!d->interlaced)
843 						memcpy(d->frame[d->hwframe].pos-len, &buf[6], len);
844 					d->frame[d->hwframe].pos += len*2;
845 #else
846 					d->frame[d->hwframe].pos += len;
847 #endif
848 					d->frame[d->hwframe].state = FRAME_GRABBING;
849 				} else {
850 					/* drop on the floor,
851 					   note that we've stopped DMA'ing */
852 					DBG(DBG_FRAMING,
853 					    printk(KERN_DEBUG "frame capture halted\n"));
854 					d->dma_enable = 0;
855 				}
856 				break;
857 			case FRAME_DONE:
858 				/* drop on the floor (must be waiting for sw) */
859 				DBG(DBG_FRAMING,
860 				    printk(KERN_DEBUG "frame capture halted\n"));
861 				d->dma_enable = 0;
862 				break;
863 			}
864 		} else {
865 			switch (d->frame[d->hwframe].state) {
866 			case FRAME_UNUSED:
867 				DBG(DBG_FRAMING,
868 				    printk(KERN_ERR "capture to unused frame %d\n",
869 					   d->hwframe));
870 				break;
871 			case FRAME_READY:
872 				/* drop on the floor (must have dropped something) */
873 				DBG(DBG_FRAMING_LOUD,
874 				    printk(KERN_DEBUG "missed SOF\n"));
875 				break;
876 			case FRAME_DONE:
877 				/* drop on the floor (must be waiting for sw) */
878 				DBG(DBG_FRAMING,
879 				    printk(KERN_DEBUG "frame overflow\n"));
880 				d->dma_enable = 0;
881 				break;
882 			case FRAME_GRABBING:
883 #if DMA_DEINTERLACE
884 				if (eav_val == 0xb6) {
885 					d->frame[d->hwframe].pos = d->frame[d->hwframe].data;
886 				}
887 				memcpy(d->frame[d->hwframe].pos, &buf[6], len);
888 				if (!d->interlaced)
889 					memcpy(d->frame[d->hwframe].pos-len, &buf[6], len);
890 				d->frame[d->hwframe].pos += len*2;
891 #else
892 				memcpy(d->frame[d->hwframe].pos, &buf[6], len);
893 				d->frame[d->hwframe].pos += len;
894 #endif
895 				/* XXXKW check pos overflow */
896 				break;
897 			}
898 		}
899 	}
900 
901 	if (d->dma_enable) {
902 		out64(delta, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
903 		DBG(DBG_DESCR,
904 		    printk(KERN_DEBUG IF_NAME ": interrupt adds %d -> %d descrs\n",
905 			   delta, (int)in64(MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT))));
906 	}
907 }
908 
909 /* -----------------------------------------------------------------------
910  * /dev/video interface
911  * ----------------------------------------------------------------------- */
912 
saa7114h_open(struct video_device * vd,int nb)913 static int saa7114h_open(struct video_device *vd, int nb)
914 {
915 	struct saa7114h *d = vd->priv;
916 	uint32_t status;
917 
918 	if (!d || d->opened)
919 		return -EBUSY;
920 
921 	d->opened = 1;
922 	DBG(DBG_CALL, printk(KERN_DEBUG IF_NAME ": open\n"));
923 
924 	/* XXKW Should check this periodically!? */
925 	status = saa7114h_reg_read(d, DECODER_STATUS);
926 	d->interlaced = ((status & 0x80) != 0);
927 
928 #if !NULL_DMA
929 	if (d->dma_enable) {
930 		printk(IF_NAME ": open found DMA on?!\n");
931 #if LAZY_READ
932 	}
933 #else
934 	} else {
935 		int descr;
936 		d->dma_enable = 1;
937 		DBG(DBG_DESCR, printk(IF_NAME ": open enabling DMA\n"));
938 		/* Force capture to start into frame buffer 0 */
939 		descr = in64(MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
940 		DBG(DBG_DESCR,
941 		    printk(IF_NAME ": open adds %d -> %d descrs\n",
942 			   d->ff.ringsz-desc, descr));
943 		out64(d->ff.ringsz-descr, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
944 	}
945 #endif
946 #endif
947 
948 	return 0;
949 }
950 
saa7114h_release(struct video_device * vd)951 static void saa7114h_release(struct video_device *vd)
952 {
953 	struct saa7114h *d = vd->priv;
954 
955 	DBG(DBG_CALL, printk(KERN_DEBUG IF_NAME ": release\n"));
956 	d->opened = 0;
957 	d->dma_enable = 0;
958 
959 	/* XXXKW do a clean drain of outstanding DMAs? toss leftover
960 	   buffer contents to avoid stale pictures? */
961 
962 	return;
963 }
964 
saa7114h_read(struct video_device * vd,char * buf,unsigned long count,int noblock)965 static long saa7114h_read(struct video_device *vd, char *buf,
966 			  unsigned long count, int noblock)
967 {
968 	struct saa7114h *d = vd->priv;
969 	int descr, status;
970 
971 	if (!d)
972 		return -ENODEV;
973 
974 	/* XXKW Should check this periodically!? */
975 	status = saa7114h_reg_read(d, DECODER_STATUS);
976 //	  d->interlaced = ((status & 0x80) != 0);
977 
978 #if !NULL_DMA
979 #if LAZY_READ
980 	if (!d->dma_enable) {
981 		DBG(DBG_DESCR, printk(KERN_DEBUG IF_NAME ": enabling DMA\n"));
982 		/* Give the buffer to the DMA engine (force ptr reset) */
983 		d->swframe = d->hwframe;
984 		d->frame[d->swframe].state = FRAME_READY;
985 #if DMA_DEINTERLACE
986 		d->frame[d->swframe].pos = d->frame[d->swframe].data+d->vw.width*RAW_PER_PIXEL;
987 #else
988 		d->frame[d->swframe].pos = d->frame[d->swframe].data;
989 #endif
990 		/* Fire up the DMA engine again if it stopped */
991 		d->dma_enable = 1;
992 		descr = in64(MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
993 		out64(d->ff.ringsz-descr, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
994 	}
995 #endif
996 #endif
997 
998 	/* XXXKW mmap/read mixture could break the swframe sequence */
999 
1000 	if (d->frame[d->swframe].state != FRAME_DONE) {
1001 		if (noblock)
1002 			return -EAGAIN;
1003 		else {
1004 			DBG(DBG_IO,
1005 			    printk(KERN_DEBUG IF_NAME ": sleeping for frame\n"));
1006 			interruptible_sleep_on(&d->frame[d->swframe].read_wait);
1007 			DBG(DBG_IO,
1008 			    printk(KERN_DEBUG IF_NAME ": awakened\n"));
1009 			if (signal_pending(current))
1010 				return -ERESTARTSYS;
1011 		}
1012 	}
1013 
1014 	if (count < d->frame[d->swframe].size)
1015 		return -EFAULT;
1016 
1017 	count = d->frame[d->swframe].size;
1018 	yuvconvert_inplace(d->frame[d->swframe].data, d->frame[d->swframe].size, d->vp.palette, 0);
1019 	copy_to_user(buf, d->frame[d->swframe].data, d->frame[d->swframe].size);
1020 	d->swframe = (d->swframe + 1) % NUM_FRAME;
1021 	/* XXXKW doesn't do format conversion!!! */
1022 #if !NULL_DMA
1023 #if !LAZY_READ
1024 	/* XXXKW Fire up the DMA engine again if it stopped ??? */
1025 	if (!d->dma_enable) {
1026 		DBG(DBG_DESCR, printk(KERN_DEBUG IF_NAME ": enabling DMA\n"));
1027 		/* Fire up the DMA engine again if it stopped */
1028 		d->dma_enable = 1;
1029 		descr = in64(MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
1030 		out64(d->ff.ringsz-descr, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
1031 	}
1032 #endif
1033 #endif
1034 
1035 	return count;
1036 }
1037 
saa7114h_ioctl(struct video_device * vd,unsigned int cmd,void * arg)1038 static int saa7114h_ioctl(struct video_device *vd, unsigned int cmd, void *arg)
1039 {
1040 	struct saa7114h *d = vd->priv;
1041 	int val, reg, retval = 0;
1042 
1043 	if (!d)
1044 		return -ENODEV;
1045 
1046 	switch (cmd) {
1047 	case VIDIOCGCHAN:
1048 	{
1049 		struct video_channel v;
1050 
1051 		if (copy_from_user(&v, arg, sizeof(v))) {
1052 			retval = -EFAULT;
1053 			break;
1054 		}
1055 		if (v.channel != 0) {
1056 			retval = -EINVAL;
1057 			break;
1058 		}
1059 
1060 		v.channel = 0;
1061 		strcpy(v.name, "Camera");
1062 		v.tuners = 0;
1063 		v.flags = 0;
1064 		v.type = VIDEO_TYPE_CAMERA;
1065 		v.norm = 0;
1066 
1067 		if (copy_to_user(arg, &v, sizeof(v)))
1068 			retval = -EFAULT;
1069 		break;
1070 	}
1071 
1072 	case VIDIOCSCHAN:
1073 	{
1074 		int v;
1075 
1076 		if (copy_from_user(&v, arg, sizeof(v)))
1077 			retval = -EFAULT;
1078 
1079 		if (retval == 0 && v != 0)
1080 			retval = -EINVAL;
1081 
1082 		break;
1083 	}
1084 
1085 	case VIDIOCGCAP:
1086 	{
1087 		struct video_capability b;
1088 
1089 		strcpy(b.name, "Philips SAA7114H Decoder");
1090 		b.type = VID_TYPE_CAPTURE /* | VID_TYPE_TELETEXT */ | VID_TYPE_SCALES;
1091 		b.channels = 1;
1092 		b.audios = 0;
1093 		b.maxwidth = MAX_HORIZ;
1094 		b.maxheight = MAX_VERT;
1095 		/* XXXKW find real values */
1096 		b.minwidth = 48;
1097 		b.minheight = 48;
1098 
1099 		if (copy_to_user(arg, &b, sizeof(b)))
1100 			retval = -EFAULT;
1101 
1102 		break;
1103 	}
1104 
1105 	/* image properties */
1106 	case VIDIOCGPICT:
1107 		if (copy_to_user(arg, &d->vp, sizeof(struct video_picture)))
1108 			retval = -EFAULT;
1109 		break;
1110 
1111 	case VIDIOCSPICT:
1112 	{
1113 		struct video_picture vp;
1114 
1115 		/* copy_from_user */
1116 		if (copy_from_user(&vp, arg, sizeof(vp))) {
1117 			retval = -EFAULT;
1118 			break;
1119 		}
1120 
1121 		down(&d->param_lock);
1122 		/* brightness, colour, contrast need not check 0-65535 */
1123 		memcpy( &d->vp, &vp, sizeof(vp) );
1124 		/* update cam->params.colourParams */
1125 		saa7114h_set_cparams(d);
1126 		up(&d->param_lock);
1127 		break;
1128 	}
1129 
1130 	/* get/set capture window */
1131 	case VIDIOCGWIN:
1132 		if (copy_to_user(arg, &d->vw, sizeof(struct video_window)))
1133 			retval = -EFAULT;
1134 		break;
1135 
1136 	case VIDIOCSWIN:
1137 	{
1138 		/* copy_from_user, check validity, copy to internal structure */
1139 		struct video_window vw;
1140 		if (copy_from_user(&vw, arg, sizeof(vw))) {
1141 			retval = -EFAULT;
1142 			break;
1143 		}
1144 
1145 		if (vw.clipcount != 0) {    /* clipping not supported */
1146 			retval = -EINVAL;
1147 			break;
1148 		}
1149 		if (vw.clips != NULL) {	    /* clipping not supported */
1150 			retval = -EINVAL;
1151 			break;
1152 		}
1153 		if ((vw.width > MAX_HORIZ || vw.width < MIN_HORIZ) ||
1154 		    (vw.height > MAX_VERT || vw.height < MIN_VERT)) {
1155 			retval = -EINVAL;
1156 			break;
1157 		}
1158 
1159 		/* we set the video window to something smaller or equal to what
1160 		 * is requested by the user???
1161 		 */
1162 		down(&d->param_lock);
1163 		if (vw.width != d->vw.width || vw.height != d->vw.height) {
1164 			uint32_t scale_factor;
1165 			/* XXXKW base percentage on input stream, not MAX? */
1166 
1167 			/* Assert scaler reset */
1168 			saa7114h_reg_write(d, 0x88, 0x98);
1169 
1170 			/* Vertical scaling */
1171 			scale_factor = (MAX_VERT*1024) / vw.height;
1172 			saa7114h_reg_write(d, 0x9e, vw.height & 0xff);
1173 			saa7114h_reg_write(d, 0x9f, (vw.height >> 8) & 0xf);
1174 			saa7114h_reg_write(d, 0xb0, scale_factor & 0xff);
1175 			saa7114h_reg_write(d, 0xb1, (scale_factor >> 8) & 0xff);
1176 			saa7114h_reg_write(d, 0xb2, scale_factor & 0xff);
1177 			saa7114h_reg_write(d, 0xb3, (scale_factor >> 8) & 0xff);
1178 			/* Horizontal scaling */
1179 			scale_factor = (MAX_HORIZ*1024) / vw.width;
1180 			saa7114h_reg_write(d, 0x9c, vw.width & 0xff);
1181 			saa7114h_reg_write(d, 0x9d, (vw.width >> 8) & 0xf);
1182 			saa7114h_reg_write(d, 0xa8, scale_factor & 0xff);
1183 			saa7114h_reg_write(d, 0xa9, (scale_factor >> 8) & 0xff);
1184 			saa7114h_reg_write(d, 0xac, (scale_factor >> 1) & 0xff);
1185 			saa7114h_reg_write(d, 0xad, (scale_factor >> 9) & 0xff);
1186 #if 0
1187 			/* prescaler
1188 			saa7114h_reg_write(d, 0xa0, 2);
1189 			saa7114h_reg_write(d, 0xa1, 1);
1190 			saa7114h_reg_write(d, 0xa2, 1);
1191 			*/
1192 #endif
1193 
1194 			/* Release scaler reset */
1195 			saa7114h_reg_write(d, 0x88, 0xb8);
1196 			d->vw.width = vw.width;
1197 			d->vw.height = vw.height;
1198 		}
1199 		up(&d->param_lock);
1200 		break;
1201 	}
1202 
1203 	/* mmap interface */
1204 	case VIDIOCGMBUF:
1205 	{
1206 		struct video_mbuf vm;
1207 		int i;
1208 
1209 		memset(&vm, 0, sizeof(vm));
1210 		vm.size = MAX_FRAME_SIZE*NUM_FRAME;
1211 		vm.frames = NUM_FRAME;
1212 		for (i = 0; i < NUM_FRAME; i++)
1213 			vm.offsets[i] = MAX_FRAME_SIZE * i;
1214 
1215 		if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
1216 			retval = -EFAULT;
1217 
1218 		break;
1219 	}
1220 
1221 	case VIDIOCMCAPTURE:
1222 	{
1223 		struct video_mmap vm;
1224 		int descr, status;
1225 
1226 		if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) {
1227 			retval = -EFAULT;
1228 			break;
1229 		}
1230 		if (vm.frame<0||vm.frame>NUM_FRAME) {
1231 			retval = -EINVAL;
1232 			break;
1233 		}
1234 
1235 		DBG(DBG_CALL,
1236 		    printk(KERN_DEBUG IF_NAME ":ioctl MCAPTURE %d\n", vm.frame));
1237 
1238 		d->vp.palette = vm.format;
1239 		/* XXXKW set depth? */
1240 		/* XXXKW match/update for vm.width, vm.height */
1241 
1242 		/* XXKW Should check this periodically!? */
1243 		status = saa7114h_reg_read(d, DECODER_STATUS);
1244 //		  d->interlaced = ((status & 0x80) != 0);
1245 
1246 		/* Give the buffer to the DMA engine */
1247 		/* XXXKW vm.frame vs d->swframe!!  mmap/read mismatch */
1248 #if DMA_DEINTERLACE
1249 		d->frame[vm.frame].pos = d->frame[vm.frame].data + d->vw.width*RAW_PER_PIXEL;
1250 #else
1251 		d->frame[vm.frame].pos = d->frame[vm.frame].data;
1252 #endif
1253 #if !NULL_DMA
1254 		d->frame[vm.frame].state = FRAME_READY;
1255 		/* Fire up the DMA engine again if it stopped */
1256 		if (!d->dma_enable) {
1257 			d->dma_enable = 1;
1258 			d->hwframe = d->swframe = vm.frame;
1259 			descr = in64(MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
1260 			DBG(DBG_DESCR,
1261 			    printk(KERN_DEBUG IF_NAME ": capture adds %d -> %d descrs\n",
1262 				   d->ff.ringsz-descr, descr));
1263 			out64(d->ff.ringsz-descr, MAC2_DMARX0_CSR(R_MAC_DMA_DSCR_CNT));
1264 		}
1265 #endif
1266 		break;
1267 	}
1268 
1269 	case VIDIOCSYNC:
1270 	{
1271 		int frame;
1272 
1273 		if (copy_from_user((void *)&frame, arg, sizeof(int))) {
1274 			retval = -EFAULT;
1275 			break;
1276 		}
1277 
1278 		if (frame<0 || frame >= NUM_FRAME) {
1279 			retval = -EINVAL;
1280 			break;
1281 		}
1282 
1283 		DBG(DBG_CALL, printk(KERN_DEBUG IF_NAME ":ioctl CSYNC %d\n", frame));
1284 
1285 		switch (d->frame[frame].state) {
1286 		case FRAME_UNUSED:
1287 			DBG(DBG_IO,
1288 			    printk(KERN_ERR IF_NAME ":sync to unused frame %d\n", frame));
1289 			retval = -EINVAL;
1290 			break;
1291 
1292 		case FRAME_READY:
1293 		case FRAME_GRABBING:
1294 			DBG(DBG_IO,
1295 			    printk(KERN_DEBUG IF_NAME ": sleeping for frame %d\n", frame));
1296 			interruptible_sleep_on(&d->frame[frame].read_wait);
1297 			DBG(DBG_IO,
1298 			    printk(KERN_DEBUG IF_NAME ": awakened\n"));
1299 			if (signal_pending(current))
1300 				return -ERESTARTSYS;
1301 		case FRAME_DONE:
1302 #if !NULL_DMA
1303 			yuvconvert_inplace(d->frame[frame].data,
1304 					   d->frame[frame].size,
1305 					   d->vp.palette, 1);
1306 			d->frame[frame].state = FRAME_UNUSED;
1307 #endif
1308 			DBG(DBG_IO,
1309 			    printk(KERN_DEBUG IF_NAME ": sync finished %d\n",
1310 				   frame));
1311 			break;
1312 		}
1313 		break;
1314 	}
1315 
1316 	case VIDIOREADREG:
1317 		reg = *(int *)arg;
1318 		DBG(DBG_REGISTER, printk(KERN_DEBUG IF_NAME ": read of %02x\n", reg));
1319 		if ((reg > 0xEF) || (reg < 0))
1320 			return -EINVAL;
1321 		val = saa7114h_reg_read((struct saa7114h *)vd->priv, reg);
1322 		if (val == -1)
1323 			return -EIO;
1324 		*(int *)arg = val;
1325 		break;
1326 	case VIDIOWRITEREG:
1327 		if (copy_from_user(&reg, arg, sizeof(int)) ||
1328 		    copy_from_user(&val, arg+sizeof(int), sizeof(int)))
1329 			return -EFAULT;
1330 		DBG(DBG_REGISTER, printk(KERN_DEBUG IF_NAME ": write of %02x <- %02x\n", reg, val));
1331 		if ((reg > 0xEF) || (reg < 0))
1332 			return -EINVAL;
1333 		val = saa7114h_reg_write((struct saa7114h *)vd->priv, reg, val);
1334 		if (val == -1)
1335 			return -EIO;
1336 		break;
1337 	case VIDIOGRABFRAME:
1338 		return grab_frame((struct saa7114h *)vd->priv, arg, 0);
1339 	case VIDIOSHOWEAV:
1340 		return grab_frame((struct saa7114h *)vd->priv, arg, 1);
1341 	default:
1342 		retval = -EINVAL;
1343 		break;
1344 	}
1345 
1346 	return retval;
1347 }
1348 
saa7114h_mmap(struct video_device * vd,const char * adr,unsigned long size)1349 static int saa7114h_mmap(struct video_device *vd, const char *adr,
1350 			 unsigned long size)
1351 {
1352 	struct saa7114h *d = vd->priv;
1353 	unsigned long start = (unsigned long)adr;
1354 	unsigned long page, pos;
1355 
1356 	if (!d)
1357 		return -ENODEV;
1358 
1359 	if (size > MAX_MMAP_SIZE) {
1360 		printk("mmap: bad size %lu > %lu\n", size, MAX_MMAP_SIZE);
1361 		return -EINVAL;
1362 	}
1363 
1364 	/* make this _really_ smp-safe */
1365 	if (down_interruptible(&d->busy_lock))
1366 		return -EINTR;
1367 
1368 	pos = (unsigned long)(d->frame_buf);
1369 	while (size > 0) {
1370 		page = kvirt_to_pa(pos);
1371 		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
1372 			up(&d->busy_lock);
1373 			return -EAGAIN;
1374 		}
1375 		start += PAGE_SIZE;
1376 		pos += PAGE_SIZE;
1377 		if (size > PAGE_SIZE)
1378 			size -= PAGE_SIZE;
1379 		else
1380 			size = 0;
1381 	}
1382 	up(&d->busy_lock);
1383 
1384 	return 0;
1385 }
1386 
1387 /* -----------------------------------------------------------------------
1388  * Device probing and initialization
1389  * ----------------------------------------------------------------------- */
1390 
1391 /* Default values to program into SAA7114H */
1392 static const unsigned char reg_init[] =	{
1393 	0x00, 0x00,	/* 00 - ID byte */
1394 
1395 	/*front end */
1396 	0x01, 0x08,	/* 01 - Horizontal increment -> recommended delay */
1397 	0x02, 0xC4,	/* 02 - AI Control 1 (CVBS AI23) */
1398 	0x03, 0x10,	/* 03 - AI Control 2 */
1399 	0x04, 0x90,	/* 04 - AI Control 3 (Gain ch 1) */
1400 	0x05, 0x90,	/* 05 - AI Control 4 (Gain ch 2) */
1401 
1402 	/* decoder */
1403 	0x06, 0xEB,	/* 06 - Horiz sync start */
1404 	0x07, 0xE0,	/* 07 - Horiz sync stop */
1405 	0x08, 0x98,	/* 08 - Sync control */
1406 	0x09, 0x40,	/* 09 - L Control */
1407 	0x0a, 0x80,	/* 0a - L Brightness */
1408 	0x0b, 0x44,	/* 0b - L Contrast */
1409 	0x0c, 0x40,	/* 0c - C Saturation */
1410 	0x0d, 0x00,	/* 0d - C Hue */
1411 	0x0e, 0x89,	/* 0e - C Control 1 */
1412 	0x0f, 0x0f,	/* 0f - C Gain (??? 0x2A recommended) */
1413 	0x10, 0x0E,	/* 10 - C Control 2 */
1414 	0x11, 0x00,	/* 11 - Mode/Delay */
1415 	0x12, 0x00,	/* 12 - RT signal control */
1416 	0x13, 0x00,	/* 13 - RT/X output */
1417 	0x14, 0x00,	/* 14 - Analog, Compat */
1418 	0x15, 0x11,	/* 15 - VGATE start */
1419 	0x16, 0xFE,	/* 16 - VGATE stop */
1420 	0x17, 0x40,	/* 17 - Misc VGATE (disable LLC2) */
1421 	0x18, 0x40,	/* 18 - Raw data gain - 128 */
1422 	0x19, 0x80,	/* 19 - Raw data offset - 0 */
1423 
1424 	/* Global settings */
1425 	0x88, 0x98,	/* 88 - AI1x on, AI2x off; decoder/slicer off; ACLK gen off */
1426 	0x83, 0x00,	/* 83 - X-port output disabled */
1427 	0x84, 0xF0,	/* 84 - I-port V/G output framing, IGP1=0=IGP0=0 */
1428 	0x85, 0x00,	/* 85 - I-port default polarities, X-port signals */
1429 	0x86, 0x40,	/* 86 - more IGP1/0, FIFO level, only video transmitted */
1430 	0x87, 0x01,	/* 87 - ICK default, IDQ default, I-port output enabled */
1431 
1432 	/* Task A: scaler input config and output format */
1433 	0x90, 0x00,	/* 90 - Task handling */
1434 	0x91, 0x08,	/* 91 - Scalar input and format */
1435 	0x92, 0x10,	/* 92 - Reference signal def */
1436 	0x93, 0x80,	/* 93 - I-port output */
1437 
1438 	/* Task B */
1439 	0xc0, 0x42,	/* 90 - Task handling */
1440 	0xc1, 0x08,	/* 91 - Scalar input and format */
1441 	0xc2, 0x10,	/* 92 - Reference signal def */
1442 	0xc3, 0x80,	/* 93 - I-port output */
1443 
1444 	/* Input and Output windows */
1445 	0x94, 0x10,	/*  - */
1446 	0x95, 0x00,	/*  - */
1447 	0x96, 0xD0,	/*  - */
1448 	0x97, 0x02,	/*  - */
1449 	0x98, 0x0A,	/*  - */
1450 	0x99, 0x00,	/*  - */
1451 	0x9a, 0xF2,	/*  - */
1452 	0x9b, 0x00,	/*  - */
1453 	0x9c, 0xD0,	/*  - */
1454 	0x9d, 0x02,	/*  - */
1455 	0xc4, 0x10,	/*  - */
1456 	0xc5, 0x00,	/*  - */
1457 	0xc6, 0xD0,	/*  - */
1458 	0xc7, 0x02,	/*  - */
1459 	0xc8, 0x0A,	/*  - */
1460 	0xc9, 0x00,	/*  - */
1461 	0xca, 0xF2,	/*  - */
1462 	0xcb, 0x00,	/*  - */
1463 	0xcc, 0xD0,	/*  - */
1464 	0xcd, 0x02,	/*  - */
1465 
1466 	0x9e, 0xf0,	/*  - */
1467 	0x9f, 0x00,	/*  - */
1468 	0xce, 0xf0,	/*  - */
1469 	0xcf, 0x00,	/*  - */
1470 
1471 	/* Prefiltering and prescaling */
1472 	0xa0, 0x01,	/*  - */
1473 	0xa1, 0x00,	/*  - */
1474 	0xa2, 0x00,	/*  - */
1475 	0xa4, 0x80,	/*  - */
1476 	0xa5, 0x40,	/*  - */
1477 	0xa6, 0x40,	/*  - */
1478 	0xd4, 0x80,	/*  - */
1479 	0xd5, 0x40,	/*  - */
1480 	0xd6, 0x40,	/*  - */
1481 
1482 	/* Horizontal phase scaling */
1483 	0xa8, 0x00,	/*  - */
1484 	0xa9, 0x04,	/*  - */
1485 	0xaa, 0x00,	/*  - */
1486 	0xd8, 0x00,	/*  - */
1487 	0xd9, 0x04,	/*  - */
1488 	0xda, 0x00,	/*  - */
1489 
1490 	0xac, 0x00,	/*  - */
1491 	0xad, 0x02,	/*  - */
1492 	0xae, 0x00,	/*  - */
1493 	0xdc, 0x00,	/*  - */
1494 	0xdd, 0x02,	/*  - */
1495 	0xde, 0x00,	/*  - */
1496 
1497 	/* Vertical phase scaling */
1498 	0xb0, 0x00,	/*  - */
1499 	0xb1, 0x04,	/*  - */
1500 	0xb2, 0x00,	/*  - */
1501 	0xb3, 0x04,	/*  - */
1502 	0xe0, 0x00,	/*  - */
1503 	0xe1, 0x04,	/*  - */
1504 	0xe2, 0x00,	/*  - */
1505 	0xe3, 0x04,	/*  - */
1506 	0xb4, 0x00,	/* b4 - vscale mode control */
1507 	0xe4, 0x00,	/* b4 - vscale mode control */
1508 
1509 	/* Task enables */
1510 	0x80, 0x10,	/* 80 - LLC->ICLK, dq->IDQ, scaler->F/V timing, task enables */
1511 
1512 	/* Reset the slicer */
1513 	0x88, 0xb8,	/* 88 - AI1x on, AI2x off; decoder/slicer on; ACLK gen off */
1514 };
1515 
saa7114h_attach(struct i2c_adapter * adap,int addr,unsigned short flags,int kind)1516 static int saa7114h_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
1517 {
1518 	struct i2c_client *client;
1519 	struct video_device *vd;
1520 	struct saa7114h *decoder;
1521 	int err;
1522 	int val, i;
1523 
1524 	client = kmalloc(sizeof(*client), GFP_KERNEL);
1525 	if (client == NULL)
1526 		return -ENOMEM;
1527 	client->adapter = adap;
1528 	client->addr = addr;
1529 	client->driver = &i2c_driver_saa7114h;
1530 	strcpy(client->name, IF_NAME);
1531 
1532 	decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
1533 	if (decoder == NULL) {
1534 		kfree(client);
1535 		return -ENOMEM;
1536 	}
1537 	memset(decoder, 0, sizeof(struct saa7114h));
1538 	decoder->client = client;
1539 	decoder->dma_enable = 0;
1540 	decoder->palette = VIDEO_PALETTE_UYVY;
1541 	decoder->depth = 16;
1542 	decoder->vw.width = MAX_HORIZ;
1543 	decoder->vw.height = MAX_VERT;
1544 	decoder->frame_buf = rvmalloc(MAX_FRAME_SIZE*NUM_FRAME);
1545 	if (!decoder->frame_buf) {
1546 		kfree(decoder);
1547 		kfree(client);
1548 		return -ENOMEM;
1549 	}
1550 	/* XXXKW use clear_page? */
1551 	memset(decoder->frame_buf, 0, MAX_FRAME_SIZE*NUM_FRAME);
1552 	printk("saa7114h_attach: frame_buf = (fb=%8p / %08lx)\n",
1553 	       decoder->frame_buf, kvirt_to_pa((int)decoder->frame_buf));
1554 	for (i=0; i<NUM_FRAME; i++) {
1555 		decoder->frame[i].data = decoder->frame_buf+i*MAX_FRAME_SIZE;
1556 #if NULL_DMA
1557 		decoder->frame[i].state = FRAME_DONE;
1558 #else
1559 		decoder->frame[i].state = FRAME_UNUSED;
1560 #endif
1561 		init_waitqueue_head(&decoder->frame[i].read_wait);
1562 	}
1563 	decoder->irq = K_INT_MAC_2;
1564 	if (request_irq
1565 	    (decoder->irq, saa7114h_interrupt, 0, "Philips SAA7114h", decoder)) {
1566 		rvfree(decoder->frame_buf, MAX_FRAME_SIZE*NUM_FRAME);
1567 		kfree(decoder);
1568 		kfree(client);
1569 		return -ENOMEM;
1570 	}
1571 	init_MUTEX(&decoder->param_lock);
1572 	init_MUTEX(&decoder->busy_lock);
1573 
1574 	if ((err = i2c_attach_client(client)) < 0) {
1575 		kfree(client);
1576 		kfree(decoder);
1577 		return err;
1578 	}
1579 
1580 	if (saa7114h_reg_init(decoder, reg_init, sizeof(reg_init)) ||
1581 	    saa7114h_get_cparams(decoder)) {
1582 		i2c_detach_client(client);
1583 		kfree(client);
1584 		kfree(decoder);
1585 		return -ENODEV;
1586 	}
1587 
1588 	vd = kmalloc(sizeof(*vd), GFP_KERNEL);
1589 	memset(vd, 0, sizeof(*vd));
1590 	if (vd == NULL) {
1591 		i2c_detach_client(client);
1592 		kfree(client);
1593 		kfree(decoder);
1594 		return -ENOMEM;
1595 	}
1596 	vd->priv = decoder;
1597 	strcpy(vd->name, IF_NAME);
1598 	vd->type = VID_TYPE_CAPTURE;
1599 	vd->hardware = VID_HARDWARE_SAA7114H;
1600 	vd->open =  saa7114h_open;
1601 	vd->close = saa7114h_release;
1602 	vd->read =  saa7114h_read;
1603 	vd->ioctl = saa7114h_ioctl;
1604 	vd->mmap =  saa7114h_mmap;
1605 
1606 	if ((err = video_register_device(vd, VFL_TYPE_GRABBER, -1)) < 0) {
1607 		i2c_detach_client(client);
1608 		kfree(client);
1609 		kfree(decoder);
1610 		kfree(vd);
1611 		return err;
1612 	}
1613 
1614 	client->data = vd;
1615 	decoder->vd = vd;
1616 
1617 	/* Turn on the ITRDY - preserve the GENO pin for syncser */
1618 	val = in64(KSEG1 + A_MAC_REGISTER(2, R_MAC_MDIO));
1619 	out64(M_MAC_MDIO_OUT | (val & M_MAC_GENC),
1620 	      KSEG1 + A_MAC_REGISTER(2, R_MAC_MDIO));
1621 
1622 	if ((err = dma_setup(decoder))) {
1623 		i2c_detach_client(client);
1624 		kfree(client);
1625 		kfree(decoder);
1626 		kfree(vd);
1627 		return err;
1628 	}
1629 
1630 	printk("saa7114h_attach successful\n");
1631 
1632 #ifdef CONFIG_PROC_FS
1633 	proc_saa7114h_create();
1634 	create_proc_decoder(vd->priv);
1635 #endif
1636 
1637 	MOD_INC_USE_COUNT;
1638 
1639 	return 0;
1640 }
1641 
1642 /* Addresses to scan */
1643 static unsigned short normal_i2c[] = {I2C_CLIENT_END};
1644 static unsigned short normal_i2c_range[] = {0x20, 0x21, I2C_CLIENT_END};
1645 static unsigned short probe[2]	      = { I2C_CLIENT_END, I2C_CLIENT_END };
1646 static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
1647 static unsigned short ignore[2]	      = { I2C_CLIENT_END, I2C_CLIENT_END };
1648 static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
1649 static unsigned short force[2]	      = { I2C_CLIENT_END, I2C_CLIENT_END };
1650 
1651 static struct i2c_client_address_data addr_data = {
1652 	normal_i2c, normal_i2c_range,
1653 	probe, probe_range,
1654 	ignore, ignore_range,
1655 	force
1656 };
1657 
saa7114h_probe(struct i2c_adapter * adap)1658 static int saa7114h_probe(struct i2c_adapter *adap)
1659 {
1660 	/* Look for this device on the given adapter (bus) */
1661 	if (adap->id == (I2C_ALGO_SIBYTE | I2C_HW_SIBYTE))
1662 		return i2c_probe(adap, &addr_data, &saa7114h_attach);
1663 	else
1664 		return 0;
1665 }
1666 
saa7114h_detach(struct i2c_client * device)1667 static int saa7114h_detach(struct i2c_client *device)
1668 {
1669 #if 0
1670 	kfree(device->data);
1671 	MOD_DEC_USE_COUNT;
1672 #endif
1673 #ifdef CONFIG_PROC_FS
1674 	destroy_proc_decoder(((struct video_device *)device->data)->priv);
1675 	proc_saa7114h_destroy();
1676 #endif
1677 	return 0;
1678 }
1679 
1680 /* ----------------------------------------------------------------------- */
1681 
swarm_7114h_init(void)1682 static int __init swarm_7114h_init(void)
1683 {
1684 	return i2c_add_driver(&i2c_driver_saa7114h);
1685 }
1686 
swarm_7114h_cleanup(void)1687 static void __exit swarm_7114h_cleanup(void)
1688 {
1689 }
1690 
1691 MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
1692 MODULE_DESCRIPTION("Philips SAA7114H Driver for Broadcom SWARM board");
1693 
1694 module_init(swarm_7114h_init);
1695 module_exit(swarm_7114h_cleanup);
1696