Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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