aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/indycam.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/indycam.c')
-rw-r--r--drivers/media/video/indycam.c262
1 files changed, 163 insertions, 99 deletions
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index 26dd06ec89a2..deeef125eb92 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -27,15 +27,15 @@
27 27
28#include "indycam.h" 28#include "indycam.h"
29 29
30//#define INDYCAM_DEBUG 30#define INDYCAM_MODULE_VERSION "0.0.5"
31
32#define INDYCAM_MODULE_VERSION "0.0.3"
33 31
34MODULE_DESCRIPTION("SGI IndyCam driver"); 32MODULE_DESCRIPTION("SGI IndyCam driver");
35MODULE_VERSION(INDYCAM_MODULE_VERSION); 33MODULE_VERSION(INDYCAM_MODULE_VERSION);
36MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); 34MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
37MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
38 36
37// #define INDYCAM_DEBUG
38
39#ifdef INDYCAM_DEBUG 39#ifdef INDYCAM_DEBUG
40#define dprintk(x...) printk("IndyCam: " x); 40#define dprintk(x...) printk("IndyCam: " x);
41#define indycam_regdump(client) indycam_regdump_debug(client) 41#define indycam_regdump(client) indycam_regdump_debug(client)
@@ -46,14 +46,14 @@ MODULE_LICENSE("GPL");
46 46
47struct indycam { 47struct indycam {
48 struct i2c_client *client; 48 struct i2c_client *client;
49 int version; 49 u8 version;
50}; 50};
51 51
52static struct i2c_driver i2c_driver_indycam; 52static struct i2c_driver i2c_driver_indycam;
53 53
54static const unsigned char initseq[] = { 54static const u8 initseq[] = {
55 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ 55 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
56 INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */ 56 INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */
57 INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ 57 INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */
58 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ 58 0x00, /* INDYCAM_BRIGHTNESS (read-only) */
59 INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ 59 INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */
@@ -64,12 +64,11 @@ static const unsigned char initseq[] = {
64 64
65/* IndyCam register handling */ 65/* IndyCam register handling */
66 66
67static int indycam_read_reg(struct i2c_client *client, unsigned char reg, 67static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value)
68 unsigned char *value)
69{ 68{
70 int ret; 69 int ret;
71 70
72 if (reg == INDYCAM_RESET) { 71 if (reg == INDYCAM_REG_RESET) {
73 dprintk("indycam_read_reg(): " 72 dprintk("indycam_read_reg(): "
74 "skipping write-only register %d\n", reg); 73 "skipping write-only register %d\n", reg);
75 *value = 0; 74 *value = 0;
@@ -77,24 +76,24 @@ static int indycam_read_reg(struct i2c_client *client, unsigned char reg,
77 } 76 }
78 77
79 ret = i2c_smbus_read_byte_data(client, reg); 78 ret = i2c_smbus_read_byte_data(client, reg);
79
80 if (ret < 0) { 80 if (ret < 0) {
81 printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " 81 printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
82 "register = 0x%02x\n", reg); 82 "register = 0x%02x\n", reg);
83 return ret; 83 return ret;
84 } 84 }
85 85
86 *value = (unsigned char)ret; 86 *value = (u8)ret;
87 87
88 return 0; 88 return 0;
89} 89}
90 90
91static int indycam_write_reg(struct i2c_client *client, unsigned char reg, 91static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value)
92 unsigned char value)
93{ 92{
94 int err; 93 int err;
95 94
96 if ((reg == INDYCAM_BRIGHTNESS) 95 if ((reg == INDYCAM_REG_BRIGHTNESS)
97 || (reg == INDYCAM_VERSION)) { 96 || (reg == INDYCAM_REG_VERSION)) {
98 dprintk("indycam_write_reg(): " 97 dprintk("indycam_write_reg(): "
99 "skipping read-only register %d\n", reg); 98 "skipping read-only register %d\n", reg);
100 return 0; 99 return 0;
@@ -102,6 +101,7 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg,
102 101
103 dprintk("Writing Reg %d = 0x%02x\n", reg, value); 102 dprintk("Writing Reg %d = 0x%02x\n", reg, value);
104 err = i2c_smbus_write_byte_data(client, reg, value); 103 err = i2c_smbus_write_byte_data(client, reg, value);
104
105 if (err) { 105 if (err) {
106 printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " 106 printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
107 "register = 0x%02x, value = 0x%02x\n", reg, value); 107 "register = 0x%02x, value = 0x%02x\n", reg, value);
@@ -109,13 +109,12 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg,
109 return err; 109 return err;
110} 110}
111 111
112static int indycam_write_block(struct i2c_client *client, unsigned char reg, 112static int indycam_write_block(struct i2c_client *client, u8 reg,
113 unsigned char length, unsigned char *data) 113 u8 length, u8 *data)
114{ 114{
115 unsigned char i; 115 int i, err;
116 int err;
117 116
118 for (i = reg; i < length; i++) { 117 for (i = 0; i < length; i++) {
119 err = indycam_write_reg(client, reg + i, data[i]); 118 err = indycam_write_reg(client, reg + i, data[i]);
120 if (err) 119 if (err)
121 return err; 120 return err;
@@ -130,7 +129,7 @@ static int indycam_write_block(struct i2c_client *client, unsigned char reg,
130static void indycam_regdump_debug(struct i2c_client *client) 129static void indycam_regdump_debug(struct i2c_client *client)
131{ 130{
132 int i; 131 int i;
133 unsigned char val; 132 u8 val;
134 133
135 for (i = 0; i < 9; i++) { 134 for (i = 0; i < 9; i++) {
136 indycam_read_reg(client, i, &val); 135 indycam_read_reg(client, i, &val);
@@ -139,76 +138,144 @@ static void indycam_regdump_debug(struct i2c_client *client)
139} 138}
140#endif 139#endif
141 140
142static int indycam_get_controls(struct i2c_client *client, 141static int indycam_get_control(struct i2c_client *client,
143 struct indycam_control *ctrl) 142 struct indycam_control *ctrl)
144{ 143{
145 unsigned char ctrl_reg; 144 struct indycam *camera = i2c_get_clientdata(client);
146 145 u8 reg;
147 indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); 146 int ret = 0;
148 ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA) 147
149 ? INDYCAM_VALUE_ENABLED 148 switch (ctrl->type) {
150 : INDYCAM_VALUE_DISABLED; 149 case INDYCAM_CONTROL_AGC:
151 ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL) 150 case INDYCAM_CONTROL_AWB:
152 ? INDYCAM_VALUE_ENABLED 151 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
153 : INDYCAM_VALUE_DISABLED; 152 if (ret)
154 indycam_read_reg(client, INDYCAM_SHUTTER, 153 return -EIO;
155 (unsigned char *)&ctrl->shutter); 154 if (ctrl->type == INDYCAM_CONTROL_AGC)
156 indycam_read_reg(client, INDYCAM_GAIN, 155 ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
157 (unsigned char *)&ctrl->gain); 156 ? 1 : 0;
158 indycam_read_reg(client, INDYCAM_RED_BALANCE, 157 else
159 (unsigned char *)&ctrl->red_balance); 158 ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
160 indycam_read_reg(client, INDYCAM_BLUE_BALANCE, 159 ? 1 : 0;
161 (unsigned char *)&ctrl->blue_balance); 160 break;
162 indycam_read_reg(client, INDYCAM_RED_SATURATION, 161 case INDYCAM_CONTROL_SHUTTER:
163 (unsigned char *)&ctrl->red_saturation); 162 ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, &reg);
164 indycam_read_reg(client, INDYCAM_BLUE_SATURATION, 163 if (ret)
165 (unsigned char *)&ctrl->blue_saturation); 164 return -EIO;
166 indycam_read_reg(client, INDYCAM_GAMMA, 165 ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
167 (unsigned char *)&ctrl->gamma); 166 break;
167 case INDYCAM_CONTROL_GAIN:
168 ret = indycam_read_reg(client, INDYCAM_REG_GAIN, &reg);
169 if (ret)
170 return -EIO;
171 ctrl->value = (s32)reg;
172 break;
173 case INDYCAM_CONTROL_RED_BALANCE:
174 ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, &reg);
175 if (ret)
176 return -EIO;
177 ctrl->value = (s32)reg;
178 break;
179 case INDYCAM_CONTROL_BLUE_BALANCE:
180 ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, &reg);
181 if (ret)
182 return -EIO;
183 ctrl->value = (s32)reg;
184 break;
185 case INDYCAM_CONTROL_RED_SATURATION:
186 ret = indycam_read_reg(client,
187 INDYCAM_REG_RED_SATURATION, &reg);
188 if (ret)
189 return -EIO;
190 ctrl->value = (s32)reg;
191 break;
192 case INDYCAM_CONTROL_BLUE_SATURATION:
193 ret = indycam_read_reg(client,
194 INDYCAM_REG_BLUE_SATURATION, &reg);
195 if (ret)
196 return -EIO;
197 ctrl->value = (s32)reg;
198 break;
199 case INDYCAM_CONTROL_GAMMA:
200 if (camera->version == CAMERA_VERSION_MOOSE) {
201 ret = indycam_read_reg(client,
202 INDYCAM_REG_GAMMA, &reg);
203 if (ret)
204 return -EIO;
205 ctrl->value = (s32)reg;
206 } else {
207 ctrl->value = INDYCAM_GAMMA_DEFAULT;
208 }
209 break;
210 default:
211 ret = -EINVAL;
212 }
168 213
169 return 0; 214 return ret;
170} 215}
171 216
172static int indycam_set_controls(struct i2c_client *client, 217static int indycam_set_control(struct i2c_client *client,
173 struct indycam_control *ctrl) 218 struct indycam_control *ctrl)
174{ 219{
175 unsigned char ctrl_reg; 220 struct indycam *camera = i2c_get_clientdata(client);
221 u8 reg;
222 int ret = 0;
223
224 switch (ctrl->type) {
225 case INDYCAM_CONTROL_AGC:
226 case INDYCAM_CONTROL_AWB:
227 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
228 if (ret)
229 break;
176 230
177 indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); 231 if (ctrl->type == INDYCAM_CONTROL_AGC) {
178 if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) { 232 if (ctrl->value)
179 if (ctrl->agc) 233 reg |= INDYCAM_CONTROL_AGCENA;
180 ctrl_reg |= INDYCAM_CONTROL_AGCENA; 234 else
181 else 235 reg &= ~INDYCAM_CONTROL_AGCENA;
182 ctrl_reg &= ~INDYCAM_CONTROL_AGCENA; 236 } else {
183 } 237 if (ctrl->value)
184 if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) { 238 reg |= INDYCAM_CONTROL_AWBCTL;
185 if (ctrl->awb) 239 else
186 ctrl_reg |= INDYCAM_CONTROL_AWBCTL; 240 reg &= ~INDYCAM_CONTROL_AWBCTL;
187 else 241 }
188 ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL; 242
243 ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg);
244 break;
245 case INDYCAM_CONTROL_SHUTTER:
246 reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
247 ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg);
248 break;
249 case INDYCAM_CONTROL_GAIN:
250 ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value);
251 break;
252 case INDYCAM_CONTROL_RED_BALANCE:
253 ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE,
254 ctrl->value);
255 break;
256 case INDYCAM_CONTROL_BLUE_BALANCE:
257 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE,
258 ctrl->value);
259 break;
260 case INDYCAM_CONTROL_RED_SATURATION:
261 ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION,
262 ctrl->value);
263 break;
264 case INDYCAM_CONTROL_BLUE_SATURATION:
265 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION,
266 ctrl->value);
267 break;
268 case INDYCAM_CONTROL_GAMMA:
269 if (camera->version == CAMERA_VERSION_MOOSE) {
270 ret = indycam_write_reg(client, INDYCAM_REG_GAMMA,
271 ctrl->value);
272 }
273 break;
274 default:
275 ret = -EINVAL;
189 } 276 }
190 indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg);
191
192 if (ctrl->shutter >= 0)
193 indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter);
194 if (ctrl->gain >= 0)
195 indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain);
196 if (ctrl->red_balance >= 0)
197 indycam_write_reg(client, INDYCAM_RED_BALANCE,
198 ctrl->red_balance);
199 if (ctrl->blue_balance >= 0)
200 indycam_write_reg(client, INDYCAM_BLUE_BALANCE,
201 ctrl->blue_balance);
202 if (ctrl->red_saturation >= 0)
203 indycam_write_reg(client, INDYCAM_RED_SATURATION,
204 ctrl->red_saturation);
205 if (ctrl->blue_saturation >= 0)
206 indycam_write_reg(client, INDYCAM_BLUE_SATURATION,
207 ctrl->blue_saturation);
208 if (ctrl->gamma >= 0)
209 indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma);
210 277
211 return 0; 278 return ret;
212} 279}
213 280
214/* I2C-interface */ 281/* I2C-interface */
@@ -247,7 +314,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
247 if (err) 314 if (err)
248 goto out_free_camera; 315 goto out_free_camera;
249 316
250 camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION); 317 camera->version = i2c_smbus_read_byte_data(client,
318 INDYCAM_REG_VERSION);
251 if (camera->version != CAMERA_VERSION_INDY && 319 if (camera->version != CAMERA_VERSION_INDY &&
252 camera->version != CAMERA_VERSION_MOOSE) { 320 camera->version != CAMERA_VERSION_MOOSE) {
253 err = -ENODEV; 321 err = -ENODEV;
@@ -260,8 +328,7 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
260 indycam_regdump(client); 328 indycam_regdump(client);
261 329
262 // initialize 330 // initialize
263 err = indycam_write_block(client, 0, sizeof(initseq), 331 err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq);
264 (unsigned char *)&initseq);
265 if (err) { 332 if (err) {
266 printk(KERN_ERR "IndyCam initalization failed\n"); 333 printk(KERN_ERR "IndyCam initalization failed\n");
267 err = -EIO; 334 err = -EIO;
@@ -271,11 +338,10 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
271 indycam_regdump(client); 338 indycam_regdump(client);
272 339
273 // white balance 340 // white balance
274 err = indycam_write_reg(client, INDYCAM_CONTROL, 341 err = indycam_write_reg(client, INDYCAM_REG_CONTROL,
275 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); 342 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
276 if (err) { 343 if (err) {
277 printk(KERN_ERR "IndyCam white balance " 344 printk(KERN_ERR "IndyCam: White balancing camera failed\n");
278 "initialization failed\n");
279 err = -EIO; 345 err = -EIO;
280 goto out_detach_client; 346 goto out_detach_client;
281 } 347 }
@@ -371,13 +437,11 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd,
371 /* TODO: convert values for indycam_set_controls() */ 437 /* TODO: convert values for indycam_set_controls() */
372 break; 438 break;
373 } 439 }
374 case DECODER_INDYCAM_GET_CONTROLS: { 440 case DECODER_INDYCAM_GET_CONTROL: {
375 struct indycam_control *ctrl = arg; 441 return indycam_get_control(client, arg);
376 indycam_get_controls(client, ctrl);
377 } 442 }
378 case DECODER_INDYCAM_SET_CONTROLS: { 443 case DECODER_INDYCAM_SET_CONTROL: {
379 struct indycam_control *ctrl = arg; 444 return indycam_set_control(client, arg);
380 indycam_set_controls(client, ctrl);
381 } 445 }
382 default: 446 default:
383 return -EINVAL; 447 return -EINVAL;
@@ -388,12 +452,12 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd,
388 452
389static struct i2c_driver i2c_driver_indycam = { 453static struct i2c_driver i2c_driver_indycam = {
390 .owner = THIS_MODULE, 454 .owner = THIS_MODULE,
391 .name = "indycam", 455 .name = "indycam",
392 .id = I2C_DRIVERID_INDYCAM, 456 .id = I2C_DRIVERID_INDYCAM,
393 .flags = I2C_DF_NOTIFY, 457 .flags = I2C_DF_NOTIFY,
394 .attach_adapter = indycam_probe, 458 .attach_adapter = indycam_probe,
395 .detach_client = indycam_detach, 459 .detach_client = indycam_detach,
396 .command = indycam_command, 460 .command = indycam_command,
397}; 461};
398 462
399static int __init indycam_init(void) 463static int __init indycam_init(void)