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