xref: /haiku/src/add-ons/media/media-add-ons/usb_webcam/sensors/tas5110c1b.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
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 
15 class TAS5110C1BSensor : public CamSensor {
16 public:
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 
36 private:
37 	bool	fIsSonix;
38 	float	fGain;
39 };
40 
41 
42 TAS5110C1BSensor::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 
56 TAS5110C1BSensor::~TAS5110C1BSensor()
57 {
58 }
59 
60 
61 status_t
62 TAS5110C1BSensor::Probe()
63 {
64 	PRINT((CH "()" CT));
65 
66 	return B_OK;
67 }
68 
69 
70 status_t
71 TAS5110C1BSensor::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 
127 const char *
128 TAS5110C1BSensor::Name()
129 {
130 	return "TASC tas5110c1b";
131 }
132 
133 
134 status_t
135 TAS5110C1BSensor::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 
150 status_t
151 TAS5110C1BSensor::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 
170 void
171 TAS5110C1BSensor::AddParameters(BParameterGroup *group, int32 &index)
172 {
173 	BContinuousParameter *p;
174 	CamSensor::AddParameters(group, index);
175 
176 #ifdef ENABLE_GAIN
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 
186 status_t
187 TAS5110C1BSensor::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 
200 status_t
201 TAS5110C1BSensor::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 
232 B_WEBCAM_DECLARE_SENSOR(TAS5110C1BSensor, tas5110c1b)
233 
234