1/* 2 * Zoran ZR36016 basic configuration functions 3 * 4 * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at> 5 * 6 * $Id: zr36016.c,v 1.1.1.1 2007/08/03 18:52:41 Exp $ 7 * 8 * ------------------------------------------------------------------------ 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 * 24 * ------------------------------------------------------------------------ 25 */ 26 27#define ZR016_VERSION "v0.7" 28 29#include <linux/module.h> 30#include <linux/init.h> 31#include <linux/slab.h> 32#include <linux/delay.h> 33 34#include <linux/types.h> 35#include <linux/wait.h> 36 37/* includes for structures and defines regarding video 38 #include<linux/videodev.h> */ 39 40/* I/O commands, error codes */ 41#include<asm/io.h> 42//#include<errno.h> 43 44/* v4l API */ 45#include<linux/videodev.h> 46 47/* headerfile of this module */ 48#include"zr36016.h" 49 50/* codec io API */ 51#include"videocodec.h" 52 53/* it doesn't make sense to have more than 20 or so, 54 just to prevent some unwanted loops */ 55#define MAX_CODECS 20 56 57/* amount of chips attached via this driver */ 58static int zr36016_codecs = 0; 59 60/* debugging is available via module parameter */ 61 62static int debug = 0; 63module_param(debug, int, 0); 64MODULE_PARM_DESC(debug, "Debug level (0-4)"); 65 66#define dprintk(num, format, args...) \ 67 do { \ 68 if (debug >= num) \ 69 printk(format, ##args); \ 70 } while (0) 71 72/* ========================================================================= 73 Local hardware I/O functions: 74 75 read/write via codec layer (registers are located in the master device) 76 ========================================================================= */ 77 78/* read and write functions */ 79static u8 80zr36016_read (struct zr36016 *ptr, 81 u16 reg) 82{ 83 u8 value = 0; 84 85 // just in case something is wrong... 86 if (ptr->codec->master_data->readreg) 87 value = 88 (ptr->codec->master_data-> 89 readreg(ptr->codec, reg)) & 0xFF; 90 else 91 dprintk(1, 92 KERN_ERR "%s: invalid I/O setup, nothing read!\n", 93 ptr->name); 94 95 dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg, 96 value); 97 98 return value; 99} 100 101static void 102zr36016_write (struct zr36016 *ptr, 103 u16 reg, 104 u8 value) 105{ 106 dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value, 107 reg); 108 109 // just in case something is wrong... 110 if (ptr->codec->master_data->writereg) { 111 ptr->codec->master_data->writereg(ptr->codec, reg, value); 112 } else 113 dprintk(1, 114 KERN_ERR 115 "%s: invalid I/O setup, nothing written!\n", 116 ptr->name); 117} 118 119/* indirect read and write functions */ 120/* the 016 supports auto-addr-increment, but 121 * writing it all time cost not much and is safer... */ 122static u8 123zr36016_readi (struct zr36016 *ptr, 124 u16 reg) 125{ 126 u8 value = 0; 127 128 // just in case something is wrong... 129 if ((ptr->codec->master_data->writereg) && 130 (ptr->codec->master_data->readreg)) { 131 ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR 132 value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF; // DATA 133 } else 134 dprintk(1, 135 KERN_ERR 136 "%s: invalid I/O setup, nothing read (i)!\n", 137 ptr->name); 138 139 dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name, 140 reg, value); 141 return value; 142} 143 144static void 145zr36016_writei (struct zr36016 *ptr, 146 u16 reg, 147 u8 value) 148{ 149 dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name, 150 value, reg); 151 152 // just in case something is wrong... 153 if (ptr->codec->master_data->writereg) { 154 ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR 155 ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF); // DATA 156 } else 157 dprintk(1, 158 KERN_ERR 159 "%s: invalid I/O setup, nothing written (i)!\n", 160 ptr->name); 161} 162 163/* ========================================================================= 164 Local helper function: 165 166 version read 167 ========================================================================= */ 168 169/* version kept in datastructure */ 170static u8 171zr36016_read_version (struct zr36016 *ptr) 172{ 173 ptr->version = zr36016_read(ptr, 0) >> 4; 174 return ptr->version; 175} 176 177/* ========================================================================= 178 Local helper function: 179 180 basic test of "connectivity", writes/reads to/from PAX-Lo register 181 ========================================================================= */ 182 183static int 184zr36016_basic_test (struct zr36016 *ptr) 185{ 186 if (debug) { 187 int i; 188 zr36016_writei(ptr, ZR016I_PAX_LO, 0x55); 189 dprintk(1, KERN_INFO "%s: registers: ", ptr->name); 190 for (i = 0; i <= 0x0b; i++) 191 dprintk(1, "%02x ", zr36016_readi(ptr, i)); 192 dprintk(1, "\n"); 193 } 194 // for testing just write 0, then the default value to a register and read 195 // it back in both cases 196 zr36016_writei(ptr, ZR016I_PAX_LO, 0x00); 197 if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) { 198 dprintk(1, 199 KERN_ERR 200 "%s: attach failed, can't connect to vfe processor!\n", 201 ptr->name); 202 return -ENXIO; 203 } 204 zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0); 205 if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) { 206 dprintk(1, 207 KERN_ERR 208 "%s: attach failed, can't connect to vfe processor!\n", 209 ptr->name); 210 return -ENXIO; 211 } 212 // we allow version numbers from 0-3, should be enough, though 213 zr36016_read_version(ptr); 214 if (ptr->version & 0x0c) { 215 dprintk(1, 216 KERN_ERR 217 "%s: attach failed, suspicious version %d found...\n", 218 ptr->name, ptr->version); 219 return -ENXIO; 220 } 221 222 return 0; /* looks good! */ 223} 224 225/* ========================================================================= 226 Local helper function: 227 228 simple loop for pushing the init datasets - NO USE -- 229 ========================================================================= */ 230 231 232/* ========================================================================= 233 Basic datasets & init: 234 235 //TODO// 236 ========================================================================= */ 237 238// needed offset values PAL NTSC SECAM 239static const int zr016_xoff[] = { 20, 20, 20 }; 240static const int zr016_yoff[] = { 8, 9, 7 }; 241 242static void 243zr36016_init (struct zr36016 *ptr) 244{ 245 // stop any processing 246 zr36016_write(ptr, ZR016_GOSTOP, 0); 247 248 // mode setup (yuv422 in and out, compression/expansuon due to mode) 249 zr36016_write(ptr, ZR016_MODE, 250 ZR016_YUV422 | ZR016_YUV422_YUV422 | 251 (ptr->mode == CODEC_DO_COMPRESSION ? 252 ZR016_COMPRESSION : ZR016_EXPANSION)); 253 254 // misc setup 255 zr36016_writei(ptr, ZR016I_SETUP1, 256 (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) | 257 (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI); 258 zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR); 259 260 // Window setup 261 // (no extra offset for now, norm defines offset, default width height) 262 zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8); 263 zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF); 264 zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8); 265 zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF); 266 zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8); 267 zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF); 268 zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8); 269 zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF); 270 271 /* shall we continue now, please? */ 272 zr36016_write(ptr, ZR016_GOSTOP, 1); 273} 274 275/* ========================================================================= 276 CODEC API FUNCTIONS 277 278 this functions are accessed by the master via the API structure 279 ========================================================================= */ 280 281/* set compression/expansion mode and launches codec - 282 this should be the last call from the master before starting processing */ 283static int 284zr36016_set_mode (struct videocodec *codec, 285 int mode) 286{ 287 struct zr36016 *ptr = (struct zr36016 *) codec->data; 288 289 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); 290 291 if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) 292 return -EINVAL; 293 294 ptr->mode = mode; 295 zr36016_init(ptr); 296 297 return 0; 298} 299 300/* set picture size */ 301static int 302zr36016_set_video (struct videocodec *codec, 303 struct tvnorm *norm, 304 struct vfe_settings *cap, 305 struct vfe_polarity *pol) 306{ 307 struct zr36016 *ptr = (struct zr36016 *) codec->data; 308 309 dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n", 310 ptr->name, norm->HStart, norm->VStart, 311 cap->x, cap->y, cap->width, cap->height, 312 cap->decimation); 313 314 /* if () return -EINVAL; 315 * trust the master driver that it knows what it does - so 316 * we allow invalid startx/y for now ... */ 317 ptr->width = cap->width; 318 ptr->height = cap->height; 319 /* (Ronald) This is ugly. zoran_device.c, line 387 320 * already mentions what happens if HStart is even 321 * (blue faces, etc., cr/cb inversed). There's probably 322 * some good reason why HStart is 0 instead of 1, so I'm 323 * leaving it to this for now, but really... This can be 324 * done a lot simpler */ 325 ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x; 326 /* Something to note here (I don't understand it), setting 327 * VStart too high will cause the codec to 'not work'. I 328 * really don't get it. values of 16 (VStart) already break 329 * it here. Just '0' seems to work. More testing needed! */ 330 ptr->yoff = norm->VStart + cap->y; 331 /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */ 332 ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1; 333 ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1; 334 335 return 0; 336} 337 338/* additional control functions */ 339static int 340zr36016_control (struct videocodec *codec, 341 int type, 342 int size, 343 void *data) 344{ 345 struct zr36016 *ptr = (struct zr36016 *) codec->data; 346 int *ival = (int *) data; 347 348 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, 349 size); 350 351 switch (type) { 352 case CODEC_G_STATUS: /* get last status - we don't know it ... */ 353 if (size != sizeof(int)) 354 return -EFAULT; 355 *ival = 0; 356 break; 357 358 case CODEC_G_CODEC_MODE: 359 if (size != sizeof(int)) 360 return -EFAULT; 361 *ival = 0; 362 break; 363 364 case CODEC_S_CODEC_MODE: 365 if (size != sizeof(int)) 366 return -EFAULT; 367 if (*ival != 0) 368 return -EINVAL; 369 /* not needed, do nothing */ 370 return 0; 371 372 case CODEC_G_VFE: 373 case CODEC_S_VFE: 374 return 0; 375 376 case CODEC_S_MMAP: 377 /* not available, give an error */ 378 return -ENXIO; 379 380 default: 381 return -EINVAL; 382 } 383 384 return size; 385} 386 387/* ========================================================================= 388 Exit and unregister function: 389 390 Deinitializes Zoran's JPEG processor 391 ========================================================================= */ 392 393static int 394zr36016_unset (struct videocodec *codec) 395{ 396 struct zr36016 *ptr = codec->data; 397 398 if (ptr) { 399 /* do wee need some codec deinit here, too ???? */ 400 401 dprintk(1, "%s: finished codec #%d\n", ptr->name, 402 ptr->num); 403 kfree(ptr); 404 codec->data = NULL; 405 406 zr36016_codecs--; 407 return 0; 408 } 409 410 return -EFAULT; 411} 412 413/* ========================================================================= 414 Setup and registry function: 415 416 Initializes Zoran's JPEG processor 417 418 Also sets pixel size, average code size, mode (compr./decompr.) 419 (the given size is determined by the processor with the video interface) 420 ========================================================================= */ 421 422static int 423zr36016_setup (struct videocodec *codec) 424{ 425 struct zr36016 *ptr; 426 int res; 427 428 dprintk(2, "zr36016: initializing VFE subsystem #%d.\n", 429 zr36016_codecs); 430 431 if (zr36016_codecs == MAX_CODECS) { 432 dprintk(1, 433 KERN_ERR "zr36016: Can't attach more codecs!\n"); 434 return -ENOSPC; 435 } 436 //mem structure init 437 codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL); 438 if (NULL == ptr) { 439 dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n"); 440 return -ENOMEM; 441 } 442 443 snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]", 444 zr36016_codecs); 445 ptr->num = zr36016_codecs++; 446 ptr->codec = codec; 447 448 //testing 449 res = zr36016_basic_test(ptr); 450 if (res < 0) { 451 zr36016_unset(codec); 452 return res; 453 } 454 //final setup 455 ptr->mode = CODEC_DO_COMPRESSION; 456 ptr->width = 768; 457 ptr->height = 288; 458 ptr->xdec = 1; 459 ptr->ydec = 0; 460 zr36016_init(ptr); 461 462 dprintk(1, KERN_INFO "%s: codec v%d attached and running\n", 463 ptr->name, ptr->version); 464 465 return 0; 466} 467 468static const struct videocodec zr36016_codec = { 469 .owner = THIS_MODULE, 470 .name = "zr36016", 471 .magic = 0L, // magic not used 472 .flags = 473 CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER | 474 CODEC_FLAG_DECODER, 475 .type = CODEC_TYPE_ZR36016, 476 .setup = zr36016_setup, // functionality 477 .unset = zr36016_unset, 478 .set_mode = zr36016_set_mode, 479 .set_video = zr36016_set_video, 480 .control = zr36016_control, 481 // others are not used 482}; 483 484/* ========================================================================= 485 HOOK IN DRIVER AS KERNEL MODULE 486 ========================================================================= */ 487 488static int __init 489zr36016_init_module (void) 490{ 491 //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION); 492 zr36016_codecs = 0; 493 return videocodec_register(&zr36016_codec); 494} 495 496static void __exit 497zr36016_cleanup_module (void) 498{ 499 if (zr36016_codecs) { 500 dprintk(1, 501 "zr36016: something's wrong - %d codecs left somehow.\n", 502 zr36016_codecs); 503 } 504 videocodec_unregister(&zr36016_codec); 505} 506 507module_init(zr36016_init_module); 508module_exit(zr36016_cleanup_module); 509 510MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>"); 511MODULE_DESCRIPTION("Driver module for ZR36016 video frontends " 512 ZR016_VERSION); 513MODULE_LICENSE("GPL"); 514