xref: /haiku/src/add-ons/media/media-add-ons/usb_webcam/sensors/tas5110c1b.cpp (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
1601cedceSFrançois Revol /*
2a1830cbdSFrançois Revol  * Copyright 2004-2008, François Revol, <revol@free.fr>.
3a1830cbdSFrançois Revol  * Distributed under the terms of the MIT License.
4601cedceSFrançois Revol  */
5601cedceSFrançois Revol 
6a486abdcSFrançois Revol #include <ParameterWeb.h>
7a486abdcSFrançois Revol 
8601cedceSFrançois Revol #include "CamSensor.h"
9601cedceSFrançois Revol #include "CamDebug.h"
10601cedceSFrançois Revol #include "addons/sonix/SonixCamDevice.h"
11601cedceSFrançois Revol 
12fb086488SFrançois Revol //#define ENABLE_GAIN 1
13fb086488SFrançois Revol 
14a486abdcSFrançois Revol 
15601cedceSFrançois Revol class TAS5110C1BSensor : public CamSensor {
16601cedceSFrançois Revol public:
17601cedceSFrançois Revol 	TAS5110C1BSensor(CamDevice *_camera);
18601cedceSFrançois Revol 	~TAS5110C1BSensor();
19fb086488SFrançois Revol 	virtual status_t	Probe();
20601cedceSFrançois Revol 	virtual status_t	Setup();
21601cedceSFrançois Revol 	const char *Name();
Use400kHz() const22601cedceSFrançois Revol 	virtual bool		Use400kHz() const { return false; };
UseRealIIC() const23fb086488SFrançois Revol 	virtual bool		UseRealIIC() const { return true /*false*/; };
IICReadAddress() const24601cedceSFrançois Revol 	virtual uint8		IICReadAddress() const { return 0x00; };
IICWriteAddress() const25fb086488SFrançois Revol 	virtual uint8		IICWriteAddress() const { return 0x61; /*0x11;*/ /*0xff;*/ };
260866ac7eSFrançois Revol 
MaxWidth() const27601cedceSFrançois Revol 	virtual int			MaxWidth() const { return 352; };
MaxHeight() const28601cedceSFrançois Revol 	virtual int			MaxHeight() const { return 288; };
290866ac7eSFrançois Revol 
300866ac7eSFrançois Revol 	virtual status_t	AcceptVideoFrame(uint32 &width, uint32 &height);
31601cedceSFrançois Revol 	virtual status_t	SetVideoFrame(BRect rect);
32a486abdcSFrançois Revol 	virtual void		AddParameters(BParameterGroup *group, int32 &firstID);
33a486abdcSFrançois Revol 	virtual status_t	GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size);
34a486abdcSFrançois Revol 	virtual status_t	SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size);
35a486abdcSFrançois Revol 
36601cedceSFrançois Revol private:
37601cedceSFrançois Revol 	bool	fIsSonix;
38a486abdcSFrançois Revol 	float	fGain;
39601cedceSFrançois Revol };
40601cedceSFrançois Revol 
410866ac7eSFrançois Revol 
TAS5110C1BSensor(CamDevice * _camera)42601cedceSFrançois Revol TAS5110C1BSensor::TAS5110C1BSensor(CamDevice *_camera)
43601cedceSFrançois Revol : CamSensor(_camera)
44601cedceSFrançois Revol {
45601cedceSFrançois Revol 	fIsSonix = (dynamic_cast<SonixCamDevice *>(_camera) != NULL);
46601cedceSFrançois Revol 	if (fIsSonix) {
47601cedceSFrançois Revol 		fInitStatus = B_OK;
48601cedceSFrançois Revol 	} else {
49601cedceSFrançois Revol 		PRINT((CH ": unknown camera device!" CT));
50601cedceSFrançois Revol 		fInitStatus = ENODEV;
51601cedceSFrançois Revol 	}
52a486abdcSFrançois Revol 	fGain = (float)0x40; // default
53601cedceSFrançois Revol }
54601cedceSFrançois Revol 
550866ac7eSFrançois Revol 
~TAS5110C1BSensor()56601cedceSFrançois Revol TAS5110C1BSensor::~TAS5110C1BSensor()
57601cedceSFrançois Revol {
58601cedceSFrançois Revol }
59601cedceSFrançois Revol 
600866ac7eSFrançois Revol 
61601cedceSFrançois Revol status_t
Probe()62fb086488SFrançois Revol TAS5110C1BSensor::Probe()
63fb086488SFrançois Revol {
64fb086488SFrançois Revol 	PRINT((CH "()" CT));
65fb086488SFrançois Revol 
66fb086488SFrançois Revol 	return B_OK;
67fb086488SFrançois Revol }
68fb086488SFrançois Revol 
69fb086488SFrançois Revol 
70fb086488SFrançois Revol status_t
Setup()71601cedceSFrançois Revol TAS5110C1BSensor::Setup()
72601cedceSFrançois Revol {
73601cedceSFrançois Revol 	PRINT((CH "()" CT));
74601cedceSFrançois Revol 	if (InitCheck())
75601cedceSFrançois Revol 		return InitCheck();
76fb086488SFrançois Revol 	Device()->PowerOnSensor(false);
77fb086488SFrançois Revol 	Device()->PowerOnSensor(true);
78601cedceSFrançois Revol 	if (fIsSonix) {
79fb086488SFrançois Revol #if 1
80601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x01);	/* power down the sensor */
81601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x44);	/* power up the sensor, enable tx, sysclk@24MHz */
82fb086488SFrançois Revol 		Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x04);	/* power up the sensor, enable tx, sysclk@24MHz */
83601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_R_B_GAIN, 0x00);	/* red, blue gain = 1+0/8 = 1 */
84601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_G_GAIN, 0x00);	/* green gain = 1+0/8 = 1 */
85601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_OFFSET, 0x0a);	/* 10 pix offset */
86601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60);	/* enable sensor clk, and invert it */
87fb086488SFrançois Revol 		Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60);	/* enable sensor clk, and invert it */
88601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_SYNC_N_SCALE, 0x06);	/* no compression, normal curve,
89601cedceSFrançois Revol 												 * no scaling, vsync active low,
90601cedceSFrançois Revol 												 * v/hsync change at rising edge,
91601cedceSFrançois Revol 												 * falling edge of sensor pck */
92601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);	/* pixclk = 2 * masterclk, sensor is slave mode */
93fb086488SFrançois Revol 
94fb086488SFrançois Revol 		// some IIC stuff for the sensor
95fb086488SFrançois Revol 		// though it seems more data is sent than told the controller
96fb086488SFrançois Revol 		// this is what the XP driver sends to the ICECAM...
97fb086488SFrançois Revol 		uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
98fb086488SFrançois Revol 		Device()->WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
99fb086488SFrançois Revol 
100fb086488SFrançois Revol 		Device()->WriteReg8(SN9C102_PIX_CLK, 0x4b);
101fb086488SFrançois Revol 
102fb086488SFrançois Revol 		uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16 };
103fb086488SFrançois Revol 		Device()->WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
104fb086488SFrançois Revol 
105fb086488SFrançois Revol #endif
106601cedceSFrançois Revol 	}
107601cedceSFrançois Revol 
108c38af24cSFrançois Revol 
109c38af24cSFrançois Revol 	if (fIsSonix) {
110601cedceSFrançois Revol 		//sonix_i2c_write_multi(dev, dev->sensor->i2c_wid, 2, 0xc0, 0x80, 0, 0, 0); /* AEC = 0x203 ??? */
111fb086488SFrançois Revol 		//Device()->WriteIIC8(0xc0, 0x80); /* AEC = 0x203 ??? */
112fb086488SFrançois Revol 		//Device()->WriteIIC8(0x1c, 0x80); /* AEC = 0x203 ??? */
113601cedceSFrançois Revol 
114601cedceSFrançois Revol 		// set crop
115601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_H_SIZE, 69);
116601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_V_SIZE, 9);
117fb086488SFrançois Revol 		SetVideoFrame(BRect(0, 0, 352-1, 288-1));
118601cedceSFrançois Revol 
119601cedceSFrançois Revol 	}
120601cedceSFrançois Revol 
121601cedceSFrançois Revol 	//Device()->SetScale(1);
122601cedceSFrançois Revol 
123601cedceSFrançois Revol 	return B_OK;
124601cedceSFrançois Revol }
125601cedceSFrançois Revol 
1260866ac7eSFrançois Revol 
127601cedceSFrançois Revol const char *
Name()128601cedceSFrançois Revol TAS5110C1BSensor::Name()
129601cedceSFrançois Revol {
130601cedceSFrançois Revol 	return "TASC tas5110c1b";
131601cedceSFrançois Revol }
132601cedceSFrançois Revol 
1330866ac7eSFrançois Revol 
1340866ac7eSFrançois Revol status_t
AcceptVideoFrame(uint32 & width,uint32 & height)1350866ac7eSFrançois Revol TAS5110C1BSensor::AcceptVideoFrame(uint32 &width, uint32 &height)
1360866ac7eSFrançois Revol {
1370866ac7eSFrançois Revol 	// default sanity checks
1380866ac7eSFrançois Revol 	status_t err = CamSensor::AcceptVideoFrame(width, height);
1390866ac7eSFrançois Revol 	if (err < B_OK)
1400866ac7eSFrançois Revol 		return err;
1410866ac7eSFrançois Revol 	// must be modulo 16
1420866ac7eSFrançois Revol 	width /= 16;
1430866ac7eSFrançois Revol 	width *= 16;
1440866ac7eSFrançois Revol 	height /= 16;
1450866ac7eSFrançois Revol 	height *= 16;
1460866ac7eSFrançois Revol 	return B_OK;
1470866ac7eSFrançois Revol }
1480866ac7eSFrançois Revol 
1490866ac7eSFrançois Revol 
150601cedceSFrançois Revol status_t
SetVideoFrame(BRect rect)151601cedceSFrançois Revol TAS5110C1BSensor::SetVideoFrame(BRect rect)
152601cedceSFrançois Revol {
153601cedceSFrançois Revol 	if (fIsSonix) {
154601cedceSFrançois Revol 		// set crop
155601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_H_START, /*rect.left + */69);
156601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_V_START, /*rect.top + */9);
157601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);
158601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_HO_SIZE, 0x14);
159601cedceSFrançois Revol 		Device()->WriteReg8(SN9C102_VO_SIZE, 0x0a);
160601cedceSFrançois Revol 		fVideoFrame = rect;
161601cedceSFrançois Revol 		/* HACK: TEST IMAGE */
162601cedceSFrançois Revol 		//Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x70);	/* enable sensor clk, and invert it, test img */
163601cedceSFrançois Revol 
164601cedceSFrançois Revol 	}
165601cedceSFrançois Revol 
166601cedceSFrançois Revol 	return B_OK;
167601cedceSFrançois Revol }
168601cedceSFrançois Revol 
1690866ac7eSFrançois Revol 
170a486abdcSFrançois Revol void
AddParameters(BParameterGroup * group,int32 & index)171a486abdcSFrançois Revol TAS5110C1BSensor::AddParameters(BParameterGroup *group, int32 &index)
172a486abdcSFrançois Revol {
173a486abdcSFrançois Revol 	CamSensor::AddParameters(group, index);
174a486abdcSFrançois Revol 
175a486abdcSFrançois Revol #ifdef ENABLE_GAIN
176*628ddb27SFranck LeCodeur 	BContinuousParameter *p;
177c38af24cSFrançois Revol 	// NON-FUNCTIONAL
1780866ac7eSFrançois Revol 	BParameterGroup *g = group->MakeGroup("global gain");
1790866ac7eSFrançois Revol 	p = g->MakeContinuousParameter(index++,
180a486abdcSFrançois Revol 		B_MEDIA_RAW_VIDEO, "global gain",
181a486abdcSFrançois Revol 		B_GAIN, "", (float)0x00, (float)0xf6, (float)1);
182a486abdcSFrançois Revol #endif
183a486abdcSFrançois Revol }
184a486abdcSFrançois Revol 
185a486abdcSFrançois Revol 
186a486abdcSFrançois Revol status_t
GetParameterValue(int32 id,bigtime_t * last_change,void * value,size_t * size)187a486abdcSFrançois Revol TAS5110C1BSensor::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size)
188a486abdcSFrançois Revol {
189a486abdcSFrançois Revol #ifdef ENABLE_GAIN
190a486abdcSFrançois Revol 	if (id == fFirstParameterID) {
191a486abdcSFrançois Revol 		*size = sizeof(float);
192a486abdcSFrançois Revol 		*((float *)value) = fGain;
193a486abdcSFrançois Revol 		*last_change = fLastParameterChanges;
194a486abdcSFrançois Revol 	}
195a486abdcSFrançois Revol #endif
196a486abdcSFrançois Revol 	return B_BAD_VALUE;
197a486abdcSFrançois Revol }
198a486abdcSFrançois Revol 
1990866ac7eSFrançois Revol 
200a486abdcSFrançois Revol status_t
SetParameterValue(int32 id,bigtime_t when,const void * value,size_t size)201a486abdcSFrançois Revol TAS5110C1BSensor::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size)
202a486abdcSFrançois Revol {
203a486abdcSFrançois Revol #ifdef ENABLE_GAIN
204a486abdcSFrançois Revol 	if (id == fFirstParameterID) {
205a486abdcSFrançois Revol 		if (!value || (size != sizeof(float)))
206a486abdcSFrançois Revol 			return B_BAD_VALUE;
207a486abdcSFrançois Revol 		if (*(float *)value == fGain)
208a486abdcSFrançois Revol 			return B_OK;
209a486abdcSFrançois Revol 		fGain = *(float *)value;
210a486abdcSFrançois Revol 		fLastParameterChanges = when;
211c38af24cSFrançois Revol 		PRINT((CH ": gain: %f" CT, fGain));
212c38af24cSFrançois Revol 
213c38af24cSFrançois Revol 		if (fIsSonix) {
214c38af24cSFrançois Revol 			// some drivers do:
215c38af24cSFrançois Revol 			//Device()->WriteIIC8(0x20, (uint8)0xf6 - (uint8)fGain);
216c38af24cSFrançois Revol 			// but it doesn't seem to work
217c38af24cSFrançois Revol 
218c38af24cSFrançois Revol 			// works, not sure why yet, XXX check datasheet for AEG/AEC
219c38af24cSFrançois Revol 			uint8 buf[2] = { 0x20, 0x70 };
220c38af24cSFrançois Revol 			buf[1] = (uint8)0xff - (uint8)fGain;
221c38af24cSFrançois Revol 			Device()->WriteIIC(0x02, buf, 2);
222c38af24cSFrançois Revol 		}
223c38af24cSFrançois Revol 
224a486abdcSFrançois Revol 		return B_OK;
225a486abdcSFrançois Revol 	}
226a486abdcSFrançois Revol #endif
227a486abdcSFrançois Revol 	return B_BAD_VALUE;
228a486abdcSFrançois Revol }
229a486abdcSFrançois Revol 
230a486abdcSFrançois Revol 
2310866ac7eSFrançois Revol 
232601cedceSFrançois Revol B_WEBCAM_DECLARE_SENSOR(TAS5110C1BSensor, tas5110c1b)
233601cedceSFrançois Revol 
234