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