static int saa7185_detect_client (struct i2c_adapter *adapter, int address, int kind) { int i; struct i2c_client *client; struct saa7185 *encoder; dprintk(1, KERN_INFO "saa7185.c: detecting saa7185 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 = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == 0) return -ENOMEM; client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_saa7185; strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client))); encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); if (encoder == NULL) { kfree(client); return -ENOMEM; } 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; } i = saa7185_write_block(client, init_common, sizeof(init_common)); if (i >= 0) { i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); } if (i < 0) { dprintk(1, KERN_ERR "%s_attach: init error %d\n", I2C_NAME(client), i); } else { dprintk(1, KERN_INFO "%s_attach: chip version %d at address 0x%x\n", I2C_NAME(client), saa7185_read(client) >> 5, client->addr << 1); } return 0; }
static int saa7111_detect_client (struct i2c_adapter *adapter, int address, int kind) { int i; struct i2c_client *client; struct saa7111 *decoder; struct video_decoder_init vdi; dprintk(1, KERN_INFO "saa7111.c: detecting saa7111 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 = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == 0) return -ENOMEM; client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_saa7111; strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client))); decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL); if (decoder == NULL) { kfree(client); return -ENOMEM; } decoder->norm = VIDEO_MODE_NTSC; decoder->input = 0; decoder->enable = 1; i2c_set_clientdata(client, decoder); i = i2c_attach_client(client); if (i) { kfree(client); kfree(decoder); return i; } vdi.data = saa7111_i2c_init; vdi.len = sizeof(saa7111_i2c_init); i = saa7111_init_decoder(client, &vdi); if (i < 0) { dprintk(1, KERN_ERR "%s_attach error: init status %d\n", I2C_NAME(client), i); } else { dprintk(1, KERN_INFO "%s_attach: chip version %x at address 0x%x\n", I2C_NAME(client), saa7111_read(client, 0x00) >> 4, client->addr << 1); } return 0; }
static int bt856_attach_adapter (struct i2c_adapter *adapter) { dprintk(1, KERN_INFO "bt856.c: starting probe for adapter %s (0x%x)\n", I2C_NAME(adapter), adapter->id); return i2c_probe(adapter, &addr_data, &bt856_detect_client); }
static void bt856_dump (struct i2c_client *client) { int i; struct bt856 *encoder = i2c_get_clientdata(client); printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); for (i = 0xd6; i <= 0xde; i += 2) printk(" %02x", encoder->reg[i - REG_OFFSET]); printk("\n"); }
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 vpx3220_command (struct i2c_client *client, unsigned int cmd, void *arg) { struct vpx3220 *decoder = i2c_get_clientdata(client); switch (cmd) { case 0: { vpx3220_write_block(client, init_common, sizeof(init_common)); vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); switch (decoder->norm) { case VIDEO_MODE_NTSC: vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); break; case VIDEO_MODE_PAL: vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); break; case VIDEO_MODE_SECAM: vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); break; default: vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); break; } } break; case DECODER_DUMP: { vpx3220_dump_i2c(client); } break; case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n", I2C_NAME(client)); cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; cap->inputs = 3; cap->outputs = 1; } break; case DECODER_GET_STATUS: { int res = 0, status; dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n", I2C_NAME(client)); status = vpx3220_fp_read(client, 0x0f3); dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client), status); if (status < 0) return status; if ((status & 0x20) == 0) { res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR; switch (status & 0x18) { case 0x00: case 0x10: case 0x14: case 0x18: res |= DECODER_STATUS_PAL; break; case 0x08: res |= DECODER_STATUS_SECAM; break; case 0x04: case 0x0c: case 0x1c: res |= DECODER_STATUS_NTSC; break; } } *(int *) arg = res; } break; case DECODER_SET_NORM: { int *iarg = arg, data; dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n", I2C_NAME(client), *iarg); switch (*iarg) { case VIDEO_MODE_NTSC: vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); dprintk(1, KERN_INFO "%s: norm switched to NTSC\n", I2C_NAME(client)); break; case VIDEO_MODE_PAL: vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); dprintk(1, KERN_INFO "%s: norm switched to PAL\n", I2C_NAME(client)); break; case VIDEO_MODE_SECAM: vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); dprintk(1, KERN_INFO "%s: norm switched to SECAM\n", I2C_NAME(client)); break; case VIDEO_MODE_AUTO: /* FIXME This is only preliminary support */ data = vpx3220_fp_read(client, 0xf2) & 0x20; vpx3220_fp_write(client, 0xf2, 0x00c0 | data); dprintk(1, KERN_INFO "%s: norm switched to Auto\n", I2C_NAME(client)); break; default: return -EINVAL; } decoder->norm = *iarg; } break; case DECODER_SET_INPUT: { int *iarg = arg, data; /* RJ: *iarg = 0: ST8 (PCTV) input *iarg = 1: COMPOSITE input *iarg = 2: SVHS input */ const int input[3][2] = { {0x0c, 0}, {0x0d, 0}, {0x0e, 1} }; if (*iarg < 0 || *iarg > 2) return -EINVAL; dprintk(1, KERN_INFO "%s: input switched to %s\n", I2C_NAME(client), inputs[*iarg]); vpx3220_write(client, 0x33, input[*iarg][0]); data = vpx3220_fp_read(client, 0xf2) & ~(0x0020); if (data < 0) return data; /* 0x0010 is required to latch the setting */ vpx3220_fp_write(client, 0xf2, data | (input[*iarg][1] << 5) | 0x0010); udelay(10); } break; case DECODER_SET_OUTPUT: { int *iarg = arg; /* not much choice of outputs */ if (*iarg != 0) { return -EINVAL; } } break; case DECODER_ENABLE_OUTPUT: { int *iarg = arg; dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n", I2C_NAME(client), *iarg); vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00)); } break; case DECODER_SET_PICTURE: { struct video_picture *pic = arg; if (decoder->bright != pic->brightness) { /* We want -128 to 128 we get 0-65535 */ decoder->bright = pic->brightness; vpx3220_write(client, 0xe6, (decoder->bright - 32768) >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 64 we get 0-65535 */ /* Bit 7 and 8 is for noise shaping */ decoder->contrast = pic->contrast; vpx3220_write(client, 0xe7, (decoder->contrast >> 10) + 192); } if (decoder->sat != pic->colour) { /* We want 0 to 4096 we get 0-65535 */ decoder->sat = pic->colour; vpx3220_fp_write(client, 0xa0, decoder->sat >> 4); }
static int saa7111_command (struct i2c_client *client, unsigned int cmd, void *arg) { struct saa7111 *decoder = i2c_get_clientdata(client); switch (cmd) { case 0: break; case DECODER_INIT: { struct video_decoder_init *init = arg; if (NULL != init) return saa7111_init_decoder(client, init); else { struct video_decoder_init vdi; vdi.data = saa7111_i2c_init; vdi.len = sizeof(saa7111_i2c_init); return saa7111_init_decoder(client, &vdi); } } case DECODER_DUMP: { int i; for (i = 0; i < SAA7111_NR_REG; i += 16) { int j; printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { printk(" %02x", saa7111_read(client, i + j)); } printk("\n"); } } break; case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; cap->inputs = 8; cap->outputs = 1; } break; case DECODER_GET_STATUS: { int *iarg = arg; int status; int res; status = saa7111_read(client, 0x1f); dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), status); res = 0; if ((status & (1 << 6)) == 0) { res |= DECODER_STATUS_GOOD; } switch (decoder->norm) { case VIDEO_MODE_NTSC: res |= DECODER_STATUS_NTSC; break; case VIDEO_MODE_PAL: res |= DECODER_STATUS_PAL; break; case VIDEO_MODE_SECAM: res |= DECODER_STATUS_SECAM; break; default: case VIDEO_MODE_AUTO: if ((status & (1 << 5)) != 0) { res |= DECODER_STATUS_NTSC; } else { res |= DECODER_STATUS_PAL; } break; } if ((status & (1 << 0)) != 0) { res |= DECODER_STATUS_COLOR; } *iarg = res; } break; case DECODER_SET_GPIO: { int *iarg = arg; if (0 != *iarg) { saa7111_write(client, 0x11, (decoder->reg[0x11] | 0x80)); } else { saa7111_write(client, 0x11, (decoder->reg[0x11] & 0x7f)); } break; } case DECODER_SET_VBI_BYPASS: { int *iarg = arg; if (0 != *iarg) { saa7111_write(client, 0x13, (decoder->reg[0x13] & 0xf0) | 0x0a); } else { saa7111_write(client, 0x13, (decoder->reg[0x13] & 0xf0)); } break; } case DECODER_SET_NORM: { int *iarg = arg; switch (*iarg) { case VIDEO_MODE_NTSC: saa7111_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x40); saa7111_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f)); break; case VIDEO_MODE_PAL: saa7111_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x00); saa7111_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f)); break; case VIDEO_MODE_SECAM: saa7111_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x00); saa7111_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f) | 0x50); break; case VIDEO_MODE_AUTO: saa7111_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x80); saa7111_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f)); break; default: return -EINVAL; } decoder->norm = *iarg; } break; case DECODER_SET_INPUT: { int *iarg = arg; if (*iarg < 0 || *iarg > 7) { return -EINVAL; } if (decoder->input != *iarg) { decoder->input = *iarg; /* select mode */ saa7111_write(client, 0x02, (decoder-> reg[0x02] & 0xf8) | decoder->input); /* bypass chrominance trap for modes 4..7 */ saa7111_write(client, 0x09, (decoder-> reg[0x09] & 0x7f) | ((decoder-> input > 3) ? 0x80 : 0)); } } break; case DECODER_SET_OUTPUT: { int *iarg = arg; /* not much choice of outputs */ if (*iarg != 0) { return -EINVAL; } } break; case DECODER_ENABLE_OUTPUT: { int *iarg = arg; int enable = (*iarg != 0); if (decoder->enable != enable) { decoder->enable = enable; /* RJ: If output should be disabled (for * playing videos), we also need a open PLL. * The input is set to 0 (where no input * source is connected), although this * is not necessary. * * If output should be enabled, we have to * reverse the above. */ if (decoder->enable) { saa7111_write(client, 0x02, (decoder-> reg[0x02] & 0xf8) | decoder->input); saa7111_write(client, 0x08, (decoder->reg[0x08] & 0xfb)); saa7111_write(client, 0x11, (decoder-> reg[0x11] & 0xf3) | 0x0c); } else { saa7111_write(client, 0x02, (decoder->reg[0x02] & 0xf8)); saa7111_write(client, 0x08, (decoder-> reg[0x08] & 0xfb) | 0x04); saa7111_write(client, 0x11, (decoder->reg[0x11] & 0xf3)); } } } break; case DECODER_SET_PICTURE: { struct video_picture *pic = arg; /* We want 0 to 255 we get 0-65535 */ saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8); /* We want 0 to 127 we get 0-65535 */ saa7111_write(client, 0x0b, pic->contrast >> 9); /* We want 0 to 127 we get 0-65535 */ saa7111_write(client, 0x0c, pic->colour >> 9); /* We want -128 to 127 we get 0-65535 */ saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); } break; default: return -EINVAL; } return 0; }
static int saa7185_detect_client (struct i2c_adapter *adapter, int address, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) unsigned short flags, #endif int kind) { int i; struct i2c_client *client; struct saa7185 *encoder; dprintk(1, KERN_INFO "saa7185.c: detecting saa7185 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_saa7185; client->flags = I2C_CLIENT_ALLOW_USE; client->id = saa7185_i2c_id++; snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1, "saa7185[%d]", client->id); encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL); if (encoder == NULL) { kfree(client); return -ENOMEM; } memset(encoder, 0, sizeof(struct saa7185)); 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; } i = saa7185_write_block(client, init_common, sizeof(init_common)); if (i >= 0) { i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); } if (i < 0) { dprintk(1, KERN_ERR "%s_attach: init error %d\n", I2C_NAME(client), i); } else { dprintk(1, KERN_INFO "%s_attach: chip version %d at address 0x%x\n", I2C_NAME(client), saa7185_read(client) >> 5, client->addr << 1); } return 0; }
static int saa7110_command (struct i2c_client *client, unsigned int cmd, void *arg) { struct saa7110 *decoder = i2c_get_clientdata(client); int v; switch (cmd) { case 0: //saa7110_write_block(client, initseq, sizeof(initseq)); break; case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *dc = arg; dc->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; dc->inputs = SAA7110_MAX_INPUT; dc->outputs = SAA7110_MAX_OUTPUT; } break; case DECODER_GET_STATUS: { int status; int res = 0; status = saa7110_read(client); dprintk(1, KERN_INFO "%s: status=0x%02x norm=%d\n", I2C_NAME(client), status, decoder->norm); if (!(status & 0x40)) res |= DECODER_STATUS_GOOD; if (status & 0x03) res |= DECODER_STATUS_COLOR; switch (decoder->norm) { case VIDEO_MODE_NTSC: res |= DECODER_STATUS_NTSC; break; case VIDEO_MODE_PAL: res |= DECODER_STATUS_PAL; break; case VIDEO_MODE_SECAM: res |= DECODER_STATUS_SECAM; break; } *(int *) arg = res; } break; case DECODER_SET_NORM: v = *(int *) arg; if (decoder->norm != v) { decoder->norm = v; //saa7110_write(client, 0x06, 0x03); switch (v) { case VIDEO_MODE_NTSC: saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client, 0x2E, 0x81); dprintk(1, KERN_INFO "%s: switched to NTSC\n", I2C_NAME(client)); break; case VIDEO_MODE_PAL: saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); dprintk(1, KERN_INFO "%s: switched to PAL\n", I2C_NAME(client)); break; case VIDEO_MODE_SECAM: saa7110_write(client, 0x0D, 0x87); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); dprintk(1, KERN_INFO "%s: switched to SECAM\n", I2C_NAME(client)); break; case VIDEO_MODE_AUTO: dprintk(1, KERN_INFO "%s: TV standard detection...\n", I2C_NAME(client)); decoder->norm = determine_norm(client); *(int *) arg = decoder->norm; break; default: return -EPERM; } } break; case DECODER_SET_INPUT: v = *(int *) arg; if (v < 0 || v > SAA7110_MAX_INPUT) { dprintk(1, KERN_INFO "%s: input=%d not available\n", I2C_NAME(client), v); return -EINVAL; } if (decoder->input != v) { saa7110_selmux(client, v); dprintk(1, KERN_INFO "%s: switched to input=%d\n", I2C_NAME(client), v); } break; case DECODER_SET_OUTPUT: v = *(int *) arg; /* not much choice of outputs */ if (v != 0) return -EINVAL; break; case DECODER_ENABLE_OUTPUT: v = *(int *) arg; if (decoder->enable != v) { decoder->enable = v; saa7110_write(client, 0x0E, v ? 0x18 : 0x80); dprintk(1, KERN_INFO "%s: YUV %s\n", I2C_NAME(client), v ? "on" : "off"); } break; case DECODER_SET_PICTURE: { struct video_picture *pic = arg; if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ decoder->bright = pic->brightness; saa7110_write(client, 0x19, decoder->bright >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 127 we get 0-65535 */ decoder->contrast = pic->contrast; saa7110_write(client, 0x13, decoder->contrast >> 9); } if (decoder->sat != pic->colour) { /* We want 0 to 127 we get 0-65535 */ decoder->sat = pic->colour; saa7110_write(client, 0x12, decoder->sat >> 9); }
static int determine_norm (struct i2c_client *client) { DEFINE_WAIT(wait); struct saa7110 *decoder = i2c_get_clientdata(client); int status; /* mode changed, start automatic detection */ saa7110_write_block(client, initseq, sizeof(initseq)); saa7110_selmux(client, decoder->input); prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/4); finish_wait(&decoder->wq, &wait); status = saa7110_read(client); if (status & 0x40) { dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n", I2C_NAME(client), status); return decoder->norm; // no change } if ((status & 3) == 0) { saa7110_write(client, 0x06, 0x83); if (status & 0x20) { dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC/no color)\n", I2C_NAME(client), status); //saa7110_write(client,0x2E,0x81); return VIDEO_MODE_NTSC; } dprintk(1, KERN_INFO "%s: status=0x%02x (PAL/no color)\n", I2C_NAME(client), status); //saa7110_write(client,0x2E,0x9A); return VIDEO_MODE_PAL; } //saa7110_write(client,0x06,0x03); if (status & 0x20) { /* 60Hz */ dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC)\n", I2C_NAME(client), status); saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client,0x2E,0x81); return VIDEO_MODE_NTSC; } /* 50Hz -> PAL/SECAM */ saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client,0x2E,0x9A); prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/4); finish_wait(&decoder->wq, &wait); status = saa7110_read(client); if ((status & 0x03) == 0x01) { dprintk(1, KERN_INFO "%s: status=0x%02x (SECAM)\n", I2C_NAME(client), status); saa7110_write(client, 0x0D, 0x87); return VIDEO_MODE_SECAM; } dprintk(1, KERN_INFO "%s: status=0x%02x (PAL)\n", I2C_NAME(client), status); return VIDEO_MODE_PAL; }
static int saa7114_command (struct i2c_client *client, unsigned int cmd, void *arg) { struct saa7114 *decoder = i2c_get_clientdata(client); switch (cmd) { case 0: //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client)); //saa7114_write_block(client, init, sizeof(init)); break; case DECODER_DUMP: { int i; dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client)); for (i = 0; i < 32; i += 16) { int j; printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); for (j = 0; j < 16; ++j) { printk(" %02x", saa7114_read(client, i + j)); } printk("\n"); } } break; case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n", I2C_NAME(client)); cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; cap->inputs = 8; cap->outputs = 1; } break; case DECODER_GET_STATUS: { int *iarg = arg; int status; int res; status = saa7114_read(client, 0x1f); dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), status); res = 0; if ((status & (1 << 6)) == 0) { res |= DECODER_STATUS_GOOD; } switch (decoder->norm) { case VIDEO_MODE_NTSC: res |= DECODER_STATUS_NTSC; break; case VIDEO_MODE_PAL: res |= DECODER_STATUS_PAL; break; case VIDEO_MODE_SECAM: res |= DECODER_STATUS_SECAM; break; default: case VIDEO_MODE_AUTO: if ((status & (1 << 5)) != 0) { res |= DECODER_STATUS_NTSC; } else { res |= DECODER_STATUS_PAL; } break; } if ((status & (1 << 0)) != 0) { res |= DECODER_STATUS_COLOR; } *iarg = res; } break; case DECODER_SET_NORM: { int *iarg = arg; short int hoff = 0, voff = 0, w = 0, h = 0; dprintk(1, KERN_DEBUG "%s: decoder set norm ", I2C_NAME(client)); switch (*iarg) { case VIDEO_MODE_NTSC: dprintk(1, "NTSC\n"); decoder->reg[REG_ADDR(0x06)] = SAA_7114_NTSC_HSYNC_START; decoder->reg[REG_ADDR(0x07)] = SAA_7114_NTSC_HSYNC_STOP; decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture decoder->reg[REG_ADDR(0x0e)] = 0x85; decoder->reg[REG_ADDR(0x0f)] = 0x24; hoff = SAA_7114_NTSC_HOFFSET; voff = SAA_7114_NTSC_VOFFSET; w = SAA_7114_NTSC_WIDTH; h = SAA_7114_NTSC_HEIGHT; break; case VIDEO_MODE_PAL: dprintk(1, "PAL\n"); decoder->reg[REG_ADDR(0x06)] = SAA_7114_PAL_HSYNC_START; decoder->reg[REG_ADDR(0x07)] = SAA_7114_PAL_HSYNC_STOP; decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture decoder->reg[REG_ADDR(0x0e)] = 0x81; decoder->reg[REG_ADDR(0x0f)] = 0x24; hoff = SAA_7114_PAL_HOFFSET; voff = SAA_7114_PAL_VOFFSET; w = SAA_7114_PAL_WIDTH; h = SAA_7114_PAL_HEIGHT; break; default: dprintk(1, " Unknown video mode!!!\n"); return -EINVAL; } decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off saa7114_write(client, 0x88, 0xd8); // sw reset scaler saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write_block(client, decoder->reg + (0x06 << 1), 3 << 1); saa7114_write_block(client, decoder->reg + (0x0e << 1), 2 << 1); saa7114_write_block(client, decoder->reg + (0x5a << 1), 2 << 1); saa7114_write_block(client, decoder->reg + (0x94 << 1), (0x9f + 1 - 0x94) << 1); saa7114_write_block(client, decoder->reg + (0xc4 << 1), (0xcf + 1 - 0xc4) << 1); saa7114_write(client, 0x88, 0xd8); // sw reset scaler saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection decoder->norm = *iarg; } break; case DECODER_SET_INPUT: { int *iarg = arg; dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n", I2C_NAME(client), *iarg); if (*iarg < 0 || *iarg > 7) { return -EINVAL; } if (decoder->input != *iarg) { dprintk(1, KERN_DEBUG "%s: now setting %s input\n", I2C_NAME(client), *iarg >= 6 ? "S-Video" : "Composite"); decoder->input = *iarg; /* select mode */ decoder->reg[REG_ADDR(0x02)] = (decoder-> reg[REG_ADDR(0x02)] & 0xf0) | (decoder-> input < 6 ? 0x0 : 0x9); saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]); /* bypass chrominance trap for modes 6..9 */ decoder->reg[REG_ADDR(0x09)] = (decoder-> reg[REG_ADDR(0x09)] & 0x7f) | (decoder-> input < 6 ? 0x0 : 0x80); saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]); decoder->reg[REG_ADDR(0x0e)] = decoder->input < 6 ? decoder-> reg[REG_ADDR(0x0e)] | 1 : decoder-> reg[REG_ADDR(0x0e)] & ~1; saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]); } } break; case DECODER_SET_OUTPUT: { int *iarg = arg; dprintk(1, KERN_DEBUG "%s: decoder set output\n", I2C_NAME(client)); /* not much choice of outputs */ if (*iarg != 0) { return -EINVAL; } } break; case DECODER_ENABLE_OUTPUT: { int *iarg = arg; int enable = (*iarg != 0); dprintk(1, KERN_DEBUG "%s: decoder %s output\n", I2C_NAME(client), enable ? "enable" : "disable"); decoder->playback = !enable; if (decoder->enable != enable) { decoder->enable = enable; /* RJ: If output should be disabled (for * playing videos), we also need a open PLL. * The input is set to 0 (where no input * source is connected), although this * is not necessary. * * If output should be enabled, we have to * reverse the above. */ if (decoder->enable) { decoder->reg[REG_ADDR(0x08)] = 0xb8; decoder->reg[REG_ADDR(0x12)] = 0xc9; decoder->reg[REG_ADDR(0x13)] = 0x80; decoder->reg[REG_ADDR(0x87)] = 0x01; } else { decoder->reg[REG_ADDR(0x08)] = 0x7c; decoder->reg[REG_ADDR(0x12)] = 0x00; decoder->reg[REG_ADDR(0x13)] = 0x00; decoder->reg[REG_ADDR(0x87)] = 0x00; } saa7114_write_block(client, decoder->reg + (0x12 << 1), 2 << 1); saa7114_write(client, 0x08, decoder->reg[REG_ADDR(0x08)]); saa7114_write(client, 0x87, decoder->reg[REG_ADDR(0x87)]); saa7114_write(client, 0x88, 0xd8); // sw reset scaler saa7114_write(client, 0x88, 0xf8); // sw reset scaler release saa7114_write(client, 0x80, 0x36); } } break; case DECODER_SET_PICTURE: { struct video_picture *pic = arg; dprintk(1, KERN_DEBUG "%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n", I2C_NAME(client), pic->brightness, pic->contrast, pic->colour, pic->hue); if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ decoder->bright = pic->brightness; saa7114_write(client, 0x0a, decoder->bright >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 127 we get 0-65535 */ decoder->contrast = pic->contrast; saa7114_write(client, 0x0b, decoder->contrast >> 9); } if (decoder->sat != pic->colour) { /* We want 0 to 127 we get 0-65535 */ decoder->sat = pic->colour; saa7114_write(client, 0x0c, decoder->sat >> 9); }