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