static int bt856_attach(struct i2c_device *device) { struct bt856 *encoder; /* This chip is not on the buz card but at the same address saa7185 */ //if (memcmp(device->bus->name, "buz", 3) == 0 || memcmp(device->bus->name, "zr36057", 6) == 0) // return 1; MOD_INC_USE_COUNT; device->data = encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL); if (encoder == NULL) { MOD_DEC_USE_COUNT; return -ENOMEM; } memset(encoder, 0, sizeof(struct bt856)); strcpy(device->name, "bt856"); encoder->bus = device->bus; encoder->addr = device->addr; encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; DEBUG(printk(KERN_INFO "%s-bt856: attach\n", encoder->bus->name)); bt856_write(encoder, 0xdc, 0x18); bt856_write(encoder, 0xda, 0); bt856_write(encoder, 0xde, 0); bt856_setbit(encoder, 0xdc, 3, 1); //bt856_setbit(encoder, 0xdc, 6, 0); bt856_setbit(encoder, 0xdc, 4, 1); switch (encoder->norm) { case VIDEO_MODE_NTSC: bt856_setbit(encoder, 0xdc, 2, 0); break; case VIDEO_MODE_PAL: bt856_setbit(encoder, 0xdc, 2, 1); break; } bt856_setbit(encoder, 0xdc, 1, 1); bt856_setbit(encoder, 0xde, 4, 0); bt856_setbit(encoder, 0xde, 3, 1); return 0; }
static inline int bt856_setbit (struct i2c_client *client, u8 reg, u8 bit, u8 value) { struct bt856 *encoder = i2c_get_clientdata(client); return bt856_write(client, reg, (encoder-> reg[reg - REG_OFFSET] & ~(1 << bit)) | (value ? (1 << bit) : 0)); }
static int bt856_detect_client (struct i2c_adapter *adapter, int address, int kind) { int i; struct i2c_client *client; struct bt856 *encoder; dprintk(1, KERN_INFO "bt856.c: detecting bt856 client on address 0x%x\n", address << 1); /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == 0) return -ENOMEM; memset(client, 0, sizeof(struct i2c_client)); client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_bt856; client->flags = I2C_CLIENT_ALLOW_USE; strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client))); encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL); if (encoder == NULL) { kfree(client); return -ENOMEM; } memset(encoder, 0, sizeof(struct bt856)); encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; i2c_set_clientdata(client, encoder); i = i2c_attach_client(client); if (i) { kfree(client); kfree(encoder); return i; } bt856_write(client, 0xdc, 0x18); bt856_write(client, 0xda, 0); bt856_write(client, 0xde, 0); bt856_setbit(client, 0xdc, 3, 1); //bt856_setbit(client, 0xdc, 6, 0); bt856_setbit(client, 0xdc, 4, 1); switch (encoder->norm) { case VIDEO_MODE_NTSC: bt856_setbit(client, 0xdc, 2, 0); break; case VIDEO_MODE_PAL: bt856_setbit(client, 0xdc, 2, 1); break; } bt856_setbit(client, 0xdc, 1, 1); bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); if (debug != 0) bt856_dump(client); dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client), client->addr << 1); return 0; }
static int bt856_command (struct i2c_client *client, unsigned int cmd, void *arg) { struct bt856 *encoder = i2c_get_clientdata(client); switch (cmd) { case 0: /* This is just for testing!!! */ dprintk(1, KERN_INFO "bt856: init\n"); bt856_write(client, 0xdc, 0x18); bt856_write(client, 0xda, 0); bt856_write(client, 0xde, 0); bt856_setbit(client, 0xdc, 3, 1); //bt856_setbit(client, 0xdc, 6, 0); bt856_setbit(client, 0xdc, 4, 1); switch (encoder->norm) { case VIDEO_MODE_NTSC: bt856_setbit(client, 0xdc, 2, 0); break; case VIDEO_MODE_PAL: bt856_setbit(client, 0xdc, 2, 1); break; } bt856_setbit(client, 0xdc, 1, 1); bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); if (debug != 0) bt856_dump(client); break; case ENCODER_GET_CAPABILITIES: { struct video_encoder_capability *cap = arg; dprintk(1, KERN_INFO "%s: get capabilities\n", I2C_NAME(client)); cap->flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC | VIDEO_ENCODER_CCIR; cap->inputs = 2; cap->outputs = 1; } break; case ENCODER_SET_NORM: { int *iarg = arg; dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client), *iarg); switch (*iarg) { case VIDEO_MODE_NTSC: bt856_setbit(client, 0xdc, 2, 0); break; case VIDEO_MODE_PAL: bt856_setbit(client, 0xdc, 2, 1); bt856_setbit(client, 0xda, 0, 0); //bt856_setbit(client, 0xda, 0, 1); break; default: return -EINVAL; } encoder->norm = *iarg; if (debug != 0) bt856_dump(client); } break; case ENCODER_SET_INPUT: { int *iarg = arg; dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client), *iarg); /* We only have video bus. * iarg = 0: input is from bt819 * iarg = 1: input is from ZR36060 */ switch (*iarg) { case 0: bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); bt856_setbit(client, 0xdc, 3, 1); bt856_setbit(client, 0xdc, 6, 0); break; case 1: bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); bt856_setbit(client, 0xdc, 3, 1); bt856_setbit(client, 0xdc, 6, 1); break; case 2: // Color bar bt856_setbit(client, 0xdc, 3, 0); bt856_setbit(client, 0xde, 4, 1); break; default: return -EINVAL; } if (debug != 0) bt856_dump(client); } break; case ENCODER_SET_OUTPUT: { int *iarg = arg; dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client), *iarg); /* not much choice of outputs */ if (*iarg != 0) { return -EINVAL; } } break; case ENCODER_ENABLE_OUTPUT: { int *iarg = arg; encoder->enable = !!*iarg; dprintk(1, KERN_INFO "%s: enable output %d\n", I2C_NAME(client), encoder->enable); } break; default: return -EINVAL; } return 0; }
static int bt856_setbit(struct bt856 *dev, int subaddr, int bit, int data) { return bt856_write(dev, subaddr,(dev->reg[subaddr] & ~(1 << bit)) | (data ? (1 << bit) : 0)); }