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