1/* @file plustek-pp_p12.c 2 * @brief p12 and pt12 specific stuff 3 * 4 * based on sources acquired from Plustek Inc. 5 * Copyright (C) 2000 Plustek Inc. 6 * Copyright (C) 2001-2013 Gerhard Jaeger <gerhard@gjaeger.de> 7 * 8 * History: 9 * - 0.38 - initial version 10 * - 0.39 - added Genius Colorpage Vivid III V2 stuff 11 * - 0.40 - no changes 12 * - 0.41 - no changes 13 * - 0.42 - removed setting of ps->sCaps.dwFlag in p12InitiateComponentModel() 14 * - 0.43 - no changes 15 * - 0.44 - fix format string issues, as Long types default to int32_t 16 * now 17 * . 18 * <hr> 19 * This file is part of the SANE package. 20 * 21 * This program is free software; you can redistribute it and/or 22 * modify it under the terms of the GNU General Public License as 23 * published by the Free Software Foundation; either version 2 of the 24 * License, or (at your option) any later version. 25 * 26 * This program is distributed in the hope that it will be useful, but 27 * WITHOUT ANY WARRANTY; without even the implied warranty of 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 * General Public License for more details. 30 * 31 * You should have received a copy of the GNU General Public License 32 * along with this program. If not, see <https://www.gnu.org/licenses/>. 33 * 34 * As a special exception, the authors of SANE give permission for 35 * additional uses of the libraries contained in this release of SANE. 36 * 37 * The exception is that, if you link a SANE library with other files 38 * to produce an executable, this does not by itself cause the 39 * resulting executable to be covered by the GNU General Public 40 * License. Your use of that executable is in no way restricted on 41 * account of linking the SANE library code into it. 42 * 43 * This exception does not, however, invalidate any other reasons why 44 * the executable file might be covered by the GNU General Public 45 * License. 46 * 47 * If you submit changes to SANE to the maintainers to be included in 48 * a subsequent release, you agree by submitting the changes that 49 * those changes may be distributed with this exception intact. 50 * 51 * If you write modifications of your own for SANE, it is your choice 52 * whether to permit this exception to apply to your modifications. 53 * If you do not wish that, delete this exception notice. 54 * <hr> 55 */ 56#include "plustek-pp_scan.h" 57 58/*************************** some local vars *********************************/ 59 60static RegDef p12CcdStop[] = { 61 {0x41, 0xff}, {0x42, 0xff}, {0x60, 0xff}, {0x61, 0xff}, 62 {0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff}, 63 {0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x15, 0x00} 64}; 65 66/*************************** local functions *********************************/ 67 68/** init the stuff according to the buttons 69 */ 70static void p12ButtonSetup( pScanData ps, Byte nrOfButtons ) 71{ 72 ps->Device.buttons = nrOfButtons; 73 74 ps->Device.Model1Mono &= ~_BUTTON_MODE; 75 ps->Device.Model1Color &= ~_BUTTON_MODE; 76 77 ps->AsicReg.RD_MotorDriverType |= _BUTTON_DISABLE; 78 ps->Scan.motorPower |= _BUTTON_DISABLE; 79} 80 81/** According to what we have detected, set the other stuff 82 */ 83static void p12InitiateComponentModel( pScanData ps ) 84{ 85 /* preset some stuff and do the differences later */ 86 ps->Device.buttons = 0; 87 ps->Device.Model1Mono = _BUTTON_MODE + _CCD_SHIFT_GATE + _SCAN_GRAYTYPE; 88 ps->Device.Model1Color = _BUTTON_MODE + _CCD_SHIFT_GATE; 89 ps->Device.dwModelOriginY = 64; 90 ps->Device.fTpa = _FALSE; 91 ps->Device.ModelCtrl = (_LED_ACTIVITY | _LED_CONTROL); 92 93 /* ps->sCaps.dwFlag should have been set correctly in models.c */ 94 95 switch( ps->Device.bPCBID ) { 96 97 case _PLUSTEK_SCANNER: 98 DBG( DBG_LOW, "We have a Plustek Scanner\n" ); 99 ps->sCaps.Model = MODEL_OP_P12; 100 break; 101 102 case _SCANNER_WITH_TPA: 103 DBG( DBG_LOW, "Scanner has TPA\n" ); 104 ps->Device.fTpa = _TRUE; 105 ps->sCaps.dwFlag |= SFLAG_TPA; 106 break; 107 108 case _SCANNER4Button: 109 DBG( DBG_LOW, "Scanner has 4 Buttons\n" ); 110 p12ButtonSetup( ps, 4 ); 111 break; 112 113 case _SCANNER4ButtonTPA: 114 DBG( DBG_LOW, "Scanner has 4 Buttons & TPA\n" ); 115 ps->Device.fTpa = _TRUE; 116 ps->sCaps.dwFlag |= SFLAG_TPA; 117 p12ButtonSetup( ps, 4 ); 118 break; 119 120 case _SCANNER5Button: 121 DBG( DBG_LOW, "Scanner has 5 Buttons\n" ); 122 ps->Device.dwModelOriginY = 64 + 20; 123 p12ButtonSetup( ps, 5 ); 124 break; 125 126 case _SCANNER5ButtonTPA: 127 DBG( DBG_LOW, "Scanner has 5 Buttons & TPA\n" ); 128 ps->Device.dwModelOriginY = 64 + 20; 129 ps->Device.fTpa = _TRUE; 130 ps->sCaps.dwFlag |= SFLAG_TPA; 131 p12ButtonSetup( ps, 5 ); 132 break; 133 134 case _SCANNER1Button: 135 DBG( DBG_LOW, "Scanner has 1 Button\n" ); 136 p12ButtonSetup( ps, 1 ); 137 break; 138 139 case _SCANNER1ButtonTPA: 140 DBG( DBG_LOW, "Scanner has 1 Button & TPA\n" ); 141 ps-> Device.fTpa = _TRUE; 142 ps->sCaps.dwFlag |= SFLAG_TPA; 143 p12ButtonSetup( ps, 1 ); 144 break; 145 146 case _AGFA_SCANNER: 147 DBG( DBG_LOW, "Agfa Scanner\n" ); 148 ps->Device.dwModelOriginY = 24; /* 1200 dpi */ 149 break; 150 151 case _SCANNER2Button: 152 DBG( DBG_LOW, "Scanner has 2 Buttons\n" ); 153 DBG( DBG_LOW, "Seems we have a Genius Colorpage Vivid III V2\n" ); 154 ps->Device.dwModelOriginY = 64 - 33; 155 p12ButtonSetup( ps, 2 ); 156 ps->sCaps.Model = MODEL_GEN_CPV2; 157 break; 158 159 default: 160 DBG( DBG_LOW, "Default Model: P12\n" ); 161 ps->sCaps.Model = MODEL_OP_P12; 162 break; 163 } 164 165 if( _MOTOR0_2003 == ps->Device.bMotorID ) { 166 ps->Device.f2003 = _TRUE; 167 ps->Device.XStepMono = 10; 168 ps->Device.XStepColor = 6; 169 ps->Device.XStepBack = 5; 170 ps->AsicReg.RD_MotorDriverType |= _MOTORR_STRONG; 171 } else { 172 ps->Device.f2003 = _FALSE; 173 ps->Device.XStepMono = 8; 174 ps->Device.XStepColor = 4; 175 ps->Device.XStepBack = 5; 176 ps->AsicReg.RD_MotorDriverType |= _MOTORR_WEAK; 177 } 178} 179 180/*............................................................................. 181 * prepare all the necessary variables - 182 */ 183static void p12SetupScannerVariables( pScanData ps ) 184{ 185 DBG( DBG_LOW, "p12SetupScannerVariables()\n" ); 186 187 /* 188 * these values were originally altered by registry entries (NT-driver) 189 * and used to adjust the picture position... 190 */ 191 ps->Device.lUpNormal = 0; 192 ps->Device.lUpNegative = 20; 193 ps->Device.lUpPositive = -30; 194 195 ps->Device.lLeftNormal = 51; 196 197 ps->OpenScanPath( ps ); 198 ps->ReInitAsic( ps, _FALSE ); 199 ps->CloseScanPath( ps ); 200} 201 202/*............................................................................. 203 * 204 */ 205static void p12SetupScanningCondition( pScanData ps ) 206{ 207 TimerDef timer; 208 ULong channel; 209 Byte bState; 210 pUChar pState = ps->Bufs.b1.pReadBuf; 211 212 DBG( DBG_LOW, "p12SetupScanningCondition()\n" ); 213 214 P12SetGeneralRegister( ps ); 215 216 IORegisterToScanner( ps, ps->RegResetMTSC ); 217 218 /* ------- Setup MinRead/MaxRead Fifo size ------- */ 219 if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) { 220 ps->Scan.dwMaxReadFifo = 221 ps->Scan.dwMinReadFifo = ps->DataInf.dwAsicBytesPerPlane * 2; 222 } else { 223 ps->Scan.dwMaxReadFifo = 224 ps->Scan.dwMinReadFifo = ps->DataInf.dwAppPixelsPerLine << 1; 225 } 226 227 if( ps->Scan.dwMinReadFifo < 1024) 228 ps->Scan.dwMinReadFifo = ps->Scan.dwMaxReadFifo = 1024; 229 230 ps->Scan.dwMaxReadFifo += (ps->DataInf.dwAsicBytesPerPlane / 2); 231 232 233 DBG( DBG_LOW, "MinReadFifo=%u, MaxReadFifo=%u\n", 234 ps->Scan.dwMinReadFifo, ps->Scan.dwMaxReadFifo ); 235 236 /* ------- Set the max. read fifo to asic ------- */ 237 if( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { 238 239 ps->Scan.bFifoSelect = ps->RegBFifoOffset; 240 241 if( !ps->Scan.p48BitBuf.pb ) { 242 243 Long lRed, lGreen; 244 245 lRed = (_SIZE_REDFIFO - _SIZE_BLUEFIFO) / 246 ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep; 247 248 lGreen = (_SIZE_GREENFIFO - _SIZE_BLUEFIFO) / 249 ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep; 250 251 if((lRed < 0) || (lGreen < 0)) { 252 253 if( lRed < lGreen ) { 254 channel = _RED_FULLSIZE << 16; 255 ps->AsicReg.RD_BufFullSize = _SIZE_REDFIFO; 256 lGreen = lRed; 257 } else { 258 channel = _GREEN_FULLSIZE << 16; 259 ps->AsicReg.RD_BufFullSize = _SIZE_GREENFIFO; 260 } 261 262 lGreen = (ULong)(-lGreen * ps->DataInf.dwAsicBytesPerPlane); 263 264 if( ps->DataInf.wPhyDataType > COLOR_TRUE24 ) 265 lGreen >>= 1; 266 267 ps->Scan.dwMinReadFifo += (ULong)lGreen; 268 ps->Scan.dwMaxReadFifo += (ULong)lGreen; 269 270 } else { 271 channel = _BLUE_FULLSIZE << 16; 272 ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO; 273 } 274 } else { 275 channel = _BLUE_FULLSIZE << 16; 276 ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO; 277 } 278 } else { 279 ps->Scan.bFifoSelect = ps->RegGFifoOffset; 280 channel = _GREEN_FULLSIZE << 16; 281 ps->AsicReg.RD_BufFullSize = _SIZE_GRAYFIFO; 282 } 283 284 ps->AsicReg.RD_BufFullSize -= (ps->DataInf.dwAsicBytesPerPlane << 1); 285 286 if( ps->DataInf.wPhyDataType > COLOR_TRUE24 ) 287 ps->AsicReg.RD_BufFullSize >>= 1; 288 289 ps->AsicReg.RD_BufFullSize |= channel; 290 291 ps->Scan.bRefresh = (Byte)(ps->Scan.dwInterval << 1); 292 ps->AsicReg.RD_LineControl = (_LOBYTE (ps->Shade.wExposure)); 293 ps->AsicReg.RD_ExtLineControl = (_HIBYTE (ps->Shade.wExposure)); 294 ps->AsicReg.RD_XStepTime = (_LOBYTE (ps->Shade.wXStep)); 295 ps->AsicReg.RD_ExtXStepTime = (_HIBYTE (ps->Shade.wXStep)); 296 ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; 297 ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; 298 ps->AsicReg.RD_ModeControl = (_ModeScan | _ModeFifoGSel); 299 300 DBG( DBG_LOW, "bRefresh = %i\n", ps->Scan.bRefresh ); 301 302 if( ps->DataInf.wPhyDataType == COLOR_BW ) { 303 ps->AsicReg.RD_ScanControl = _SCAN_BITMODE; 304 305 if( !(ps->DataInf.dwScanFlag & SCANDEF_Inverse)) 306 ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT; 307 308 } else if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) 309 ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; 310 else { 311 ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE; 312 313 if(!(ps->DataInf.dwScanFlag & SCANDEF_RightAlign)) 314 ps->AsicReg.RD_ScanControl |= _BITALIGN_LEFT; 315 316 if( ps->DataInf.dwScanFlag & SCANDEF_Inverse) 317 ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT; 318 } 319 320 ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE; 321 IOSelectLampSource( ps ); 322 323 DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl ); 324 325 ps->AsicReg.RD_MotorTotalSteps = (ULong)ps->DataInf.crImage.cy * 4 + 326 ((ps->Device.f0_8_16) ? 32 : 16) + 327 ((ps->Scan.bDiscardAll) ? 32 : 0); 328 329 ps->AsicReg.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL | 330 _MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP); 331 332 ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x; 333 334 if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA )) { 335 336 ps->AsicReg.RD_Origin = (UShort)(ps->Device.lLeftNormal * 2 + 337 ps->Device.DataOriginX + 338 ps->DataInf.crImage.x ); 339 340 } else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) { 341 ps->AsicReg.RD_Origin = 342 (UShort)(ps->Scan.posBegin + ps->DataInf.crImage.x); 343 } else { 344 ps->AsicReg.RD_Origin = 345 (UShort)(ps->Scan.negBegin + ps->DataInf.crImage.x); 346 } 347 348 if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) 349 ps->AsicReg.RD_Origin >>= 1; 350 351 if( ps->DataInf.wPhyDataType == COLOR_BW ) 352 ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicBytesPerPlane; 353 else 354 ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAppPixelsPerLine; 355 356 DBG( DBG_LOW, "RD_Origin = %u, RD_Pixels = %u\n", 357 ps->AsicReg.RD_Origin, ps->AsicReg.RD_Pixels ); 358 359 /* ------- Prepare scan states ------- */ 360 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); 361 memset( ps->Bufs.b1.pReadBuf, 0, _NUMBER_OF_SCANSTEPS ); 362 363 if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) 364 bState = (_SS_MONO | _SS_STEP); 365 else 366 bState = (_SS_COLOR | _SS_STEP); 367 368 for( channel = _NUMBER_OF_SCANSTEPS; 369 channel; channel -= ps->Scan.dwInterval ) { 370 *pState = bState; 371 if( ps->Scan.dwInterlace ) 372 pState[ ps->Scan.dwInterlace] = _SS_STEP; 373 pState += ps->Scan.dwInterval; 374 } 375 for( channel = 0, pState = ps->Bufs.b1.pReadBuf; 376 channel < _SCANSTATE_BYTES; channel++) { 377 ps->a_nbNewAdrPointer[channel] = pState [0] | (pState [1] << 4); 378 pState += 2; 379 } 380 381 /* ------- Wait for scan state stop ------- */ 382 MiscStartTimer( &timer, _SECOND * 2 ); 383 384 while(!(IOGetScanState( ps, _FALSE ) & _SCANSTATE_STOP) && 385 !MiscCheckTimer(&timer)); 386 387/* CHECK: Replace by IOPutAll.... */ 388 IODownloadScanStates( ps ); 389 IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl); 390 IODataToRegister( ps, ps->RegExtendedLineControl, 391 ps->AsicReg.RD_ExtLineControl); 392 IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); 393 IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime); 394 IODataToRegister( ps, ps->RegMotorDriverType, 395 ps->AsicReg.RD_MotorDriverType); 396 IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl); 397 IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control); 398 IODataToRegister( ps, ps->RegModelControl,ps->AsicReg.RD_ModelControl); 399 IODataToRegister( ps, ps->RegDpiLow, (_LOBYTE(ps->AsicReg.RD_Dpi))); 400 IODataToRegister( ps, ps->RegDpiHigh, (_HIBYTE(ps->AsicReg.RD_Dpi))); 401 IODataToRegister( ps, ps->RegScanPosLow, (_LOBYTE(ps->AsicReg.RD_Origin))); 402 IODataToRegister( ps, ps->RegScanPosHigh,(_HIBYTE(ps->AsicReg.RD_Origin))); 403 IODataToRegister( ps, ps->RegWidthPixelsLow, 404 (_LOBYTE(ps->AsicReg.RD_Pixels))); 405 IODataToRegister( ps, ps->RegWidthPixelsHigh, 406 (_HIBYTE(ps->AsicReg.RD_Pixels))); 407 IODataToRegister( ps, ps->RegThresholdLow, 408 (_LOBYTE(ps->AsicReg.RD_ThresholdControl))); 409 IODataToRegister( ps, ps->RegThresholdHigh, 410 (_HIBYTE(ps->AsicReg.RD_ThresholdControl))); 411 IODataToRegister( ps, ps->RegMotorTotalStep0, 412 (_LOBYTE(ps->AsicReg.RD_MotorTotalSteps))); 413 IODataToRegister( ps, ps->RegMotorTotalStep1, 414 (_HIBYTE(ps->AsicReg.RD_MotorTotalSteps))); 415 IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); 416 417 IORegisterToScanner( ps, ps->RegInitDataFifo); 418} 419 420/*............................................................................. 421 * program the CCD relevant stuff 422 */ 423static void p12ProgramCCD( pScanData ps) 424{ 425 UShort w; 426 pRegDef rp; 427 428 DBG( DBG_IO, "p12ProgramCCD: 0x%08lx[%lu]\n", 429 (unsigned long)ps->Device.pCCDRegisters, 430 ((unsigned long)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate)); 431 432 DBG( DBG_IO, " %u regs * %u (intermediate)\n", 433 ps->Device.wNumCCDRegs, ps->Shade.bIntermediate ); 434 435 rp = ps->Device.pCCDRegisters + 436 (ULong)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate; 437 438 for( w = ps->Device.wNumCCDRegs; w--; rp++ ) { 439 440 DBG( DBG_IO, "[0x%02x] = 0x%02x\n", rp->bReg, rp->bParam ); 441 IODataToRegister( ps, rp->bReg, rp->bParam ); 442 } 443} 444 445/*............................................................................. 446 * this initializes the ASIC and prepares the different functions for shading 447 * and scanning 448 */ 449static void p12Init98003( pScanData ps, Bool shading ) 450{ 451 DBG( DBG_LOW, "p12InitP98003(%d)\n", shading ); 452 453 /* get DAC and motor stuff */ 454 ps->Device.bDACType = IODataFromRegister( ps, ps->RegResetConfig ); 455 ps->Device.bMotorID = (Byte)(ps->Device.bDACType & _MOTOR0_MASK); 456 457 ps->AsicReg.RD_MotorDriverType = 458 (Byte)((ps->Device.bDACType & _MOTOR0_MASK) >> 3); 459 ps->AsicReg.RD_MotorDriverType |= 460 (Byte)((ps->Device.bDACType & _MOTOR1_MASK) >> 1); 461 462 463 ps->Scan.motorPower = ps->AsicReg.RD_MotorDriverType | _MOTORR_STRONG; 464 465 ps->Device.bDACType &= _ADC_MASK; 466 467 /*get CCD and PCB ID */ 468 ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration ); 469 ps->Device.bCCDID = ps->Device.bPCBID & 0x07; 470 ps->Device.bPCBID &= 0xf0; 471 472 if( _AGFA_SCANNER == ps->Device.bPCBID ) 473 ps->Device.bDACType = _DA_WOLFSON8141; 474 475 DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x, DAC-TYPE=0x%02x\n", 476 ps->Device.bPCBID, ps->Device.bCCDID, ps->Device.bDACType ); 477 478 p12InitiateComponentModel( ps ); 479 480 /* encode the CCD-id into the flag parameter */ 481 ps->sCaps.dwFlag |= ((ULong)(ps->Device.bCCDID | ps->Device.bPCBID) << 16); 482 483 P12InitCCDandDAC( ps, shading ); 484 485 if( ps->Shade.bIntermediate & _ScanMode_Mono ) 486 ps->AsicReg.RD_Model1Control = ps->Device.Model1Mono; 487 else 488 ps->AsicReg.RD_Model1Control = ps->Device.Model1Color; 489 490 IODataToRegister( ps, ps->RegPllPredivider, 1 ); 491 IODataToRegister( ps, ps->RegPllMaindivider, 0x20 ); 492 IODataToRegister( ps, ps->RegPllPostdivider, 2 ); 493 IODataToRegister( ps, ps->RegClockSelector, 3 ); /* 2 */ 494 IODataToRegister( ps, ps->RegMotorDriverType, 495 ps->AsicReg.RD_MotorDriverType ); 496 497 /* this might be changed, def value is 11 */ 498 IODataToRegister( ps, ps->RegWaitStateInsert, 11 ); 499 IODataToRegister( ps, ps->RegModel1Control, ps->AsicReg.RD_Model1Control ); 500 501 p12ProgramCCD( ps ); 502} 503 504/*............................................................................. 505 * initialize the register values for the 98003 asic and preset other stuff 506 */ 507static void p12InitializeAsicRegister( pScanData ps ) 508{ 509 memset( &ps->AsicReg, 0, sizeof(RegData)); 510} 511 512/*............................................................................. 513 * as the function name says 514 */ 515static void p12PutToIdleMode( pScanData ps ) 516{ 517 ULong i; 518 519 ps->OpenScanPath( ps ); 520 521 DBG( DBG_IO, "CCD-Stop\n" ); 522 523 for( i = 0; i < 13; i++ ) { 524 525 DBG( DBG_IO, "[0x%02x] = 0x%02x\n", 526 p12CcdStop[i].bReg, p12CcdStop[i].bParam ); 527 528 IODataToRegister( ps, p12CcdStop[i].bReg, p12CcdStop[i].bParam ); 529 } 530 531 ps->CloseScanPath( ps ); 532} 533 534/*............................................................................. 535 * here we simply call the WaitForShading function which performs this topic 536 */ 537static int p12Calibration( pScanData ps ) 538{ 539 Bool result; 540 541 DBG( DBG_LOW, "p12Calibration()\n" ); 542 543 /* 544 * wait for shading to be done 545 */ 546 ps->OpenScanPath( ps ); 547 548 _ASSERT(ps->WaitForShading); 549 result = ps->WaitForShading( ps ); 550 ps->CloseScanPath( ps ); 551 552 if( !result ) 553 return _E_TIMEOUT; 554 555 return _OK; 556} 557 558/************************ exported functions *********************************/ 559 560/*............................................................................. 561 * initialize the register values and function calls for the 98003 asic 562 */ 563_LOC int P12InitAsic( pScanData ps ) 564{ 565 int result; 566 567 DBG( DBG_LOW, "P12InitAsic()\n" ); 568 569 /* 570 * preset the asic shadow registers 571 */ 572 p12InitializeAsicRegister( ps ); 573 574 ps->IO.bOpenCount = 0; 575 576 /* 577 * setup the register values 578 */ 579 ps->RegSwitchBus = 0; 580 ps->RegEPPEnable = 1; 581 ps->RegECPEnable = 2; 582 ps->RegReadDataMode = 3; 583 ps->RegWriteDataMode = 4; 584 ps->RegInitDataFifo = 5; 585 ps->RegForceStep = 6; 586 ps->RegInitScanState = 7; 587 ps->RegRefreshScanState = 8; 588 ps->RegWaitStateInsert = 0x0a; 589 ps->RegRFifoOffset = 0x0a; 590 ps->RegGFifoOffset = 0x0b; 591 ps->RegBFifoOffset = 0x0c; 592 ps->RegBitDepth = 0x13; 593 ps->RegStepControl = 0x14; 594 ps->RegMotor0Control = 0x15; 595 ps->RegXStepTime = 0x16; 596 ps->RegGetScanState = 0x17; 597 ps->RegAsicID = 0x18; 598 ps->RegMemoryLow = 0x19; 599 ps->RegMemoryHigh = 0x1a; 600 ps->RegModeControl = 0x1b; 601 ps->RegLineControl = 0x1c; 602 ps->RegScanControl = 0x1d; 603 ps->RegConfiguration = 0x1e; 604 ps->RegModelControl = 0x1f; 605 ps->RegModel1Control = 0x20; 606 ps->RegDpiLow = 0x21; 607 ps->RegDpiHigh = 0x22; 608 ps->RegScanPosLow = 0x23; 609 ps->RegScanPosHigh = 0x24; 610 ps->RegWidthPixelsLow = 0x25; 611 ps->RegWidthPixelsHigh = 0x26; 612 ps->RegThresholdLow = 0x27; 613 ps->RegThresholdHigh = 0x28; 614 ps->RegThresholdGapControl = 0x29; 615 ps->RegADCAddress = 0x2a; 616 ps->RegADCData = 0x2b; 617 ps->RegADCPixelOffset = 0x2c; 618 ps->RegADCSerialOutStr = 0x2d; 619 ps->RegResetConfig = 0x2e; 620 ps->RegLensPosition = 0x2f; 621 ps->RegStatus = 0x30; 622 ps->RegScanStateControl = 0x31; 623 ps->RegRedChDarkOffsetLow = 0x33; 624 ps->RegRedChDarkOffsetHigh = 0x34; 625 ps->RegGreenChDarkOffsetLow = 0x35; 626 ps->RegGreenChDarkOffsetHigh= 0x36; 627 ps->RegBlueChDarkOffsetLow = 0x37; 628 ps->RegBlueChDarkOffsetHigh = 0x38; 629 ps->RegResetPulse0 = 0x39; 630 ps->RegResetPulse1 = 0x3a; 631 ps->RegCCDClampTiming0 = 0x3b; 632 ps->RegCCDClampTiming1 = 0x3c; 633 ps->RegVSMPTiming0 = 0x41; 634 ps->RegVSMPTiming1 = 0x42; 635 ps->RegCCDQ1Timing0 = 0x43; 636 ps->RegCCDQ1Timing1 = 0x44; 637 ps->RegCCDQ1Timing2 = 0x45; 638 ps->RegCCDQ1Timing3 = 0x46; 639 ps->RegCCDQ2Timing0 = 0x47; 640 ps->RegCCDQ2Timing1 = 0x48; 641 ps->RegCCDQ2Timing2 = 0x49; 642 ps->RegCCDQ2Timing3 = 0x4a; 643 ps->RegADCclockTiming0 = 0x4b; 644 ps->RegADCclockTiming1 = 0x4c; 645 ps->RegADCclockTiming2 = 0x4d; 646 ps->RegADCclockTiming3 = 0x4e; 647 ps->RegADCDVTiming0 = 0x50; 648 ps->RegADCDVTiming1 = 0x51; 649 ps->RegADCDVTiming2 = 0x52; 650 ps->RegADCDVTiming3 = 0x53; 651 652 ps->RegFifoFullLength0 = 0x54; 653 ps->RegFifoFullLength1 = 0x55; 654 ps->RegFifoFullLength2 = 0x56; 655 656 ps->RegMotorTotalStep0 = 0x57; 657 ps->RegMotorTotalStep1 = 0x58; 658 ps->RegMotorFreeRunCount0 = 0x59; 659 ps->RegMotorFreeRunCount1 = 0x5a; 660 ps->RegScanControl1 = 0x5b; 661 ps->RegMotorFreeRunTrigger = 0x5c; 662 663 ps->RegResetMTSC = 0x5d; 664 665 ps->RegMotor1Control = 0x62; 666 ps->RegMotor2Control = 0x63; 667 ps->RegMotorDriverType = 0x64; 668 669 ps->RegStatus2 = 0x66; 670 671 ps->RegExtendedLineControl = 0x6d; 672 ps->RegExtendedXStep = 0x6e; 673 674 ps->RegPllPredivider = 0x71; 675 ps->RegPllMaindivider = 0x72; 676 ps->RegPllPostdivider = 0x73; 677 ps->RegClockSelector = 0x74; 678 ps->RegTestMode = 0xf0; 679 680 /* 681 * setup function calls 682 */ 683 ps->SetupScannerVariables = p12SetupScannerVariables; 684 ps->SetupScanningCondition = p12SetupScanningCondition; 685 ps->Calibration = p12Calibration; 686 ps->PutToIdleMode = p12PutToIdleMode; 687 ps->ReInitAsic = p12Init98003; 688 689 ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE; 690 ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF; 691 692 ps->IO.useEPPCmdMode = _FALSE; 693 694 /* 695 * initialize the other modules and set some 696 * function pointer 697 */ 698 result = DacInitialize( ps ); 699 if( _OK != result ) 700 return result; 701 702 result = ImageInitialize( ps ); 703 if( _OK != result ) 704 return result; 705 706 result = IOFuncInitialize( ps ); 707 if( _OK != result ) 708 return result; 709 710 result = IOInitialize( ps ); 711 if( _OK != result ) 712 return result; 713 714 result = MotorInitialize( ps ); 715 if( _OK != result ) 716 return result; 717 718 if( _FALSE == ps->OpenScanPath( ps )) { 719 DBG( DBG_LOW, "P12InitAsic() failed.\n" ); 720 return _E_NO_DEV; 721 } 722 723 /*get CCD and PCB ID */ 724 ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration ); 725 ps->Device.bCCDID = ps->Device.bPCBID & 0x07; 726 ps->Device.bPCBID &= 0xf0; 727 728 DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x\n", ps->Device.bPCBID, ps->Device.bCCDID ); 729 730 /* get a more closer model description...*/ 731 p12InitiateComponentModel( ps ); 732 733 ps->CloseScanPath( ps ); 734 735 /* here we check for the OpticWorks 2000, which is not supported */ 736 if( _OPTICWORKS2000 == ps->Device.bPCBID ) { 737 DBG( DBG_LOW, "OpticWorks 2000 not supported!\n" ); 738 return _E_NOSUPP; 739 } 740 741 DBG( DBG_LOW, "P12InitAsic() done.\n" ); 742 return _OK; 743} 744 745/*............................................................................. 746 * set all necessary register contents 747 */ 748_LOC void P12SetGeneralRegister( pScanData ps ) 749{ 750 DBG( DBG_LOW, "P12SetGeneralRegister()\n" ); 751 752 ps->Scan.fMotorBackward = _FALSE; 753 ps->Scan.fRefreshState = _FALSE; 754 755 if( COLOR_BW == ps->DataInf.wPhyDataType ) 756 ps->AsicReg.RD_ScanControl = _SCAN_BITMODE; 757 else { 758 if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) 759 ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; 760 else 761 ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE; 762 } 763 764 IOSelectLampSource( ps ); 765 766 if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) 767 ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi300; 768 else 769 ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi600; 770 771 ps->AsicReg.RD_Motor0Control = _MotorOn | _MotorHQuarterStep | _MotorPowerEnable; 772 ps->AsicReg.RD_ScanControl1 = _SCANSTOPONBUFFULL | _MFRC_BY_XSTEP; 773 ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; 774} 775 776/* END PLUSTEK-PP_P12.C .....................................................*/ 777