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