Loading drivers/media/video/indycam.c +163 −99 Original line number Original line Diff line number Diff line Loading @@ -27,15 +27,15 @@ #include "indycam.h" #include "indycam.h" //#define INDYCAM_DEBUG #define INDYCAM_MODULE_VERSION "0.0.5" #define INDYCAM_MODULE_VERSION "0.0.3" MODULE_DESCRIPTION("SGI IndyCam driver"); MODULE_DESCRIPTION("SGI IndyCam driver"); MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL"); // #define INDYCAM_DEBUG #ifdef INDYCAM_DEBUG #ifdef INDYCAM_DEBUG #define dprintk(x...) printk("IndyCam: " x); #define dprintk(x...) printk("IndyCam: " x); #define indycam_regdump(client) indycam_regdump_debug(client) #define indycam_regdump(client) indycam_regdump_debug(client) Loading @@ -46,14 +46,14 @@ MODULE_LICENSE("GPL"); struct indycam { struct indycam { struct i2c_client *client; struct i2c_client *client; int version; u8 version; }; }; static struct i2c_driver i2c_driver_indycam; static struct i2c_driver i2c_driver_indycam; static const unsigned char initseq[] = { static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ Loading @@ -64,12 +64,11 @@ static const unsigned char initseq[] = { /* IndyCam register handling */ /* IndyCam register handling */ static int indycam_read_reg(struct i2c_client *client, unsigned char reg, static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) unsigned char *value) { { int ret; int ret; if (reg == INDYCAM_RESET) { if (reg == INDYCAM_REG_RESET) { dprintk("indycam_read_reg(): " dprintk("indycam_read_reg(): " "skipping write-only register %d\n", reg); "skipping write-only register %d\n", reg); *value = 0; *value = 0; Loading @@ -77,24 +76,24 @@ static int indycam_read_reg(struct i2c_client *client, unsigned char reg, } } ret = i2c_smbus_read_byte_data(client, reg); ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { if (ret < 0) { printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " "register = 0x%02x\n", reg); "register = 0x%02x\n", reg); return ret; return ret; } } *value = (unsigned char)ret; *value = (u8)ret; return 0; return 0; } } static int indycam_write_reg(struct i2c_client *client, unsigned char reg, static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) unsigned char value) { { int err; int err; if ((reg == INDYCAM_BRIGHTNESS) if ((reg == INDYCAM_REG_BRIGHTNESS) || (reg == INDYCAM_VERSION)) { || (reg == INDYCAM_REG_VERSION)) { dprintk("indycam_write_reg(): " dprintk("indycam_write_reg(): " "skipping read-only register %d\n", reg); "skipping read-only register %d\n", reg); return 0; return 0; Loading @@ -102,6 +101,7 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, dprintk("Writing Reg %d = 0x%02x\n", reg, value); dprintk("Writing Reg %d = 0x%02x\n", reg, value); err = i2c_smbus_write_byte_data(client, reg, value); err = i2c_smbus_write_byte_data(client, reg, value); if (err) { if (err) { printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " "register = 0x%02x, value = 0x%02x\n", reg, value); "register = 0x%02x, value = 0x%02x\n", reg, value); Loading @@ -109,13 +109,12 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, return err; return err; } } static int indycam_write_block(struct i2c_client *client, unsigned char reg, static int indycam_write_block(struct i2c_client *client, u8 reg, unsigned char length, unsigned char *data) u8 length, u8 *data) { { unsigned char i; int i, err; int err; for (i = reg; i < length; i++) { for (i = 0; i < length; i++) { err = indycam_write_reg(client, reg + i, data[i]); err = indycam_write_reg(client, reg + i, data[i]); if (err) if (err) return err; return err; Loading @@ -130,7 +129,7 @@ static int indycam_write_block(struct i2c_client *client, unsigned char reg, static void indycam_regdump_debug(struct i2c_client *client) static void indycam_regdump_debug(struct i2c_client *client) { { int i; int i; unsigned char val; u8 val; for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) { indycam_read_reg(client, i, &val); indycam_read_reg(client, i, &val); Loading @@ -139,76 +138,144 @@ static void indycam_regdump_debug(struct i2c_client *client) } } #endif #endif static int indycam_get_controls(struct i2c_client *client, static int indycam_get_control(struct i2c_client *client, struct indycam_control *ctrl) struct indycam_control *ctrl) { { unsigned char ctrl_reg; struct indycam *camera = i2c_get_clientdata(client); u8 reg; indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); int ret = 0; ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA) ? INDYCAM_VALUE_ENABLED switch (ctrl->type) { : INDYCAM_VALUE_DISABLED; case INDYCAM_CONTROL_AGC: ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL) case INDYCAM_CONTROL_AWB: ? INDYCAM_VALUE_ENABLED ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); : INDYCAM_VALUE_DISABLED; if (ret) indycam_read_reg(client, INDYCAM_SHUTTER, return -EIO; (unsigned char *)&ctrl->shutter); if (ctrl->type == INDYCAM_CONTROL_AGC) indycam_read_reg(client, INDYCAM_GAIN, ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) (unsigned char *)&ctrl->gain); ? 1 : 0; indycam_read_reg(client, INDYCAM_RED_BALANCE, else (unsigned char *)&ctrl->red_balance); ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) indycam_read_reg(client, INDYCAM_BLUE_BALANCE, ? 1 : 0; (unsigned char *)&ctrl->blue_balance); break; indycam_read_reg(client, INDYCAM_RED_SATURATION, case INDYCAM_CONTROL_SHUTTER: (unsigned char *)&ctrl->red_saturation); ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); indycam_read_reg(client, INDYCAM_BLUE_SATURATION, if (ret) (unsigned char *)&ctrl->blue_saturation); return -EIO; indycam_read_reg(client, INDYCAM_GAMMA, ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); (unsigned char *)&ctrl->gamma); break; case INDYCAM_CONTROL_GAIN: ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_SATURATION: ret = indycam_read_reg(client, INDYCAM_REG_RED_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_SATURATION: ret = indycam_read_reg(client, INDYCAM_REG_BLUE_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_read_reg(client, INDYCAM_REG_GAMMA, ®); if (ret) return -EIO; ctrl->value = (s32)reg; } else { ctrl->value = INDYCAM_GAMMA_DEFAULT; } break; default: ret = -EINVAL; } return 0; return ret; } } static int indycam_set_controls(struct i2c_client *client, static int indycam_set_control(struct i2c_client *client, struct indycam_control *ctrl) struct indycam_control *ctrl) { { unsigned char ctrl_reg; struct indycam *camera = i2c_get_clientdata(client); u8 reg; int ret = 0; switch (ctrl->type) { case INDYCAM_CONTROL_AGC: case INDYCAM_CONTROL_AWB: ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); if (ret) break; indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); if (ctrl->type == INDYCAM_CONTROL_AGC) { if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) { if (ctrl->value) if (ctrl->agc) reg |= INDYCAM_CONTROL_AGCENA; ctrl_reg |= INDYCAM_CONTROL_AGCENA; else else ctrl_reg &= ~INDYCAM_CONTROL_AGCENA; reg &= ~INDYCAM_CONTROL_AGCENA; } } else { if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) { if (ctrl->value) if (ctrl->awb) reg |= INDYCAM_CONTROL_AWBCTL; ctrl_reg |= INDYCAM_CONTROL_AWBCTL; else else ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL; reg &= ~INDYCAM_CONTROL_AWBCTL; } } indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg); if (ctrl->shutter >= 0) indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter); if (ctrl->gain >= 0) indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain); if (ctrl->red_balance >= 0) indycam_write_reg(client, INDYCAM_RED_BALANCE, ctrl->red_balance); if (ctrl->blue_balance >= 0) indycam_write_reg(client, INDYCAM_BLUE_BALANCE, ctrl->blue_balance); if (ctrl->red_saturation >= 0) indycam_write_reg(client, INDYCAM_RED_SATURATION, ctrl->red_saturation); if (ctrl->blue_saturation >= 0) indycam_write_reg(client, INDYCAM_BLUE_SATURATION, ctrl->blue_saturation); if (ctrl->gamma >= 0) indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma); return 0; ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); break; case INDYCAM_CONTROL_SHUTTER: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); break; case INDYCAM_CONTROL_GAIN: ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); break; case INDYCAM_CONTROL_RED_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_BLUE_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_RED_SATURATION: ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_BLUE_SATURATION: ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, ctrl->value); } break; default: ret = -EINVAL; } return ret; } } /* I2C-interface */ /* I2C-interface */ Loading Loading @@ -247,7 +314,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) if (err) if (err) goto out_free_camera; goto out_free_camera; camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION); camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); if (camera->version != CAMERA_VERSION_INDY && if (camera->version != CAMERA_VERSION_INDY && camera->version != CAMERA_VERSION_MOOSE) { camera->version != CAMERA_VERSION_MOOSE) { err = -ENODEV; err = -ENODEV; Loading @@ -260,8 +328,7 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) indycam_regdump(client); indycam_regdump(client); // initialize // initialize err = indycam_write_block(client, 0, sizeof(initseq), err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); (unsigned char *)&initseq); if (err) { if (err) { printk(KERN_ERR "IndyCam initalization failed\n"); printk(KERN_ERR "IndyCam initalization failed\n"); err = -EIO; err = -EIO; Loading @@ -271,11 +338,10 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) indycam_regdump(client); indycam_regdump(client); // white balance // white balance err = indycam_write_reg(client, INDYCAM_CONTROL, err = indycam_write_reg(client, INDYCAM_REG_CONTROL, INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { if (err) { printk(KERN_ERR "IndyCam white balance " printk(KERN_ERR "IndyCam: White balancing camera failed\n"); "initialization failed\n"); err = -EIO; err = -EIO; goto out_detach_client; goto out_detach_client; } } Loading Loading @@ -371,13 +437,11 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd, /* TODO: convert values for indycam_set_controls() */ /* TODO: convert values for indycam_set_controls() */ break; break; } } case DECODER_INDYCAM_GET_CONTROLS: { case DECODER_INDYCAM_GET_CONTROL: { struct indycam_control *ctrl = arg; return indycam_get_control(client, arg); indycam_get_controls(client, ctrl); } } case DECODER_INDYCAM_SET_CONTROLS: { case DECODER_INDYCAM_SET_CONTROL: { struct indycam_control *ctrl = arg; return indycam_set_control(client, arg); indycam_set_controls(client, ctrl); } } default: default: return -EINVAL; return -EINVAL; Loading drivers/media/video/indycam.h +42 −46 Original line number Original line Diff line number Diff line Loading @@ -22,21 +22,21 @@ #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) /* Register bus addresses */ /* Register bus addresses */ #define INDYCAM_CONTROL 0x00 #define INDYCAM_REG_CONTROL 0x00 #define INDYCAM_SHUTTER 0x01 #define INDYCAM_REG_SHUTTER 0x01 #define INDYCAM_GAIN 0x02 #define INDYCAM_REG_GAIN 0x02 #define INDYCAM_BRIGHTNESS 0x03 /* read-only */ #define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */ #define INDYCAM_RED_BALANCE 0x04 #define INDYCAM_REG_RED_BALANCE 0x04 #define INDYCAM_BLUE_BALANCE 0x05 #define INDYCAM_REG_BLUE_BALANCE 0x05 #define INDYCAM_RED_SATURATION 0x06 #define INDYCAM_REG_RED_SATURATION 0x06 #define INDYCAM_BLUE_SATURATION 0x07 #define INDYCAM_REG_BLUE_SATURATION 0x07 #define INDYCAM_GAMMA 0x08 #define INDYCAM_REG_GAMMA 0x08 #define INDYCAM_VERSION 0x0e /* read-only */ #define INDYCAM_REG_VERSION 0x0e /* read-only */ #define INDYCAM_RESET 0x0f /* write-only */ #define INDYCAM_REG_RESET 0x0f /* write-only */ #define INDYCAM_LED 0x46 #define INDYCAM_REG_LED 0x46 #define INDYCAM_ORIENTATION 0x47 #define INDYCAM_REG_ORIENTATION 0x47 #define INDYCAM_BUTTON 0x48 #define INDYCAM_REG_BUTTON 0x48 /* Field definitions of registers */ /* Field definitions of registers */ #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ Loading @@ -59,13 +59,14 @@ #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 #define INDYCAM_BUTTON_RELEASED 0x10 #define INDYCAM_BUTTON_RELEASED 0x10 /* Values for controls */ #define INDYCAM_SHUTTER_MIN 0x00 #define INDYCAM_SHUTTER_MIN 0x00 #define INDYCAM_SHUTTER_MAX 0xff #define INDYCAM_SHUTTER_MAX 0xff #define INDYCAM_GAIN_MIN 0x00 #define INDYCAM_GAIN_MIN 0x00 #define INDYCAM_GAIN_MAX 0xff #define INDYCAM_GAIN_MAX 0xff #define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */ #define INDYCAM_RED_BALANCE_MIN 0x00 #define INDYCAM_RED_BALANCE_MAX 0xff #define INDYCAM_RED_BALANCE_MAX 0xff #define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */ #define INDYCAM_BLUE_BALANCE_MIN 0x00 #define INDYCAM_BLUE_BALANCE_MAX 0xff #define INDYCAM_BLUE_BALANCE_MAX 0xff #define INDYCAM_RED_SATURATION_MIN 0x00 #define INDYCAM_RED_SATURATION_MIN 0x00 #define INDYCAM_RED_SATURATION_MAX 0xff #define INDYCAM_RED_SATURATION_MAX 0xff Loading @@ -74,34 +75,9 @@ #define INDYCAM_GAMMA_MIN 0x00 #define INDYCAM_GAMMA_MIN 0x00 #define INDYCAM_GAMMA_MAX 0xff #define INDYCAM_GAMMA_MAX 0xff /* Driver interface definitions */ #define INDYCAM_AGC_DEFAULT 1 #define INDYCAM_AWB_DEFAULT 0 #define INDYCAM_VALUE_ENABLED 1 #define INDYCAM_SHUTTER_DEFAULT 0xff #define INDYCAM_VALUE_DISABLED 0 #define INDYCAM_VALUE_UNCHANGED -1 /* When setting controls, a value of -1 leaves the control unchanged. */ struct indycam_control { int agc; /* boolean */ int awb; /* boolean */ int shutter; int gain; int red_balance; int blue_balance; int red_saturation; int blue_saturation; int gamma; }; #define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control) #define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control) /* Default values for controls */ #define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED #define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED #define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60 #define INDYCAM_GAIN_DEFAULT 0x80 #define INDYCAM_GAIN_DEFAULT 0x80 #define INDYCAM_RED_BALANCE_DEFAULT 0x18 #define INDYCAM_RED_BALANCE_DEFAULT 0x18 #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 Loading @@ -109,4 +85,24 @@ struct indycam_control { #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 #define INDYCAM_GAMMA_DEFAULT 0x80 #define INDYCAM_GAMMA_DEFAULT 0x80 /* Driver interface definitions */ #define INDYCAM_CONTROL_AGC 0 /* boolean */ #define INDYCAM_CONTROL_AWB 1 /* boolean */ #define INDYCAM_CONTROL_SHUTTER 2 #define INDYCAM_CONTROL_GAIN 3 #define INDYCAM_CONTROL_RED_BALANCE 4 #define INDYCAM_CONTROL_BLUE_BALANCE 5 #define INDYCAM_CONTROL_RED_SATURATION 6 #define INDYCAM_CONTROL_BLUE_SATURATION 7 #define INDYCAM_CONTROL_GAMMA 8 struct indycam_control { u8 type; s32 value; }; #define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) #define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) #endif #endif Loading
drivers/media/video/indycam.c +163 −99 Original line number Original line Diff line number Diff line Loading @@ -27,15 +27,15 @@ #include "indycam.h" #include "indycam.h" //#define INDYCAM_DEBUG #define INDYCAM_MODULE_VERSION "0.0.5" #define INDYCAM_MODULE_VERSION "0.0.3" MODULE_DESCRIPTION("SGI IndyCam driver"); MODULE_DESCRIPTION("SGI IndyCam driver"); MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL"); // #define INDYCAM_DEBUG #ifdef INDYCAM_DEBUG #ifdef INDYCAM_DEBUG #define dprintk(x...) printk("IndyCam: " x); #define dprintk(x...) printk("IndyCam: " x); #define indycam_regdump(client) indycam_regdump_debug(client) #define indycam_regdump(client) indycam_regdump_debug(client) Loading @@ -46,14 +46,14 @@ MODULE_LICENSE("GPL"); struct indycam { struct indycam { struct i2c_client *client; struct i2c_client *client; int version; u8 version; }; }; static struct i2c_driver i2c_driver_indycam; static struct i2c_driver i2c_driver_indycam; static const unsigned char initseq[] = { static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ Loading @@ -64,12 +64,11 @@ static const unsigned char initseq[] = { /* IndyCam register handling */ /* IndyCam register handling */ static int indycam_read_reg(struct i2c_client *client, unsigned char reg, static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) unsigned char *value) { { int ret; int ret; if (reg == INDYCAM_RESET) { if (reg == INDYCAM_REG_RESET) { dprintk("indycam_read_reg(): " dprintk("indycam_read_reg(): " "skipping write-only register %d\n", reg); "skipping write-only register %d\n", reg); *value = 0; *value = 0; Loading @@ -77,24 +76,24 @@ static int indycam_read_reg(struct i2c_client *client, unsigned char reg, } } ret = i2c_smbus_read_byte_data(client, reg); ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { if (ret < 0) { printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " "register = 0x%02x\n", reg); "register = 0x%02x\n", reg); return ret; return ret; } } *value = (unsigned char)ret; *value = (u8)ret; return 0; return 0; } } static int indycam_write_reg(struct i2c_client *client, unsigned char reg, static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) unsigned char value) { { int err; int err; if ((reg == INDYCAM_BRIGHTNESS) if ((reg == INDYCAM_REG_BRIGHTNESS) || (reg == INDYCAM_VERSION)) { || (reg == INDYCAM_REG_VERSION)) { dprintk("indycam_write_reg(): " dprintk("indycam_write_reg(): " "skipping read-only register %d\n", reg); "skipping read-only register %d\n", reg); return 0; return 0; Loading @@ -102,6 +101,7 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, dprintk("Writing Reg %d = 0x%02x\n", reg, value); dprintk("Writing Reg %d = 0x%02x\n", reg, value); err = i2c_smbus_write_byte_data(client, reg, value); err = i2c_smbus_write_byte_data(client, reg, value); if (err) { if (err) { printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " "register = 0x%02x, value = 0x%02x\n", reg, value); "register = 0x%02x, value = 0x%02x\n", reg, value); Loading @@ -109,13 +109,12 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, return err; return err; } } static int indycam_write_block(struct i2c_client *client, unsigned char reg, static int indycam_write_block(struct i2c_client *client, u8 reg, unsigned char length, unsigned char *data) u8 length, u8 *data) { { unsigned char i; int i, err; int err; for (i = reg; i < length; i++) { for (i = 0; i < length; i++) { err = indycam_write_reg(client, reg + i, data[i]); err = indycam_write_reg(client, reg + i, data[i]); if (err) if (err) return err; return err; Loading @@ -130,7 +129,7 @@ static int indycam_write_block(struct i2c_client *client, unsigned char reg, static void indycam_regdump_debug(struct i2c_client *client) static void indycam_regdump_debug(struct i2c_client *client) { { int i; int i; unsigned char val; u8 val; for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) { indycam_read_reg(client, i, &val); indycam_read_reg(client, i, &val); Loading @@ -139,76 +138,144 @@ static void indycam_regdump_debug(struct i2c_client *client) } } #endif #endif static int indycam_get_controls(struct i2c_client *client, static int indycam_get_control(struct i2c_client *client, struct indycam_control *ctrl) struct indycam_control *ctrl) { { unsigned char ctrl_reg; struct indycam *camera = i2c_get_clientdata(client); u8 reg; indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); int ret = 0; ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA) ? INDYCAM_VALUE_ENABLED switch (ctrl->type) { : INDYCAM_VALUE_DISABLED; case INDYCAM_CONTROL_AGC: ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL) case INDYCAM_CONTROL_AWB: ? INDYCAM_VALUE_ENABLED ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); : INDYCAM_VALUE_DISABLED; if (ret) indycam_read_reg(client, INDYCAM_SHUTTER, return -EIO; (unsigned char *)&ctrl->shutter); if (ctrl->type == INDYCAM_CONTROL_AGC) indycam_read_reg(client, INDYCAM_GAIN, ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) (unsigned char *)&ctrl->gain); ? 1 : 0; indycam_read_reg(client, INDYCAM_RED_BALANCE, else (unsigned char *)&ctrl->red_balance); ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) indycam_read_reg(client, INDYCAM_BLUE_BALANCE, ? 1 : 0; (unsigned char *)&ctrl->blue_balance); break; indycam_read_reg(client, INDYCAM_RED_SATURATION, case INDYCAM_CONTROL_SHUTTER: (unsigned char *)&ctrl->red_saturation); ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); indycam_read_reg(client, INDYCAM_BLUE_SATURATION, if (ret) (unsigned char *)&ctrl->blue_saturation); return -EIO; indycam_read_reg(client, INDYCAM_GAMMA, ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); (unsigned char *)&ctrl->gamma); break; case INDYCAM_CONTROL_GAIN: ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_SATURATION: ret = indycam_read_reg(client, INDYCAM_REG_RED_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_SATURATION: ret = indycam_read_reg(client, INDYCAM_REG_BLUE_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_read_reg(client, INDYCAM_REG_GAMMA, ®); if (ret) return -EIO; ctrl->value = (s32)reg; } else { ctrl->value = INDYCAM_GAMMA_DEFAULT; } break; default: ret = -EINVAL; } return 0; return ret; } } static int indycam_set_controls(struct i2c_client *client, static int indycam_set_control(struct i2c_client *client, struct indycam_control *ctrl) struct indycam_control *ctrl) { { unsigned char ctrl_reg; struct indycam *camera = i2c_get_clientdata(client); u8 reg; int ret = 0; switch (ctrl->type) { case INDYCAM_CONTROL_AGC: case INDYCAM_CONTROL_AWB: ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); if (ret) break; indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); if (ctrl->type == INDYCAM_CONTROL_AGC) { if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) { if (ctrl->value) if (ctrl->agc) reg |= INDYCAM_CONTROL_AGCENA; ctrl_reg |= INDYCAM_CONTROL_AGCENA; else else ctrl_reg &= ~INDYCAM_CONTROL_AGCENA; reg &= ~INDYCAM_CONTROL_AGCENA; } } else { if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) { if (ctrl->value) if (ctrl->awb) reg |= INDYCAM_CONTROL_AWBCTL; ctrl_reg |= INDYCAM_CONTROL_AWBCTL; else else ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL; reg &= ~INDYCAM_CONTROL_AWBCTL; } } indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg); if (ctrl->shutter >= 0) indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter); if (ctrl->gain >= 0) indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain); if (ctrl->red_balance >= 0) indycam_write_reg(client, INDYCAM_RED_BALANCE, ctrl->red_balance); if (ctrl->blue_balance >= 0) indycam_write_reg(client, INDYCAM_BLUE_BALANCE, ctrl->blue_balance); if (ctrl->red_saturation >= 0) indycam_write_reg(client, INDYCAM_RED_SATURATION, ctrl->red_saturation); if (ctrl->blue_saturation >= 0) indycam_write_reg(client, INDYCAM_BLUE_SATURATION, ctrl->blue_saturation); if (ctrl->gamma >= 0) indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma); return 0; ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); break; case INDYCAM_CONTROL_SHUTTER: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); break; case INDYCAM_CONTROL_GAIN: ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); break; case INDYCAM_CONTROL_RED_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_BLUE_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_RED_SATURATION: ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_BLUE_SATURATION: ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, ctrl->value); } break; default: ret = -EINVAL; } return ret; } } /* I2C-interface */ /* I2C-interface */ Loading Loading @@ -247,7 +314,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) if (err) if (err) goto out_free_camera; goto out_free_camera; camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION); camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); if (camera->version != CAMERA_VERSION_INDY && if (camera->version != CAMERA_VERSION_INDY && camera->version != CAMERA_VERSION_MOOSE) { camera->version != CAMERA_VERSION_MOOSE) { err = -ENODEV; err = -ENODEV; Loading @@ -260,8 +328,7 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) indycam_regdump(client); indycam_regdump(client); // initialize // initialize err = indycam_write_block(client, 0, sizeof(initseq), err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); (unsigned char *)&initseq); if (err) { if (err) { printk(KERN_ERR "IndyCam initalization failed\n"); printk(KERN_ERR "IndyCam initalization failed\n"); err = -EIO; err = -EIO; Loading @@ -271,11 +338,10 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) indycam_regdump(client); indycam_regdump(client); // white balance // white balance err = indycam_write_reg(client, INDYCAM_CONTROL, err = indycam_write_reg(client, INDYCAM_REG_CONTROL, INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { if (err) { printk(KERN_ERR "IndyCam white balance " printk(KERN_ERR "IndyCam: White balancing camera failed\n"); "initialization failed\n"); err = -EIO; err = -EIO; goto out_detach_client; goto out_detach_client; } } Loading Loading @@ -371,13 +437,11 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd, /* TODO: convert values for indycam_set_controls() */ /* TODO: convert values for indycam_set_controls() */ break; break; } } case DECODER_INDYCAM_GET_CONTROLS: { case DECODER_INDYCAM_GET_CONTROL: { struct indycam_control *ctrl = arg; return indycam_get_control(client, arg); indycam_get_controls(client, ctrl); } } case DECODER_INDYCAM_SET_CONTROLS: { case DECODER_INDYCAM_SET_CONTROL: { struct indycam_control *ctrl = arg; return indycam_set_control(client, arg); indycam_set_controls(client, ctrl); } } default: default: return -EINVAL; return -EINVAL; Loading
drivers/media/video/indycam.h +42 −46 Original line number Original line Diff line number Diff line Loading @@ -22,21 +22,21 @@ #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) /* Register bus addresses */ /* Register bus addresses */ #define INDYCAM_CONTROL 0x00 #define INDYCAM_REG_CONTROL 0x00 #define INDYCAM_SHUTTER 0x01 #define INDYCAM_REG_SHUTTER 0x01 #define INDYCAM_GAIN 0x02 #define INDYCAM_REG_GAIN 0x02 #define INDYCAM_BRIGHTNESS 0x03 /* read-only */ #define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */ #define INDYCAM_RED_BALANCE 0x04 #define INDYCAM_REG_RED_BALANCE 0x04 #define INDYCAM_BLUE_BALANCE 0x05 #define INDYCAM_REG_BLUE_BALANCE 0x05 #define INDYCAM_RED_SATURATION 0x06 #define INDYCAM_REG_RED_SATURATION 0x06 #define INDYCAM_BLUE_SATURATION 0x07 #define INDYCAM_REG_BLUE_SATURATION 0x07 #define INDYCAM_GAMMA 0x08 #define INDYCAM_REG_GAMMA 0x08 #define INDYCAM_VERSION 0x0e /* read-only */ #define INDYCAM_REG_VERSION 0x0e /* read-only */ #define INDYCAM_RESET 0x0f /* write-only */ #define INDYCAM_REG_RESET 0x0f /* write-only */ #define INDYCAM_LED 0x46 #define INDYCAM_REG_LED 0x46 #define INDYCAM_ORIENTATION 0x47 #define INDYCAM_REG_ORIENTATION 0x47 #define INDYCAM_BUTTON 0x48 #define INDYCAM_REG_BUTTON 0x48 /* Field definitions of registers */ /* Field definitions of registers */ #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ Loading @@ -59,13 +59,14 @@ #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 #define INDYCAM_BUTTON_RELEASED 0x10 #define INDYCAM_BUTTON_RELEASED 0x10 /* Values for controls */ #define INDYCAM_SHUTTER_MIN 0x00 #define INDYCAM_SHUTTER_MIN 0x00 #define INDYCAM_SHUTTER_MAX 0xff #define INDYCAM_SHUTTER_MAX 0xff #define INDYCAM_GAIN_MIN 0x00 #define INDYCAM_GAIN_MIN 0x00 #define INDYCAM_GAIN_MAX 0xff #define INDYCAM_GAIN_MAX 0xff #define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */ #define INDYCAM_RED_BALANCE_MIN 0x00 #define INDYCAM_RED_BALANCE_MAX 0xff #define INDYCAM_RED_BALANCE_MAX 0xff #define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */ #define INDYCAM_BLUE_BALANCE_MIN 0x00 #define INDYCAM_BLUE_BALANCE_MAX 0xff #define INDYCAM_BLUE_BALANCE_MAX 0xff #define INDYCAM_RED_SATURATION_MIN 0x00 #define INDYCAM_RED_SATURATION_MIN 0x00 #define INDYCAM_RED_SATURATION_MAX 0xff #define INDYCAM_RED_SATURATION_MAX 0xff Loading @@ -74,34 +75,9 @@ #define INDYCAM_GAMMA_MIN 0x00 #define INDYCAM_GAMMA_MIN 0x00 #define INDYCAM_GAMMA_MAX 0xff #define INDYCAM_GAMMA_MAX 0xff /* Driver interface definitions */ #define INDYCAM_AGC_DEFAULT 1 #define INDYCAM_AWB_DEFAULT 0 #define INDYCAM_VALUE_ENABLED 1 #define INDYCAM_SHUTTER_DEFAULT 0xff #define INDYCAM_VALUE_DISABLED 0 #define INDYCAM_VALUE_UNCHANGED -1 /* When setting controls, a value of -1 leaves the control unchanged. */ struct indycam_control { int agc; /* boolean */ int awb; /* boolean */ int shutter; int gain; int red_balance; int blue_balance; int red_saturation; int blue_saturation; int gamma; }; #define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control) #define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control) /* Default values for controls */ #define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED #define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED #define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60 #define INDYCAM_GAIN_DEFAULT 0x80 #define INDYCAM_GAIN_DEFAULT 0x80 #define INDYCAM_RED_BALANCE_DEFAULT 0x18 #define INDYCAM_RED_BALANCE_DEFAULT 0x18 #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 Loading @@ -109,4 +85,24 @@ struct indycam_control { #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 #define INDYCAM_GAMMA_DEFAULT 0x80 #define INDYCAM_GAMMA_DEFAULT 0x80 /* Driver interface definitions */ #define INDYCAM_CONTROL_AGC 0 /* boolean */ #define INDYCAM_CONTROL_AWB 1 /* boolean */ #define INDYCAM_CONTROL_SHUTTER 2 #define INDYCAM_CONTROL_GAIN 3 #define INDYCAM_CONTROL_RED_BALANCE 4 #define INDYCAM_CONTROL_BLUE_BALANCE 5 #define INDYCAM_CONTROL_RED_SATURATION 6 #define INDYCAM_CONTROL_BLUE_SATURATION 7 #define INDYCAM_CONTROL_GAMMA 8 struct indycam_control { u8 type; s32 value; }; #define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) #define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) #endif #endif