www.pudn.com > spca5xx-.rar > sp5xxfw2.h
#ifndef SP5XXFW2_H
#define SP5XXFW2_H
/****************************************************************************
# Sunplus spca504(abc) spca533 spca536 library #
# Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
# #
****************************************************************************/
#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
#define SPCA504_PCCAM600_OFFSET_MODE 5
#define SPCA504_PCCAM600_OFFSET_DATA 14
/* Frame packet header offsets for the spca533 */
#define SPCA533_OFFSET_DATA 16
#define SPCA533_OFFSET_FRAMSEQ 15
/* Frame packet header offsets for the spca536 */
#define SPCA536_OFFSET_DATA 4
#define SPCA536_OFFSET_FRAMSEQ 1
#include "sp5xxfw2.dat"
static int sp5xxfw2_init(struct usb_spca50x *spca50x);
static void sp5xxfw2_start(struct usb_spca50x *spca50x);
static void sp5xxfw2_stop(struct usb_spca50x *spca50x);
static __u16 sp5xxfw2_setbrightness(struct usb_spca50x *spca50x);
static __u16 sp5xxfw2_getbrightness(struct usb_spca50x *spca50x);
static __u16 sp5xxfw2_setcontrast(struct usb_spca50x *spca50x);
static __u16 sp5xxfw2_getcontrast(struct usb_spca50x *spca50x);
static __u16 sp5xxfw2_setcolors(struct usb_spca50x *spca50x);
static __u16 sp5xxfw2_getcolors(struct usb_spca50x *spca50x);
//static __u16 sp5xxfw2_setexposure(struct usb_spca50x *spca50x);
//static __u16 sp5xxfw2_getexposure(struct usb_spca50x *spca50x);
//static void spca5xxx_setAutobright (struct usb_spca50x *spca50x);
static int sp5xxfw2_config(struct usb_spca50x *spca50x);
//static void sp5xxfw2_shutdown(struct usb_spca50x *spca50x);
/************************** Private *************************/
static void
spca504B_SetSizeType(struct usb_spca50x *spca50x );
static void
spca504_acknowledged_command(struct usb_spca50x *spca50x,
__u16 reg,
__u16 idx,
__u16 val);
static void
spca504A_acknowledged_command(struct usb_spca50x *spca50x,
__u16 reg,
__u16 idx,
__u16 val,
__u8 stat,
__u8 count);
static void
spca504_wait_status(struct usb_spca50x *spca50x);
static void
spca50x_GetFirmware(struct usb_spca50x *spca50x);
static int
spca504B_PollingDataReady(struct usb_device *dev);
static void
spca504B_WaitCmdStatus(struct usb_spca50x *spca50x);
static void
spca504B_setQtable ( struct usb_spca50x *spca50x );
static void
sp5xx_initContBrigHueRegisters (struct usb_spca50x *spca50x);
/************************************************************/
static int sp5xxfw2_init(struct usb_spca50x *spca50x)
{ int rc ;
__u8 Data = 0;
__u8 i;
__u8 info[6];
int err_code;
switch (spca50x->bridge){
case BRIDGE_SPCA504B:{
spca5xxRegWrite(spca50x->dev,0x1d ,0 ,0 ,NULL,0 );
spca5xxRegWrite(spca50x->dev,0,1 ,0x2306 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0,0 ,0x0d04 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0,0 ,0x2000 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0,0x13 ,0x2301 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0,0 ,0x2306 ,NULL ,0 );
} // becare no break here init follow
case BRIDGE_SPCA533:
rc = spca504B_PollingDataReady ( spca50x->dev );
spca50x_GetFirmware( spca50x );
break;
case BRIDGE_SPCA536:
spca50x_GetFirmware( spca50x );
spca5xxRegRead(spca50x->dev,0x00 ,0 ,0x5002 , &Data ,1);
Data = 0;
spca5xxRegWrite(spca50x->dev,0x24 ,0 ,0 ,&Data ,1 );
spca5xxRegRead(spca50x->dev,0x24 ,0 ,0 , &Data ,1);
rc = spca504B_PollingDataReady( spca50x->dev );
spca5xxRegWrite(spca50x->dev,0x34 ,0 ,0 ,NULL ,0 );
spca504B_WaitCmdStatus(spca50x);
break;
case BRIDGE_SPCA504C: //pccam600
PDEBUG (2, "Opening SPCA504 (PC-CAM 600)");
spca50x_reg_write (spca50x->dev, 0xe0, 0x0000, 0x0000);
spca50x_reg_write (spca50x->dev, 0xe0, 0x0000, 0x0001); // reset
spca504_wait_status (spca50x);
if (spca50x->desc == LogitechClickSmart420)
{ /* clicksmart 420 */
spca50x_write_vector (spca50x, spca504A_clicksmart420_open_data);
}
else
{
spca50x_write_vector (spca50x, spca504_pccam600_open_data);
}
err_code = spca50x_setup_qtable (spca50x,
0x00, 0x2800,
0x2840, qtable_creative_pccam);
if (err_code < 0)
{
PDEBUG (2, "spca50x_setup_qtable failed");
return err_code;
}
break;
case BRIDGE_SPCA504:
PDEBUG (2, "Opening SPCA504");
if (spca50x->desc == AiptekMiniPenCam13)
{
/***************************************************************/
for (i=0; i<6; i++)
{
info[i]=spca50x_reg_read_with_value(spca50x->dev,
0x20, i, 0x0000, 1);
}
PDEBUG(0, "Read info: %d %d %d %d %d %d . Should be 1,0,2,2,0,0\n",
info[0], info[1], info[2], info[3], info[4], info[5]);
/* spca504a aiptek */
// Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz
spca504A_acknowledged_command(spca50x, 0x24, 8, 3,0x9e,1);
// Twice sequencial need status 0xff->0x9e->0x9d
spca504A_acknowledged_command(spca50x, 0x24, 8, 3,0x9e,0);
spca504A_acknowledged_command(spca50x, 0x24, 0, 0,0x9d,1);
/**************************************************************/
/* spca504a aiptek */
spca504A_acknowledged_command (spca50x, 0x08, 6, 0, 0x86, 1);
// spca50x_reg_write (spca50x->dev, 0, 0x2000, 0);
// spca50x_reg_write (spca50x->dev, 0, 0x2883, 1);
// spca504A_acknowledged_command (spca50x, 0x08, 6, 0, 0x86, 1);
//spca504A_acknowledged_command (spca50x, 0x24, 0, 0, 0x9D, 1);
spca50x_reg_write(spca50x->dev, 0x0, 0x270c, 0x5); // L92 sno1t.txt
spca50x_reg_write(spca50x->dev, 0x0, 0x2310, 0x5);
spca504A_acknowledged_command (spca50x, 1, 0x0f, 0, 0xFF, 0);
}
/* setup qtable */
spca50x_reg_write (spca50x->dev, 0, 0x2000, 0);
spca50x_reg_write (spca50x->dev, 0, 0x2883, 1);
err_code = spca50x_setup_qtable (spca50x,
0x00, 0x2800,
0x2840, qtable_spca504_default);
if (err_code < 0)
{
PDEBUG (2, "spca50x_setup_qtable failed");
return err_code;
}
break;
}
return 0;
}
static void sp5xxfw2_start(struct usb_spca50x *spca50x)
{
int rc;
int enable;
__u8 i;
__u8 info[6];
if(spca50x->bridge == BRIDGE_SPCA504B)
spca504B_setQtable ( spca50x );
spca504B_SetSizeType(spca50x);
switch (spca50x->bridge){
case BRIDGE_SPCA504B:
case BRIDGE_SPCA533:
case BRIDGE_SPCA536:
if(spca50x->desc == MegapixV4 ||
spca50x->desc == LogitechClickSmart820){
spca5xxRegWrite(spca50x->dev,0xF0 ,0 ,0 ,NULL ,0 );
spca504B_WaitCmdStatus( spca50x );
spca5xxRegRead(spca50x->dev,0xF0 ,0 ,4 ,NULL ,0 );
spca504B_WaitCmdStatus( spca50x );
} else {
spca5xxRegWrite(spca50x->dev,0x31,0 ,4 ,NULL ,0 );
spca504B_WaitCmdStatus( spca50x );
rc = spca504B_PollingDataReady(spca50x->dev );
}
break;
case BRIDGE_SPCA504:
if (spca50x->desc == AiptekMiniPenCam13){
for (i=0; i<6; i++)
{
info[i]=spca50x_reg_read_with_value(spca50x->dev,
0x20, i, 0x0000, 1);
}
PDEBUG(0, "Read info: %d %d %d %d %d %d . Should be 1,0,2,2,0,0\n",
info[0], info[1], info[2], info[3], info[4], info[5]);
/* spca504a aiptek */
// Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz
spca504A_acknowledged_command(spca50x, 0x24, 8, 3,0x9e,1);
// Twice sequencial need status 0xff->0x9e->0x9d
spca504A_acknowledged_command(spca50x, 0x24, 8, 3,0x9e,0);
spca504A_acknowledged_command(spca50x, 0x24, 0, 0,0x9d,1);
} else {
spca504_acknowledged_command(spca50x, 0x24, 8, 3);
for (i=0; i<6; i++)
{
info[i]=spca50x_reg_read_with_value(spca50x->dev,
0x20, i, 0x0000, 1);
}
PDEBUG(0, "Read info: %d %d %d %d %d %d . Should be 1,0,2,2,0,0\n",
info[0], info[1], info[2], info[3], info[4], info[5]);
spca504_acknowledged_command(spca50x, 0x24, 8, 3);
spca504_acknowledged_command(spca50x, 0x24, 0, 0);
}
spca504B_SetSizeType(spca50x);
spca50x_reg_write(spca50x->dev, 0x0, 0x270c, 0x5); // L92 sno1t.txt
spca50x_reg_write(spca50x->dev, 0x0, 0x2310, 0x5);
break;
case BRIDGE_SPCA504C:
if (spca50x->desc == LogitechClickSmart420) {
spca50x_write_vector(spca50x, spca504A_clicksmart420_init_data);
} else {
spca50x_write_vector(spca50x, spca504_pccam600_init_data);
}
enable = (autoexpo ? 0x4 : 0x1);
spca50x_reg_write(spca50x->dev, 0x0c, 0x0000, enable); // auto exposure
spca50x_reg_write(spca50x->dev, 0xb0, 0x0000, enable); // auto whiteness
/* set default exposure compensation and whiteness balance */
spca50x_reg_write(spca50x->dev, 0x30, 0x0001, 800); // ~ 20 fps
spca50x_reg_write(spca50x->dev, 0x30, 0x0002, 1600);
spca504B_SetSizeType(spca50x);
break;
}
sp5xx_initContBrigHueRegisters (spca50x);
}
static void sp5xxfw2_stop(struct usb_spca50x *spca50x)
{
int rc ;
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA536:
case BRIDGE_SPCA504B:
spca5xxRegWrite(spca50x->dev,0x31,0 ,0 ,NULL ,0 );
spca504B_WaitCmdStatus(spca50x);
rc = spca504B_PollingDataReady(spca50x->dev);
break;
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
spca50x_reg_write (spca50x->dev, 0x00, 0x2000, 0x0000);
if (spca50x->desc == AiptekMiniPenCam13)
{
/* spca504a aiptek */
// spca504A_acknowledged_command (spca50x, 0x08, 6, 0, 0x86, 1);
spca504A_acknowledged_command (spca50x, 0x24, 0x0000, 0x0000, 0x9d, 1);
spca504A_acknowledged_command (spca50x, 0x01, 0x000f, 0x0000, 0xFF,
1);
}
else
{
spca504_acknowledged_command (spca50x, 0x24, 0x0000, 0x0000);
spca50x_reg_write (spca50x->dev, 0x01, 0x000f, 0x0);
}
break;
}
}
static __u16 sp5xxfw2_setbrightness(struct usb_spca50x *spca50x)
{
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
spca50x_reg_write (spca50x->dev, 0x0, 0x21a7, (spca50x->brightness >> 8));
break;
case BRIDGE_SPCA536:
spca50x_reg_write (spca50x->dev, 0x0, 0x20f0, (spca50x->brightness >>8));
break;
}
return 0;
}
static __u16 sp5xxfw2_getbrightness(struct usb_spca50x *spca50x)
{
__u16 brightness = 0;
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
brightness = spca50x_reg_read (spca50x->dev, 0x0, 0x21a7, 2);
spca50x->brightness = (((brightness & 0xFF) - 128) % 255) << 8;
break;
case BRIDGE_SPCA536:
brightness = spca50x_reg_read (spca50x->dev, 0x0, 0x20f0, 2);
spca50x->brightness = (((brightness & 0xFF) - 128) % 255) << 8;
break;
}
return (((brightness & 0xFF) - 128) % 255) << 8;
}
static __u16 sp5xxfw2_setcontrast(struct usb_spca50x *spca50x)
{
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
spca50x_reg_write (spca50x->dev, 0x0, 0x21a8,
spca50x->contrast >> 8);
break;
case BRIDGE_SPCA536:
spca50x_reg_write (spca50x->dev, 0x0, 0x20f1,
spca50x->contrast >> 8);
break;
}
return 0;
}
static __u16 sp5xxfw2_getcontrast(struct usb_spca50x *spca50x)
{
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
spca50x->contrast =
spca50x_reg_read (spca50x->dev, 0x0, 0x21a8, 2) << 8;
break;
case BRIDGE_SPCA536:
spca50x->contrast =
spca50x_reg_read (spca50x->dev, 0x0, 0x20f1, 2) << 8;
break;
}
return spca50x->contrast;
}
static __u16 sp5xxfw2_setcolors(struct usb_spca50x *spca50x)
{
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
spca50x_reg_write (spca50x->dev, 0x0, 0x21ae,
spca50x->colour >> 8);
break;
case BRIDGE_SPCA536:
spca50x_reg_write(spca50x->dev, 0x0, 0x20f6,
spca50x->colour >> 8);
break;
}
return 0;
}
static __u16 sp5xxfw2_getcolors(struct usb_spca50x *spca50x)
{
switch (spca50x->bridge) {
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
spca50x->colour =
spca50x_reg_read (spca50x->dev, 0x0, 0x21ae, 2) << 7;
break;
case BRIDGE_SPCA536:
spca50x->colour =
spca50x_reg_read (spca50x->dev, 0x0, 0x20f6, 2) << 7;
break;
}
return spca50x->colour;
}
static int sp5xxfw2_config(struct usb_spca50x *spca50x)
{
switch (spca50x->bridge){
case BRIDGE_SPCA504B:
case BRIDGE_SPCA504:
case BRIDGE_SPCA536:
memset (spca50x->mode_cam, 0x00, TOTMODE * sizeof(struct mwebcam));
spca50x->mode_cam[VGA].width = 640;
spca50x->mode_cam[VGA].height = 480;
spca50x->mode_cam[VGA].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[VGA].pipe = 1023;
spca50x->mode_cam[VGA].method = 0;
spca50x->mode_cam[VGA].mode = 1;
spca50x->mode_cam[PAL].width = 384;
spca50x->mode_cam[PAL].height = 288;
spca50x->mode_cam[PAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[PAL].pipe = 1023;
spca50x->mode_cam[PAL].method = 1;
spca50x->mode_cam[PAL].mode = 1;
spca50x->mode_cam[SIF].width = 352;
spca50x->mode_cam[SIF].height = 288;
spca50x->mode_cam[SIF].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[SIF].pipe = 1023;
spca50x->mode_cam[SIF].method = 1;
spca50x->mode_cam[SIF].mode = 1;
spca50x->mode_cam[CIF].width = 320;
spca50x->mode_cam[CIF].height = 240;
spca50x->mode_cam[CIF].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[CIF].pipe = 896;
spca50x->mode_cam[CIF].method = 0;
spca50x->mode_cam[CIF].mode = 2;
spca50x->mode_cam[QPAL].width = 192;
spca50x->mode_cam[QPAL].height = 144;
spca50x->mode_cam[QPAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[QPAL].pipe = 896;
spca50x->mode_cam[QPAL].method = 1;
spca50x->mode_cam[QPAL].mode = 2;
spca50x->mode_cam[QSIF].width = 176;
spca50x->mode_cam[QSIF].height = 144;
spca50x->mode_cam[QSIF].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[QSIF].pipe = 896;
spca50x->mode_cam[QSIF].method = 1;
spca50x->mode_cam[QSIF].mode = 2;
break;
case BRIDGE_SPCA533:
memset (spca50x->mode_cam, 0x00, TOTMODE * sizeof(struct mwebcam));
spca50x->mode_cam[CUSTOM].width = 464;
spca50x->mode_cam[CUSTOM].height = 480;
spca50x->mode_cam[CUSTOM].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[CUSTOM].pipe = 1023;
spca50x->mode_cam[CUSTOM].method = 0;
spca50x->mode_cam[CUSTOM].mode = 1;
spca50x->mode_cam[PAL].width = 384;
spca50x->mode_cam[PAL].height = 288;
spca50x->mode_cam[PAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[PAL].pipe = 1023;
spca50x->mode_cam[PAL].method = 1;
spca50x->mode_cam[PAL].mode = 1;
spca50x->mode_cam[SIF].width = 352;
spca50x->mode_cam[SIF].height = 288;
spca50x->mode_cam[SIF].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[SIF].pipe = 1023;
spca50x->mode_cam[SIF].method = 1;
spca50x->mode_cam[SIF].mode = 1;
spca50x->mode_cam[CIF].width = 320;
spca50x->mode_cam[CIF].height = 240;
spca50x->mode_cam[CIF].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[CIF].pipe = 1023;
spca50x->mode_cam[CIF].method = 0;
spca50x->mode_cam[CIF].mode = 2;
spca50x->mode_cam[QPAL].width = 192;
spca50x->mode_cam[QPAL].height = 144;
spca50x->mode_cam[QPAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[QPAL].pipe = 1023;
spca50x->mode_cam[QPAL].method = 1;
spca50x->mode_cam[QPAL].mode = 2;
spca50x->mode_cam[QSIF].width = 176;
spca50x->mode_cam[QSIF].height = 144;
spca50x->mode_cam[QSIF].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[QSIF].pipe = 1023;
spca50x->mode_cam[QSIF].method = 1;
spca50x->mode_cam[QSIF].mode = 2;
break;
case BRIDGE_SPCA504C:
memset (spca50x->mode_cam, 0x00, TOTMODE * sizeof(struct mwebcam));
spca50x->mode_cam[VGA].width = 640;
spca50x->mode_cam[VGA].height = 480;
spca50x->mode_cam[VGA].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[VGA].pipe = 1023;
spca50x->mode_cam[VGA].method = 0;
spca50x->mode_cam[VGA].mode = 1;
spca50x->mode_cam[PAL].width = 384;
spca50x->mode_cam[PAL].height = 288;
spca50x->mode_cam[PAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[PAL].pipe = 1023;
spca50x->mode_cam[PAL].method = 1;
spca50x->mode_cam[PAL].mode = 1;
spca50x->mode_cam[SIF].width = 352;
spca50x->mode_cam[SIF].height = 288;
spca50x->mode_cam[SIF].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[SIF].pipe = 1023;
spca50x->mode_cam[SIF].method = 0;
spca50x->mode_cam[SIF].mode = 2;
spca50x->mode_cam[CIF].width = 320;
spca50x->mode_cam[CIF].height = 240;
spca50x->mode_cam[CIF].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[CIF].pipe = 896;
spca50x->mode_cam[CIF].method = 0;
spca50x->mode_cam[CIF].mode = 3;
spca50x->mode_cam[QPAL].width = 192;
spca50x->mode_cam[QPAL].height = 144;
spca50x->mode_cam[QPAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[QPAL].pipe = 896;
spca50x->mode_cam[QPAL].method = 1;
spca50x->mode_cam[QPAL].mode = 3;
spca50x->mode_cam[QSIF].width = 176;
spca50x->mode_cam[QSIF].height = 144;
spca50x->mode_cam[QSIF].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
spca50x->mode_cam[QSIF].pipe = 768;
spca50x->mode_cam[QSIF].method = 0;
spca50x->mode_cam[QSIF].mode = 4;
break;
}
return 0;
}
/****************************************************************************************/
static void
spca504B_SetSizeType(struct usb_spca50x *spca50x )
{
__u8 Size ;
__u8 Type ;
int rc;
Size = spca50x->mode;
Type = 0;
switch (spca50x->bridge) {
case BRIDGE_SPCA533: {
spca5xxRegWrite(spca50x->dev,0x31,0 ,0 ,NULL ,0 );
spca504B_WaitCmdStatus(spca50x);
rc = spca504B_PollingDataReady(spca50x->dev);
spca50x_GetFirmware( spca50x );
Type = 2;
spca5xxRegWrite(spca50x->dev,0x24,0 ,8 ,&Type ,1 );
spca5xxRegRead(spca50x->dev,0x24,0 ,8 ,&Type ,1 );
spca5xxRegWrite(spca50x->dev,0x25,0 ,4 ,&Size ,1 );
spca5xxRegRead(spca50x->dev,0x25,0 ,4 ,&Size ,1 );
rc = spca504B_PollingDataReady(spca50x->dev );
/* Init the cam width height with some values get on init ?*/
spca5xxRegWrite(spca50x->dev,0x31,0 ,4 ,NULL ,0 );
spca504B_WaitCmdStatus( spca50x );
rc = spca504B_PollingDataReady(spca50x->dev );
}
break;
case BRIDGE_SPCA504B:
case BRIDGE_SPCA536:
{
Type = 6;
spca5xxRegWrite(spca50x->dev,0x25,0 ,4 ,&Size ,1 );
spca5xxRegRead(spca50x->dev,0x25,0 ,4 ,&Size ,1 );
spca5xxRegWrite(spca50x->dev,0x27,0 ,0 ,&Type ,1 );
spca5xxRegRead(spca50x->dev,0x27,0 ,0 ,&Type ,1 );
rc = spca504B_PollingDataReady ( spca50x->dev );
}
break;
case BRIDGE_SPCA504:
Size += 3;
if (spca50x->desc == AiptekMiniPenCam13)
{
/* spca504a aiptek */
spca504A_acknowledged_command (spca50x, 0x8, Size, 0,
(0x80 | (Size & 0x0F)), 1);
spca504A_acknowledged_command (spca50x, 1, 3, 0, 0x9F, 0);
}
else
{
spca504_acknowledged_command (spca50x, 0x8, Size, 0);
}
break;
case BRIDGE_SPCA504C:
spca50x_reg_write (spca50x->dev, 0xa0, (0x0500 | (Size & 0x0F)), 0x0); // capture mode
spca50x_reg_write (spca50x->dev, 0x20, 0x1, (0x0500 | (Size & 0x0F)));
break;
}
return ;
}
static void
spca504_acknowledged_command(struct usb_spca50x *spca50x,
__u16 reg,
__u16 idx,
__u16 val)
{
__u8 notdone = 0;
spca50x_reg_write(spca50x->dev,reg,idx,val);
notdone=spca50x_reg_read(spca50x->dev, 0x01, 0x0001, 1);
spca50x_reg_write(spca50x->dev,reg,idx,val);
PDEBUG(5,"before wait 0x%x",notdone);
wait_ms(200);
notdone=spca50x_reg_read(spca50x->dev, 0x01, 0x0001, 1);
PDEBUG(5,"after wait 0x%x",notdone);
return;
}
static void
spca504A_acknowledged_command(struct usb_spca50x *spca50x,
__u16 reg,
__u16 idx,
__u16 val,
__u8 stat,
__u8 count)
{
__u8 status ;
__u8 endcode;
spca50x_reg_write(spca50x->dev,reg,idx,val);
status=spca50x_reg_read(spca50x->dev, 0x01, 0x0001, 1);
endcode = stat ;
PDEBUG(5,"Status 0x%x Need 0x%x",status, stat);
if (count) {
while (1){
wait_ms(10);
/* gsmart mini2 write a each wait setting 1 ms is enought*/
//spca50x_reg_write(spca50x->dev,reg,idx,val);
status=spca50x_reg_read(spca50x->dev, 0x01, 0x0001, 1);
if (status == endcode) {
PDEBUG(5,"status 0x%x after wait 0x%x",status,count);
break;
}
count++;
if(count > 200) break;
}
}
return;
}
static void
spca504_wait_status(struct usb_spca50x *spca50x)
{
int ret = 256;
do {
/* With this we get the status, when return 0 it's all ok */
ret = spca50x_reg_read(spca50x->dev, 0x06, 0x00, 1);
} while(ret--);
}
static void
spca50x_GetFirmware(struct usb_spca50x *spca50x)
{ __u8 FW[5] = {0,0,0,0,0};
__u8 ProductInfo[64];
spca5xxRegRead(spca50x->dev,0x20 ,0 ,0 ,FW ,5);
PDEBUG(0, "FirmWare : %d %d %d %d %d ", FW[0],FW[1],FW[2],FW[3],FW[4] );
spca5xxRegRead(spca50x->dev,0x23 ,0 ,0 ,ProductInfo ,64);
spca5xxRegRead(spca50x->dev,0x23 ,0 ,1 ,ProductInfo ,64);
return ;
}
static int
spca504B_PollingDataReady(struct usb_device *dev)
{
__u8 DataReady = 0 ;
int count = 0;
while(1) {
spca5xxRegRead(dev,0x21,0, 0, &DataReady,1);
if ( (DataReady & 0x01) == 0) break;
wait_ms(10);
count++;
if (count > 10) break;
}
return DataReady;
}
static void
spca504B_WaitCmdStatus(struct usb_spca50x *spca50x)
{
__u8 DataReady = 0;
int ReqDone;
int count = 0;
while (1) {
spca5xxRegRead(spca50x->dev,0x21,0, 1, &DataReady,1);
if ( DataReady ) {
DataReady = 0;
spca5xxRegWrite(spca50x->dev,0x21,0, 1, &DataReady, 1);
spca5xxRegRead(spca50x->dev,0x21,0, 1, &DataReady, 1);
ReqDone = spca504B_PollingDataReady(spca50x->dev);
break ;
}
wait_ms (10);
count++;
if (count > 50) break;
}
return ;
}
static void
spca504B_setQtable ( struct usb_spca50x *spca50x )
{
__u8 Data = 3 ;
int rc ;
spca5xxRegWrite(spca50x->dev,0x26,0 ,0 ,&Data ,1 );
spca5xxRegRead(spca50x->dev,0x26 ,0 ,0 , &Data ,1);
rc = spca504B_PollingDataReady ( spca50x->dev );
return ;
}
static void sp5xx_initContBrigHueRegisters (struct usb_spca50x *spca50x)
{
int rc;
int pollreg =1;
switch (spca50x->bridge){
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
pollreg = 0;
case BRIDGE_SPCA533:
case BRIDGE_SPCA504B:
spca5xxRegWrite(spca50x->dev,0 ,0 ,0x21a7 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0x20 ,0x21a8 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0 ,0x21ad ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,1 ,0x21ac ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0x20 ,0x21ae ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0 ,0x21a3 ,NULL ,0 );
break;
case BRIDGE_SPCA536:
spca5xxRegWrite(spca50x->dev,0 ,0 ,0x20f0 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0x21 ,0x20f1 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0x40 ,0x20f5 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,1 ,0x20f4 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0x40 ,0x20f6 ,NULL ,0 );
spca5xxRegWrite(spca50x->dev,0 ,0 ,0x2089 ,NULL ,0 );
break;
}
if (pollreg)
rc = spca504B_PollingDataReady( spca50x->dev );
return ;
}
#endif //SP5XXFW2