1/*
2 * Copyright 2004-2008, Fran��ois Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include <ParameterWeb.h>
7
8#include "CamSensor.h"
9#include "CamDebug.h"
10#include "addons/sonix/SonixCamDevice.h"
11
12//#define ENABLE_GAIN 1
13
14
15class TAS5110C1BSensor : public CamSensor {
16public:
17	TAS5110C1BSensor(CamDevice *_camera);
18	~TAS5110C1BSensor();
19	virtual status_t	Probe();
20	virtual status_t	Setup();
21	const char *Name();
22	virtual bool		Use400kHz() const { return false; };
23	virtual bool		UseRealIIC() const { return true /*false*/; };
24	virtual uint8		IICReadAddress() const { return 0x00; };
25	virtual uint8		IICWriteAddress() const { return 0x61; /*0x11;*/ /*0xff;*/ };
26
27	virtual int			MaxWidth() const { return 352; };
28	virtual int			MaxHeight() const { return 288; };
29
30	virtual status_t	AcceptVideoFrame(uint32 &width, uint32 &height);
31	virtual status_t	SetVideoFrame(BRect rect);
32	virtual void		AddParameters(BParameterGroup *group, int32 &firstID);
33	virtual status_t	GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size);
34	virtual status_t	SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size);
35
36private:
37	bool	fIsSonix;
38	float	fGain;
39};
40
41
42TAS5110C1BSensor::TAS5110C1BSensor(CamDevice *_camera)
43: CamSensor(_camera)
44{
45	fIsSonix = (dynamic_cast<SonixCamDevice *>(_camera) != NULL);
46	if (fIsSonix) {
47		fInitStatus = B_OK;
48	} else {
49		PRINT((CH ": unknown camera device!" CT));
50		fInitStatus = ENODEV;
51	}
52	fGain = (float)0x40; // default
53}
54
55
56TAS5110C1BSensor::~TAS5110C1BSensor()
57{
58}
59
60
61status_t
62TAS5110C1BSensor::Probe()
63{
64	PRINT((CH "()" CT));
65
66	return B_OK;
67}
68
69
70status_t
71TAS5110C1BSensor::Setup()
72{
73	PRINT((CH "()" CT));
74	if (InitCheck())
75		return InitCheck();
76	Device()->PowerOnSensor(false);
77	Device()->PowerOnSensor(true);
78	if (fIsSonix) {
79#if 1
80		Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x01);	/* power down the sensor */
81		Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x44);	/* power up the sensor, enable tx, sysclk@24MHz */
82		Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x04);	/* power up the sensor, enable tx, sysclk@24MHz */
83		Device()->WriteReg8(SN9C102_R_B_GAIN, 0x00);	/* red, blue gain = 1+0/8 = 1 */
84		Device()->WriteReg8(SN9C102_G_GAIN, 0x00);	/* green gain = 1+0/8 = 1 */
85		Device()->WriteReg8(SN9C102_OFFSET, 0x0a);	/* 10 pix offset */
86		Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60);	/* enable sensor clk, and invert it */
87		Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60);	/* enable sensor clk, and invert it */
88		Device()->WriteReg8(SN9C102_SYNC_N_SCALE, 0x06);	/* no compression, normal curve,
89												 * no scaling, vsync active low,
90												 * v/hsync change at rising edge,
91												 * falling edge of sensor pck */
92		Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);	/* pixclk = 2 * masterclk, sensor is slave mode */
93
94		// some IIC stuff for the sensor
95		// though it seems more data is sent than told the controller
96		// this is what the XP driver sends to the ICECAM...
97		uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
98		Device()->WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
99
100		Device()->WriteReg8(SN9C102_PIX_CLK, 0x4b);
101
102		uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16 };
103		Device()->WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
104
105#endif
106	}
107
108
109	if (fIsSonix) {
110		//sonix_i2c_write_multi(dev, dev->sensor->i2c_wid, 2, 0xc0, 0x80, 0, 0, 0); /* AEC = 0x203 ??? */
111		//Device()->WriteIIC8(0xc0, 0x80); /* AEC = 0x203 ??? */
112		//Device()->WriteIIC8(0x1c, 0x80); /* AEC = 0x203 ??? */
113
114		// set crop
115		Device()->WriteReg8(SN9C102_H_SIZE, 69);
116		Device()->WriteReg8(SN9C102_V_SIZE, 9);
117		SetVideoFrame(BRect(0, 0, 352-1, 288-1));
118
119	}
120
121	//Device()->SetScale(1);
122
123	return B_OK;
124}
125
126
127const char *
128TAS5110C1BSensor::Name()
129{
130	return "TASC tas5110c1b";
131}
132
133
134status_t
135TAS5110C1BSensor::AcceptVideoFrame(uint32 &width, uint32 &height)
136{
137	// default sanity checks
138	status_t err = CamSensor::AcceptVideoFrame(width, height);
139	if (err < B_OK)
140		return err;
141	// must be modulo 16
142	width /= 16;
143	width *= 16;
144	height /= 16;
145	height *= 16;
146	return B_OK;
147}
148
149
150status_t
151TAS5110C1BSensor::SetVideoFrame(BRect rect)
152{
153	if (fIsSonix) {
154		// set crop
155		Device()->WriteReg8(SN9C102_H_START, /*rect.left + */69);
156		Device()->WriteReg8(SN9C102_V_START, /*rect.top + */9);
157		Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);
158		Device()->WriteReg8(SN9C102_HO_SIZE, 0x14);
159		Device()->WriteReg8(SN9C102_VO_SIZE, 0x0a);
160		fVideoFrame = rect;
161		/* HACK: TEST IMAGE */
162		//Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x70);	/* enable sensor clk, and invert it, test img */
163
164	}
165
166	return B_OK;
167}
168
169
170void
171TAS5110C1BSensor::AddParameters(BParameterGroup *group, int32 &index)
172{
173	CamSensor::AddParameters(group, index);
174
175#ifdef ENABLE_GAIN
176	BContinuousParameter *p;
177	// NON-FUNCTIONAL
178	BParameterGroup *g = group->MakeGroup("global gain");
179	p = g->MakeContinuousParameter(index++,
180		B_MEDIA_RAW_VIDEO, "global gain",
181		B_GAIN, "", (float)0x00, (float)0xf6, (float)1);
182#endif
183}
184
185
186status_t
187TAS5110C1BSensor::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size)
188{
189#ifdef ENABLE_GAIN
190	if (id == fFirstParameterID) {
191		*size = sizeof(float);
192		*((float *)value) = fGain;
193		*last_change = fLastParameterChanges;
194	}
195#endif
196	return B_BAD_VALUE;
197}
198
199
200status_t
201TAS5110C1BSensor::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size)
202{
203#ifdef ENABLE_GAIN
204	if (id == fFirstParameterID) {
205		if (!value || (size != sizeof(float)))
206			return B_BAD_VALUE;
207		if (*(float *)value == fGain)
208			return B_OK;
209		fGain = *(float *)value;
210		fLastParameterChanges = when;
211		PRINT((CH ": gain: %f" CT, fGain));
212
213		if (fIsSonix) {
214			// some drivers do:
215			//Device()->WriteIIC8(0x20, (uint8)0xf6 - (uint8)fGain);
216			// but it doesn't seem to work
217
218			// works, not sure why yet, XXX check datasheet for AEG/AEC
219			uint8 buf[2] = { 0x20, 0x70 };
220			buf[1] = (uint8)0xff - (uint8)fGain;
221			Device()->WriteIIC(0x02, buf, 2);
222		}
223
224		return B_OK;
225	}
226#endif
227	return B_BAD_VALUE;
228}
229
230
231
232B_WEBCAM_DECLARE_SENSOR(TAS5110C1BSensor, tas5110c1b)
233
234