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 static void 250 zr36016_init (struct zr36016 *ptr) 251 { 252 // stop any processing 253 zr36016_write(ptr, ZR016_GOSTOP, 0); 254 255 // mode setup (yuv422 in and out, compression/expansuon due to mode) 256 zr36016_write(ptr, ZR016_MODE, 257 ZR016_YUV422 | ZR016_YUV422_YUV422 | 258 (ptr->mode == CODEC_DO_COMPRESSION ? 259 ZR016_COMPRESSION : ZR016_EXPANSION)); 260 261 // misc setup 262 zr36016_writei(ptr, ZR016I_SETUP1, 263 (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) | 264 (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI); 265 zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR); 266 267 // Window setup 268 // (no extra offset for now, norm defines offset, default width height) 269 zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8); 270 zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF); 271 zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8); 272 zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF); 273 zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8); 274 zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF); 275 zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8); 276 zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF); 277 278 /* shall we continue now, please? */ 279 zr36016_write(ptr, ZR016_GOSTOP, 1); 280 } 281 282 /* ========================================================================= 283 CODEC API FUNCTIONS 284 285 this functions are accessed by the master via the API structure 286 ========================================================================= */ 287 288 /* set compression/expansion mode and launches codec - 289 this should be the last call from the master before starting processing */ 290 static int 291 zr36016_set_mode (struct videocodec *codec, 292 int mode) 293 { 294 struct zr36016 *ptr = (struct zr36016 *) codec->data; 295 296 dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); 297 298 if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) 299 return -EINVAL; 300 301 ptr->mode = mode; 302 zr36016_init(ptr); 303 304 return 0; 305 } 306 307 /* set picture size */ 308 static int 309 zr36016_set_video (struct videocodec *codec, 310 struct tvnorm *norm, 311 struct vfe_settings *cap, 312 struct vfe_polarity *pol) 313 { 314 struct zr36016 *ptr = (struct zr36016 *) codec->data; 315 316 dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n", 317 ptr->name, norm->HStart, norm->VStart, 318 cap->x, cap->y, cap->width, cap->height, 319 cap->decimation); 320 321 /* if () return -EINVAL; 322 * trust the master driver that it knows what it does - so 323 * we allow invalid startx/y for now ... */ 324 ptr->width = cap->width; 325 ptr->height = cap->height; 326 /* (Ronald) This is ugly. zoran_device.c, line 387 327 * already mentions what happens if HStart is even 328 * (blue faces, etc., cr/cb inversed). There's probably 329 * some good reason why HStart is 0 instead of 1, so I'm 330 * leaving it to this for now, but really... This can be 331 * done a lot simpler */ 332 ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x; 333 /* Something to note here (I don't understand it), setting 334 * VStart too high will cause the codec to 'not work'. I 335 * really don't get it. values of 16 (VStart) already break 336 * it here. Just '0' seems to work. More testing needed! */ 337 ptr->yoff = norm->VStart + cap->y; 338 /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */ 339 ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1; 340 ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1; 341 342 return 0; 343 } 344 345 /* additional control functions */ 346 static int 347 zr36016_control (struct videocodec *codec, 348 int type, 349 int size, 350 void *data) 351 { 352 struct zr36016 *ptr = (struct zr36016 *) codec->data; 353 int *ival = (int *) data; 354 355 dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, 356 size); 357 358 switch (type) { 359 case CODEC_G_STATUS: /* get last status - we don't know it ... */ 360 if (size != sizeof(int)) 361 return -EFAULT; 362 *ival = 0; 363 break; 364 365 case CODEC_G_CODEC_MODE: 366 if (size != sizeof(int)) 367 return -EFAULT; 368 *ival = 0; 369 break; 370 371 case CODEC_S_CODEC_MODE: 372 if (size != sizeof(int)) 373 return -EFAULT; 374 if (*ival != 0) 375 return -EINVAL; 376 /* not needed, do nothing */ 377 return 0; 378 379 case CODEC_G_VFE: 380 case CODEC_S_VFE: 381 return 0; 382 383 case CODEC_S_MMAP: 384 /* not available, give an error */ 385 return -ENXIO; 386 387 default: 388 return -EINVAL; 389 } 390 391 return size; 392 } 393 394 /* ========================================================================= 395 Exit and unregister function: 396 397 Deinitializes Zoran's JPEG processor 398 ========================================================================= */ 399 400 static int 401 zr36016_unset (struct videocodec *codec) 402 { 403 struct zr36016 *ptr = codec->data; 404 405 if (ptr) { 406 /* do wee need some codec deinit here, too ???? */ 407 408 dprintk(1, "%s: finished codec #%d\n", ptr->name, 409 ptr->num); 410 kfree(ptr); 411 codec->data = NULL; 412 413 zr36016_codecs--; 414 return 0; 415 } 416 417 return -EFAULT; 418 } 419 420 /* ========================================================================= 421 Setup and registry function: 422 423 Initializes Zoran's JPEG processor 424 425 Also sets pixel size, average code size, mode (compr./decompr.) 426 (the given size is determined by the processor with the video interface) 427 ========================================================================= */ 428 429 static int 430 zr36016_setup (struct videocodec *codec) 431 { 432 struct zr36016 *ptr; 433 int res; 434 435 dprintk(2, "zr36016: initializing VFE subsystem #%d.\n", 436 zr36016_codecs); 437 438 if (zr36016_codecs == MAX_CODECS) { 439 dprintk(1, 440 KERN_ERR "zr36016: Can't attach more codecs!\n"); 441 return -ENOSPC; 442 } 443 //mem structure init 444 codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL); 445 if (NULL == ptr) { 446 dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n"); 447 return -ENOMEM; 448 } 449 450 snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]", 451 zr36016_codecs); 452 ptr->num = zr36016_codecs++; 453 ptr->codec = codec; 454 455 //testing 456 res = zr36016_basic_test(ptr); 457 if (res < 0) { 458 zr36016_unset(codec); 459 return res; 460 } 461 //final setup 462 ptr->mode = CODEC_DO_COMPRESSION; 463 ptr->width = 768; 464 ptr->height = 288; 465 ptr->xdec = 1; 466 ptr->ydec = 0; 467 zr36016_init(ptr); 468 469 dprintk(1, KERN_INFO "%s: codec v%d attached and running\n", 470 ptr->name, ptr->version); 471 472 return 0; 473 } 474 475 static const struct videocodec zr36016_codec = { 476 .owner = THIS_MODULE, 477 .name = "zr36016", 478 .magic = 0L, // magic not used 479 .flags = 480 CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER | 481 CODEC_FLAG_DECODER, 482 .type = CODEC_TYPE_ZR36016, 483 .setup = zr36016_setup, // functionality 484 .unset = zr36016_unset, 485 .set_mode = zr36016_set_mode, 486 .set_video = zr36016_set_video, 487 .control = zr36016_control, 488 // others are not used 489 }; 490 491 /* ========================================================================= 492 HOOK IN DRIVER AS KERNEL MODULE 493 ========================================================================= */ 494 495 static int __init 496 zr36016_init_module (void) 497 { 498 //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION); 499 zr36016_codecs = 0; 500 return videocodec_register(&zr36016_codec); 501 } 502 503 static void __exit 504 zr36016_cleanup_module (void) 505 { 506 if (zr36016_codecs) { 507 dprintk(1, 508 "zr36016: something's wrong - %d codecs left somehow.\n", 509 zr36016_codecs); 510 } 511 videocodec_unregister(&zr36016_codec); 512 } 513 514 module_init(zr36016_init_module); 515 module_exit(zr36016_cleanup_module); 516 517 MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>"); 518 MODULE_DESCRIPTION("Driver module for ZR36016 video frontends " 519 ZR016_VERSION); 520 MODULE_LICENSE("GPL"); 521