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 
60 static 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  */
p12ButtonSetup(pScanData ps,Byte nrOfButtons)70 static 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  */
p12InitiateComponentModel(pScanData ps)83 static 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  */
p12SetupScannerVariables(pScanData ps)183 static 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  */
p12SetupScanningCondition(pScanData ps)205 static 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  */
p12ProgramCCD(pScanData ps)423 static 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  */
p12Init98003(pScanData ps,Bool shading)449 static 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  */
p12InitializeAsicRegister(pScanData ps)507 static void p12InitializeAsicRegister( pScanData ps )
508 {
509     memset( &ps->AsicReg, 0, sizeof(RegData));
510 }
511 
512 /*.............................................................................
513  * as the function name says
514  */
p12PutToIdleMode(pScanData ps)515 static 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  */
p12Calibration(pScanData ps)537 static 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  */
P12InitAsic(pScanData ps)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  */
P12SetGeneralRegister(pScanData ps)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