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