xref: /linux/drivers/media/pci/zoran/zr36016.c (revision 0337966d121ebebf73a1c346123e8112796e684e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Zoran ZR36016 basic configuration functions
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * ------------------------------------------------------------------------
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
111da177e4SLinus Torvalds  * it under the terms of the GNU General Public License as published by
121da177e4SLinus Torvalds  * the Free Software Foundation; either version 2 of the License, or
131da177e4SLinus Torvalds  * (at your option) any later version.
141da177e4SLinus Torvalds  *
151da177e4SLinus Torvalds  * This program is distributed in the hope that it will be useful,
161da177e4SLinus Torvalds  * but WITHOUT ANY WARRANTY; without even the implied warranty of
171da177e4SLinus Torvalds  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
181da177e4SLinus Torvalds  * GNU General Public License for more details.
191da177e4SLinus Torvalds  *
201da177e4SLinus Torvalds  * ------------------------------------------------------------------------
211da177e4SLinus Torvalds  */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #define ZR016_VERSION "v0.7"
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #include <linux/module.h>
261da177e4SLinus Torvalds #include <linux/init.h>
271da177e4SLinus Torvalds #include <linux/slab.h>
281da177e4SLinus Torvalds #include <linux/delay.h>
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds #include <linux/types.h>
311da177e4SLinus Torvalds #include <linux/wait.h>
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds /* I/O commands, error codes */
341da177e4SLinus Torvalds #include <asm/io.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /* v4l  API */
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds /* headerfile of this module */
391da177e4SLinus Torvalds #include "zr36016.h"
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds /* codec io API */
421da177e4SLinus Torvalds #include "videocodec.h"
431da177e4SLinus Torvalds 
441da177e4SLinus Torvalds /* it doesn't make sense to have more than 20 or so,
451da177e4SLinus Torvalds   just to prevent some unwanted loops */
461da177e4SLinus Torvalds #define MAX_CODECS 20
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds /* amount of chips attached via this driver */
49*ff699e6bSDouglas Schilling Landgraf static int zr36016_codecs;
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds /* debugging is available via module parameter */
52*ff699e6bSDouglas Schilling Landgraf static int debug;
531da177e4SLinus Torvalds module_param(debug, int, 0);
541da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "Debug level (0-4)");
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds #define dprintk(num, format, args...) \
571da177e4SLinus Torvalds 	do { \
581da177e4SLinus Torvalds 		if (debug >= num) \
591da177e4SLinus Torvalds 			printk(format, ##args); \
601da177e4SLinus Torvalds 	} while (0)
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds /* =========================================================================
631da177e4SLinus Torvalds    Local hardware I/O functions:
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds    read/write via codec layer (registers are located in the master device)
661da177e4SLinus Torvalds    ========================================================================= */
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds /* read and write functions */
691da177e4SLinus Torvalds static u8
701da177e4SLinus Torvalds zr36016_read (struct zr36016 *ptr,
711da177e4SLinus Torvalds 	      u16             reg)
721da177e4SLinus Torvalds {
731da177e4SLinus Torvalds 	u8 value = 0;
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds 	// just in case something is wrong...
761da177e4SLinus Torvalds 	if (ptr->codec->master_data->readreg)
771da177e4SLinus Torvalds 		value =
781da177e4SLinus Torvalds 		    (ptr->codec->master_data->
791da177e4SLinus Torvalds 		     readreg(ptr->codec, reg)) & 0xFF;
801da177e4SLinus Torvalds 	else
811da177e4SLinus Torvalds 		dprintk(1,
821da177e4SLinus Torvalds 			KERN_ERR "%s: invalid I/O setup, nothing read!\n",
831da177e4SLinus Torvalds 			ptr->name);
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds 	dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
861da177e4SLinus Torvalds 		value);
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	return value;
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds static void
921da177e4SLinus Torvalds zr36016_write (struct zr36016 *ptr,
931da177e4SLinus Torvalds 	       u16             reg,
941da177e4SLinus Torvalds 	       u8              value)
951da177e4SLinus Torvalds {
961da177e4SLinus Torvalds 	dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
971da177e4SLinus Torvalds 		reg);
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds 	// just in case something is wrong...
1001da177e4SLinus Torvalds 	if (ptr->codec->master_data->writereg) {
1011da177e4SLinus Torvalds 		ptr->codec->master_data->writereg(ptr->codec, reg, value);
1021da177e4SLinus Torvalds 	} else
1031da177e4SLinus Torvalds 		dprintk(1,
1041da177e4SLinus Torvalds 			KERN_ERR
1051da177e4SLinus Torvalds 			"%s: invalid I/O setup, nothing written!\n",
1061da177e4SLinus Torvalds 			ptr->name);
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds /* indirect read and write functions */
1101da177e4SLinus Torvalds /* the 016 supports auto-addr-increment, but
1111da177e4SLinus Torvalds  * writing it all time cost not much and is safer... */
1121da177e4SLinus Torvalds static u8
1131da177e4SLinus Torvalds zr36016_readi (struct zr36016 *ptr,
1141da177e4SLinus Torvalds 	       u16             reg)
1151da177e4SLinus Torvalds {
1161da177e4SLinus Torvalds 	u8 value = 0;
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds 	// just in case something is wrong...
1191da177e4SLinus Torvalds 	if ((ptr->codec->master_data->writereg) &&
1201da177e4SLinus Torvalds 	    (ptr->codec->master_data->readreg)) {
1211da177e4SLinus Torvalds 		ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F);	// ADDR
1221da177e4SLinus Torvalds 		value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;	// DATA
1231da177e4SLinus Torvalds 	} else
1241da177e4SLinus Torvalds 		dprintk(1,
1251da177e4SLinus Torvalds 			KERN_ERR
1261da177e4SLinus Torvalds 			"%s: invalid I/O setup, nothing read (i)!\n",
1271da177e4SLinus Torvalds 			ptr->name);
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 	dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
1301da177e4SLinus Torvalds 		reg, value);
1311da177e4SLinus Torvalds 	return value;
1321da177e4SLinus Torvalds }
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds static void
1351da177e4SLinus Torvalds zr36016_writei (struct zr36016 *ptr,
1361da177e4SLinus Torvalds 		u16             reg,
1371da177e4SLinus Torvalds 		u8              value)
1381da177e4SLinus Torvalds {
1391da177e4SLinus Torvalds 	dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
1401da177e4SLinus Torvalds 		value, reg);
1411da177e4SLinus Torvalds 
1421da177e4SLinus Torvalds 	// just in case something is wrong...
1431da177e4SLinus Torvalds 	if (ptr->codec->master_data->writereg) {
1441da177e4SLinus Torvalds 		ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F);	// ADDR
1451da177e4SLinus Torvalds 		ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);	// DATA
1461da177e4SLinus Torvalds 	} else
1471da177e4SLinus Torvalds 		dprintk(1,
1481da177e4SLinus Torvalds 			KERN_ERR
1491da177e4SLinus Torvalds 			"%s: invalid I/O setup, nothing written (i)!\n",
1501da177e4SLinus Torvalds 			ptr->name);
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds /* =========================================================================
1541da177e4SLinus Torvalds    Local helper function:
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds    version read
1571da177e4SLinus Torvalds    ========================================================================= */
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds /* version kept in datastructure */
1601da177e4SLinus Torvalds static u8
1611da177e4SLinus Torvalds zr36016_read_version (struct zr36016 *ptr)
1621da177e4SLinus Torvalds {
1631da177e4SLinus Torvalds 	ptr->version = zr36016_read(ptr, 0) >> 4;
1641da177e4SLinus Torvalds 	return ptr->version;
1651da177e4SLinus Torvalds }
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds /* =========================================================================
1681da177e4SLinus Torvalds    Local helper function:
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds    basic test of "connectivity", writes/reads to/from PAX-Lo register
1711da177e4SLinus Torvalds    ========================================================================= */
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds static int
1741da177e4SLinus Torvalds zr36016_basic_test (struct zr36016 *ptr)
1751da177e4SLinus Torvalds {
1761da177e4SLinus Torvalds 	if (debug) {
1771da177e4SLinus Torvalds 		int i;
1781da177e4SLinus Torvalds 		zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
1791da177e4SLinus Torvalds 		dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
1801da177e4SLinus Torvalds 		for (i = 0; i <= 0x0b; i++)
1811da177e4SLinus Torvalds 			dprintk(1, "%02x ", zr36016_readi(ptr, i));
1821da177e4SLinus Torvalds 		dprintk(1, "\n");
1831da177e4SLinus Torvalds 	}
1841da177e4SLinus Torvalds 	// for testing just write 0, then the default value to a register and read
1851da177e4SLinus Torvalds 	// it back in both cases
1861da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
1871da177e4SLinus Torvalds 	if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
1881da177e4SLinus Torvalds 		dprintk(1,
1891da177e4SLinus Torvalds 			KERN_ERR
1901da177e4SLinus Torvalds 			"%s: attach failed, can't connect to vfe processor!\n",
1911da177e4SLinus Torvalds 			ptr->name);
1921da177e4SLinus Torvalds 		return -ENXIO;
1931da177e4SLinus Torvalds 	}
1941da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
1951da177e4SLinus Torvalds 	if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
1961da177e4SLinus Torvalds 		dprintk(1,
1971da177e4SLinus Torvalds 			KERN_ERR
1981da177e4SLinus Torvalds 			"%s: attach failed, can't connect to vfe processor!\n",
1991da177e4SLinus Torvalds 			ptr->name);
2001da177e4SLinus Torvalds 		return -ENXIO;
2011da177e4SLinus Torvalds 	}
2021da177e4SLinus Torvalds 	// we allow version numbers from 0-3, should be enough, though
2031da177e4SLinus Torvalds 	zr36016_read_version(ptr);
2041da177e4SLinus Torvalds 	if (ptr->version & 0x0c) {
2051da177e4SLinus Torvalds 		dprintk(1,
2061da177e4SLinus Torvalds 			KERN_ERR
2071da177e4SLinus Torvalds 			"%s: attach failed, suspicious version %d found...\n",
2081da177e4SLinus Torvalds 			ptr->name, ptr->version);
2091da177e4SLinus Torvalds 		return -ENXIO;
2101da177e4SLinus Torvalds 	}
2111da177e4SLinus Torvalds 
2121da177e4SLinus Torvalds 	return 0;		/* looks good! */
2131da177e4SLinus Torvalds }
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds /* =========================================================================
2161da177e4SLinus Torvalds    Local helper function:
2171da177e4SLinus Torvalds 
2181da177e4SLinus Torvalds    simple loop for pushing the init datasets - NO USE --
2191da177e4SLinus Torvalds    ========================================================================= */
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds #if 0
2221da177e4SLinus Torvalds static int zr36016_pushit (struct zr36016 *ptr,
2231da177e4SLinus Torvalds 			   u16             startreg,
2241da177e4SLinus Torvalds 			   u16             len,
2251da177e4SLinus Torvalds 			   const char     *data)
2261da177e4SLinus Torvalds {
2271da177e4SLinus Torvalds 	int i=0;
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 	dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
2301da177e4SLinus Torvalds 		ptr->name, startreg,len);
2311da177e4SLinus Torvalds 	while (i<len) {
2321da177e4SLinus Torvalds 		zr36016_writei(ptr, startreg++,  data[i++]);
2331da177e4SLinus Torvalds 	}
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds 	return i;
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds #endif
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds /* =========================================================================
2401da177e4SLinus Torvalds    Basic datasets & init:
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds    //TODO//
2431da177e4SLinus Torvalds    ========================================================================= */
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds static void
2461da177e4SLinus Torvalds zr36016_init (struct zr36016 *ptr)
2471da177e4SLinus Torvalds {
2481da177e4SLinus Torvalds 	// stop any processing
2491da177e4SLinus Torvalds 	zr36016_write(ptr, ZR016_GOSTOP, 0);
2501da177e4SLinus Torvalds 
2511da177e4SLinus Torvalds 	// mode setup (yuv422 in and out, compression/expansuon due to mode)
2521da177e4SLinus Torvalds 	zr36016_write(ptr, ZR016_MODE,
2531da177e4SLinus Torvalds 		      ZR016_YUV422 | ZR016_YUV422_YUV422 |
2541da177e4SLinus Torvalds 		      (ptr->mode == CODEC_DO_COMPRESSION ?
2551da177e4SLinus Torvalds 		       ZR016_COMPRESSION : ZR016_EXPANSION));
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	// misc setup
2581da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_SETUP1,
2591da177e4SLinus Torvalds 		       (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
2601da177e4SLinus Torvalds 		       (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
2611da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds 	// Window setup
2641da177e4SLinus Torvalds 	// (no extra offset for now, norm defines offset, default width height)
2651da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
2661da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
2671da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
2681da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
2691da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
2701da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
2711da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
2721da177e4SLinus Torvalds 	zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	/* shall we continue now, please? */
2751da177e4SLinus Torvalds 	zr36016_write(ptr, ZR016_GOSTOP, 1);
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds /* =========================================================================
2791da177e4SLinus Torvalds    CODEC API FUNCTIONS
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds    this functions are accessed by the master via the API structure
2821da177e4SLinus Torvalds    ========================================================================= */
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds /* set compression/expansion mode and launches codec -
2851da177e4SLinus Torvalds    this should be the last call from the master before starting processing */
2861da177e4SLinus Torvalds static int
2871da177e4SLinus Torvalds zr36016_set_mode (struct videocodec *codec,
2881da177e4SLinus Torvalds 		  int                mode)
2891da177e4SLinus Torvalds {
2901da177e4SLinus Torvalds 	struct zr36016 *ptr = (struct zr36016 *) codec->data;
2911da177e4SLinus Torvalds 
2921da177e4SLinus Torvalds 	dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
2931da177e4SLinus Torvalds 
2941da177e4SLinus Torvalds 	if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
2951da177e4SLinus Torvalds 		return -EINVAL;
2961da177e4SLinus Torvalds 
2971da177e4SLinus Torvalds 	ptr->mode = mode;
2981da177e4SLinus Torvalds 	zr36016_init(ptr);
2991da177e4SLinus Torvalds 
3001da177e4SLinus Torvalds 	return 0;
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds 
3031da177e4SLinus Torvalds /* set picture size */
3041da177e4SLinus Torvalds static int
3051da177e4SLinus Torvalds zr36016_set_video (struct videocodec   *codec,
3061da177e4SLinus Torvalds 		   struct tvnorm       *norm,
3071da177e4SLinus Torvalds 		   struct vfe_settings *cap,
3081da177e4SLinus Torvalds 		   struct vfe_polarity *pol)
3091da177e4SLinus Torvalds {
3101da177e4SLinus Torvalds 	struct zr36016 *ptr = (struct zr36016 *) codec->data;
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds 	dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
3131da177e4SLinus Torvalds 		ptr->name, norm->HStart, norm->VStart,
3141da177e4SLinus Torvalds 		cap->x, cap->y, cap->width, cap->height,
3151da177e4SLinus Torvalds 		cap->decimation);
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds 	/* if () return -EINVAL;
3181da177e4SLinus Torvalds 	 * trust the master driver that it knows what it does - so
3191da177e4SLinus Torvalds 	 * we allow invalid startx/y for now ... */
3201da177e4SLinus Torvalds 	ptr->width = cap->width;
3211da177e4SLinus Torvalds 	ptr->height = cap->height;
3221da177e4SLinus Torvalds 	/* (Ronald) This is ugly. zoran_device.c, line 387
3231da177e4SLinus Torvalds 	 * already mentions what happens if HStart is even
3241da177e4SLinus Torvalds 	 * (blue faces, etc., cr/cb inversed). There's probably
3251da177e4SLinus Torvalds 	 * some good reason why HStart is 0 instead of 1, so I'm
3261da177e4SLinus Torvalds 	 * leaving it to this for now, but really... This can be
3271da177e4SLinus Torvalds 	 * done a lot simpler */
3281da177e4SLinus Torvalds 	ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
3291da177e4SLinus Torvalds 	/* Something to note here (I don't understand it), setting
3301da177e4SLinus Torvalds 	 * VStart too high will cause the codec to 'not work'. I
3311da177e4SLinus Torvalds 	 * really don't get it. values of 16 (VStart) already break
3321da177e4SLinus Torvalds 	 * it here. Just '0' seems to work. More testing needed! */
3331da177e4SLinus Torvalds 	ptr->yoff = norm->VStart + cap->y;
3341da177e4SLinus Torvalds 	/* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
3351da177e4SLinus Torvalds 	ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
3361da177e4SLinus Torvalds 	ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
3371da177e4SLinus Torvalds 
3381da177e4SLinus Torvalds 	return 0;
3391da177e4SLinus Torvalds }
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds /* additional control functions */
3421da177e4SLinus Torvalds static int
3431da177e4SLinus Torvalds zr36016_control (struct videocodec *codec,
3441da177e4SLinus Torvalds 		 int                type,
3451da177e4SLinus Torvalds 		 int                size,
3461da177e4SLinus Torvalds 		 void              *data)
3471da177e4SLinus Torvalds {
3481da177e4SLinus Torvalds 	struct zr36016 *ptr = (struct zr36016 *) codec->data;
3491da177e4SLinus Torvalds 	int *ival = (int *) data;
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds 	dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
3521da177e4SLinus Torvalds 		size);
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 	switch (type) {
3551da177e4SLinus Torvalds 	case CODEC_G_STATUS:	/* get last status - we don't know it ... */
3561da177e4SLinus Torvalds 		if (size != sizeof(int))
3571da177e4SLinus Torvalds 			return -EFAULT;
3581da177e4SLinus Torvalds 		*ival = 0;
3591da177e4SLinus Torvalds 		break;
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds 	case CODEC_G_CODEC_MODE:
3621da177e4SLinus Torvalds 		if (size != sizeof(int))
3631da177e4SLinus Torvalds 			return -EFAULT;
3641da177e4SLinus Torvalds 		*ival = 0;
3651da177e4SLinus Torvalds 		break;
3661da177e4SLinus Torvalds 
3671da177e4SLinus Torvalds 	case CODEC_S_CODEC_MODE:
3681da177e4SLinus Torvalds 		if (size != sizeof(int))
3691da177e4SLinus Torvalds 			return -EFAULT;
3701da177e4SLinus Torvalds 		if (*ival != 0)
3711da177e4SLinus Torvalds 			return -EINVAL;
3721da177e4SLinus Torvalds 		/* not needed, do nothing */
3731da177e4SLinus Torvalds 		return 0;
3741da177e4SLinus Torvalds 
3751da177e4SLinus Torvalds 	case CODEC_G_VFE:
3761da177e4SLinus Torvalds 	case CODEC_S_VFE:
3771da177e4SLinus Torvalds 		return 0;
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds 	case CODEC_S_MMAP:
3801da177e4SLinus Torvalds 		/* not available, give an error */
3811da177e4SLinus Torvalds 		return -ENXIO;
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	default:
3841da177e4SLinus Torvalds 		return -EINVAL;
3851da177e4SLinus Torvalds 	}
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds 	return size;
3881da177e4SLinus Torvalds }
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds /* =========================================================================
3911da177e4SLinus Torvalds    Exit and unregister function:
3921da177e4SLinus Torvalds 
3931da177e4SLinus Torvalds    Deinitializes Zoran's JPEG processor
3941da177e4SLinus Torvalds    ========================================================================= */
3951da177e4SLinus Torvalds 
3961da177e4SLinus Torvalds static int
3971da177e4SLinus Torvalds zr36016_unset (struct videocodec *codec)
3981da177e4SLinus Torvalds {
3991da177e4SLinus Torvalds 	struct zr36016 *ptr = codec->data;
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds 	if (ptr) {
4021da177e4SLinus Torvalds 		/* do wee need some codec deinit here, too ???? */
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds 		dprintk(1, "%s: finished codec #%d\n", ptr->name,
4051da177e4SLinus Torvalds 			ptr->num);
4061da177e4SLinus Torvalds 		kfree(ptr);
4071da177e4SLinus Torvalds 		codec->data = NULL;
4081da177e4SLinus Torvalds 
4091da177e4SLinus Torvalds 		zr36016_codecs--;
4101da177e4SLinus Torvalds 		return 0;
4111da177e4SLinus Torvalds 	}
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds 	return -EFAULT;
4141da177e4SLinus Torvalds }
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds /* =========================================================================
4171da177e4SLinus Torvalds    Setup and registry function:
4181da177e4SLinus Torvalds 
4191da177e4SLinus Torvalds    Initializes Zoran's JPEG processor
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds    Also sets pixel size, average code size, mode (compr./decompr.)
4221da177e4SLinus Torvalds    (the given size is determined by the processor with the video interface)
4231da177e4SLinus Torvalds    ========================================================================= */
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds static int
4261da177e4SLinus Torvalds zr36016_setup (struct videocodec *codec)
4271da177e4SLinus Torvalds {
4281da177e4SLinus Torvalds 	struct zr36016 *ptr;
4291da177e4SLinus Torvalds 	int res;
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds 	dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
4321da177e4SLinus Torvalds 		zr36016_codecs);
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds 	if (zr36016_codecs == MAX_CODECS) {
4351da177e4SLinus Torvalds 		dprintk(1,
4361da177e4SLinus Torvalds 			KERN_ERR "zr36016: Can't attach more codecs!\n");
4371da177e4SLinus Torvalds 		return -ENOSPC;
4381da177e4SLinus Torvalds 	}
4391da177e4SLinus Torvalds 	//mem structure init
4407408187dSPanagiotis Issaris 	codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
4411da177e4SLinus Torvalds 	if (NULL == ptr) {
4421da177e4SLinus Torvalds 		dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
4431da177e4SLinus Torvalds 		return -ENOMEM;
4441da177e4SLinus Torvalds 	}
4451da177e4SLinus Torvalds 
4461da177e4SLinus Torvalds 	snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
4471da177e4SLinus Torvalds 		 zr36016_codecs);
4481da177e4SLinus Torvalds 	ptr->num = zr36016_codecs++;
4491da177e4SLinus Torvalds 	ptr->codec = codec;
4501da177e4SLinus Torvalds 
4511da177e4SLinus Torvalds 	//testing
4521da177e4SLinus Torvalds 	res = zr36016_basic_test(ptr);
4531da177e4SLinus Torvalds 	if (res < 0) {
4541da177e4SLinus Torvalds 		zr36016_unset(codec);
4551da177e4SLinus Torvalds 		return res;
4561da177e4SLinus Torvalds 	}
4571da177e4SLinus Torvalds 	//final setup
4581da177e4SLinus Torvalds 	ptr->mode = CODEC_DO_COMPRESSION;
4591da177e4SLinus Torvalds 	ptr->width = 768;
4601da177e4SLinus Torvalds 	ptr->height = 288;
4611da177e4SLinus Torvalds 	ptr->xdec = 1;
4621da177e4SLinus Torvalds 	ptr->ydec = 0;
4631da177e4SLinus Torvalds 	zr36016_init(ptr);
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds 	dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
4661da177e4SLinus Torvalds 		ptr->name, ptr->version);
4671da177e4SLinus Torvalds 
4681da177e4SLinus Torvalds 	return 0;
4691da177e4SLinus Torvalds }
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds static const struct videocodec zr36016_codec = {
4721da177e4SLinus Torvalds 	.owner = THIS_MODULE,
4731da177e4SLinus Torvalds 	.name = "zr36016",
4741da177e4SLinus Torvalds 	.magic = 0L,		// magic not used
4751da177e4SLinus Torvalds 	.flags =
4761da177e4SLinus Torvalds 	    CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
4771da177e4SLinus Torvalds 	    CODEC_FLAG_DECODER,
4781da177e4SLinus Torvalds 	.type = CODEC_TYPE_ZR36016,
4791da177e4SLinus Torvalds 	.setup = zr36016_setup,	// functionality
4801da177e4SLinus Torvalds 	.unset = zr36016_unset,
4811da177e4SLinus Torvalds 	.set_mode = zr36016_set_mode,
4821da177e4SLinus Torvalds 	.set_video = zr36016_set_video,
4831da177e4SLinus Torvalds 	.control = zr36016_control,
4841da177e4SLinus Torvalds 	// others are not used
4851da177e4SLinus Torvalds };
4861da177e4SLinus Torvalds 
4871da177e4SLinus Torvalds /* =========================================================================
4881da177e4SLinus Torvalds    HOOK IN DRIVER AS KERNEL MODULE
4891da177e4SLinus Torvalds    ========================================================================= */
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds static int __init
4921da177e4SLinus Torvalds zr36016_init_module (void)
4931da177e4SLinus Torvalds {
4941da177e4SLinus Torvalds 	//dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
4951da177e4SLinus Torvalds 	zr36016_codecs = 0;
4961da177e4SLinus Torvalds 	return videocodec_register(&zr36016_codec);
4971da177e4SLinus Torvalds }
4981da177e4SLinus Torvalds 
4991da177e4SLinus Torvalds static void __exit
5001da177e4SLinus Torvalds zr36016_cleanup_module (void)
5011da177e4SLinus Torvalds {
5021da177e4SLinus Torvalds 	if (zr36016_codecs) {
5031da177e4SLinus Torvalds 		dprintk(1,
5041da177e4SLinus Torvalds 			"zr36016: something's wrong - %d codecs left somehow.\n",
5051da177e4SLinus Torvalds 			zr36016_codecs);
5061da177e4SLinus Torvalds 	}
5071da177e4SLinus Torvalds 	videocodec_unregister(&zr36016_codec);
5081da177e4SLinus Torvalds }
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds module_init(zr36016_init_module);
5111da177e4SLinus Torvalds module_exit(zr36016_cleanup_module);
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
5141da177e4SLinus Torvalds MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
5151da177e4SLinus Torvalds 		   ZR016_VERSION);
5161da177e4SLinus Torvalds MODULE_LICENSE("GPL");
517