📄 saa7191.c
字号:
return saa7191_set_norm(client, SAA7191_NORM_PAL); }}static int saa7191_get_control(struct i2c_client *client, struct saa7191_control *ctrl){ u8 reg; int ret = 0; switch (ctrl->type) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: reg = saa7191_read_reg(client, SAA7191_REG_LUMA); switch (ctrl->type) { case SAA7191_CONTROL_BANDPASS: ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) >> SAA7191_LUMA_BPSS_SHIFT; break; case SAA7191_CONTROL_BANDPASS_WEIGHT: ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK) >> SAA7191_LUMA_APER_SHIFT; break; case SAA7191_CONTROL_CORING: ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK) >> SAA7191_LUMA_CORI_SHIFT; break; } break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: reg = saa7191_read_reg(client, SAA7191_REG_GAIN); if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; else ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) >> SAA7191_GAIN_LFIS_SHIFT; break; case SAA7191_CONTROL_HUE: reg = saa7191_read_reg(client, SAA7191_REG_HUEC); if (reg < 0x80) reg += 0x80; else reg -= 0x80; ctrl->value = (s32)reg; break; case SAA7191_CONTROL_VTRC: reg = saa7191_read_reg(client, SAA7191_REG_STDC); ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; break; case SAA7191_CONTROL_LUMA_DELAY: reg = saa7191_read_reg(client, SAA7191_REG_CTL3); ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) >> SAA7191_CTL3_YDEL_SHIFT; if (ctrl->value >= 4) ctrl->value -= 8; break; case SAA7191_CONTROL_VNR: reg = saa7191_read_reg(client, SAA7191_REG_CTL4); ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) >> SAA7191_CTL4_VNOI_SHIFT; break; default: ret = -EINVAL; } return ret;}static int saa7191_set_control(struct i2c_client *client, struct saa7191_control *ctrl){ u8 reg; int ret = 0; switch (ctrl->type) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: reg = saa7191_read_reg(client, SAA7191_REG_LUMA); switch (ctrl->type) { case SAA7191_CONTROL_BANDPASS: reg &= ~SAA7191_LUMA_BPSS_MASK; reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) & SAA7191_LUMA_BPSS_MASK; break; case SAA7191_CONTROL_BANDPASS_WEIGHT: reg &= ~SAA7191_LUMA_APER_MASK; reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT) & SAA7191_LUMA_APER_MASK; break; case SAA7191_CONTROL_CORING: reg &= ~SAA7191_LUMA_CORI_MASK; reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT) & SAA7191_LUMA_CORI_MASK; break; } ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg); break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: reg = saa7191_read_reg(client, SAA7191_REG_GAIN); if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) { if (ctrl->value) reg |= SAA7191_GAIN_COLO; else reg &= ~SAA7191_GAIN_COLO; } else { reg &= ~SAA7191_GAIN_LFIS_MASK; reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) & SAA7191_GAIN_LFIS_MASK; } ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); break; case SAA7191_CONTROL_HUE: reg = ctrl->value & 0xff; if (reg < 0x80) reg += 0x80; else reg -= 0x80; ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg); break; case SAA7191_CONTROL_VTRC: reg = saa7191_read_reg(client, SAA7191_REG_STDC); if (ctrl->value) reg |= SAA7191_STDC_VTRC; else reg &= ~SAA7191_STDC_VTRC; ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg); break; case SAA7191_CONTROL_LUMA_DELAY: { s32 value = ctrl->value; if (value < 0) value += 8; reg = saa7191_read_reg(client, SAA7191_REG_CTL3); reg &= ~SAA7191_CTL3_YDEL_MASK; reg |= (value << SAA7191_CTL3_YDEL_SHIFT) & SAA7191_CTL3_YDEL_MASK; ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg); break; } case SAA7191_CONTROL_VNR: reg = saa7191_read_reg(client, SAA7191_REG_CTL4); reg &= ~SAA7191_CTL4_VNOI_MASK; reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) & SAA7191_CTL4_VNOI_MASK; ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg); break; default: ret = -EINVAL; } return ret;}/* I2C-interface */static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind){ int err = 0; struct saa7191 *decoder; struct i2c_client *client; printk(KERN_INFO "Philips SAA7191 driver version %s\n", SAA7191_MODULE_VERSION); client = kmalloc(sizeof(*client), GFP_KERNEL); if (!client) return -ENOMEM; decoder = kmalloc(sizeof(*decoder), GFP_KERNEL); if (!decoder) { err = -ENOMEM; goto out_free_client; } memset(client, 0, sizeof(struct i2c_client)); memset(decoder, 0, sizeof(struct saa7191)); client->addr = addr; client->adapter = adap; client->driver = &i2c_driver_saa7191; client->flags = 0; strcpy(client->name, "saa7191 client"); i2c_set_clientdata(client, decoder); decoder->client = client; err = i2c_attach_client(client); if (err) goto out_free_decoder; err = saa7191_write_block(client, sizeof(initseq), (u8 *)initseq); if (err) { printk(KERN_ERR "SAA7191 initialization failed\n"); goto out_detach_client; } printk(KERN_INFO "SAA7191 initialized\n"); decoder->input = SAA7191_INPUT_COMPOSITE; decoder->norm = SAA7191_NORM_PAL; err = saa7191_autodetect_norm(client); if (err && (err != -EBUSY)) { printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); } return 0;out_detach_client: i2c_detach_client(client);out_free_decoder: kfree(decoder);out_free_client: kfree(client); return err;}static int saa7191_probe(struct i2c_adapter *adap){ /* Always connected to VINO */ if (adap->id == I2C_HW_SGI_VINO) return saa7191_attach(adap, SAA7191_ADDR, 0); /* Feel free to add probe here :-) */ return -ENODEV;}static int saa7191_detach(struct i2c_client *client){ struct saa7191 *decoder = i2c_get_clientdata(client); i2c_detach_client(client); kfree(decoder); kfree(client); return 0;}static int saa7191_command(struct i2c_client *client, unsigned int cmd, void *arg){ struct saa7191 *decoder = i2c_get_clientdata(client); switch (cmd) { case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1; cap->outputs = 1; break; } case DECODER_GET_STATUS: { int *iarg = arg; u8 status; int res = 0; if (saa7191_read_status(client, &status)) { return -EIO; } if ((status & SAA7191_STATUS_HLCK) == 0) res |= DECODER_STATUS_GOOD; if (status & SAA7191_STATUS_CODE) res |= DECODER_STATUS_COLOR; switch (decoder->norm) { case SAA7191_NORM_NTSC: res |= DECODER_STATUS_NTSC; break; case SAA7191_NORM_PAL: res |= DECODER_STATUS_PAL; break; case SAA7191_NORM_SECAM: res |= DECODER_STATUS_SECAM; break; case SAA7191_NORM_AUTO: default: if (status & SAA7191_STATUS_FIDT) res |= DECODER_STATUS_NTSC; else res |= DECODER_STATUS_PAL; break; } *iarg = res; break; } case DECODER_SET_NORM: { int *iarg = arg; switch (*iarg) { case VIDEO_MODE_AUTO: return saa7191_autodetect_norm(client); case VIDEO_MODE_PAL: return saa7191_set_norm(client, SAA7191_NORM_PAL); case VIDEO_MODE_NTSC: return saa7191_set_norm(client, SAA7191_NORM_NTSC); case VIDEO_MODE_SECAM: return saa7191_set_norm(client, SAA7191_NORM_SECAM); default: return -EINVAL; } break; } case DECODER_SET_INPUT: { int *iarg = arg; switch (client->adapter->id) { case I2C_HW_SGI_VINO: return saa7191_set_input(client, *iarg); default: if (*iarg != 0) return -EINVAL; } break; } case DECODER_SET_OUTPUT: { int *iarg = arg; /* not much choice of outputs */ if (*iarg != 0) return -EINVAL; break; } case DECODER_ENABLE_OUTPUT: { /* Always enabled */ break; } case DECODER_SET_PICTURE: { struct video_picture *pic = arg; unsigned val; int err; val = (pic->hue >> 8) - 0x80; err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); if (err) return -EIO; break; } case DECODER_SAA7191_GET_STATUS: { struct saa7191_status *status = arg; u8 status_reg; if (saa7191_read_status(client, &status_reg)) return -EIO; status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) ? 1 : 0; status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT) ? 1 : 0; status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0; status->input = decoder->input; status->norm = decoder->norm; break; } case DECODER_SAA7191_SET_NORM: { int *norm = arg; switch (*norm) { case SAA7191_NORM_AUTO: return saa7191_autodetect_norm(client); case SAA7191_NORM_AUTO_EXT: return saa7191_autodetect_norm_extended(client); default: return saa7191_set_norm(client, *norm); } } case DECODER_SAA7191_GET_CONTROL: { return saa7191_get_control(client, arg); } case DECODER_SAA7191_SET_CONTROL: { return saa7191_set_control(client, arg); } default: return -EINVAL; } return 0;}static struct i2c_driver i2c_driver_saa7191 = { .owner = THIS_MODULE, .name = "saa7191", .id = I2C_DRIVERID_SAA7191, .flags = I2C_DF_NOTIFY, .attach_adapter = saa7191_probe, .detach_client = saa7191_detach, .command = saa7191_command};static int saa7191_init(void){ return i2c_add_driver(&i2c_driver_saa7191);}static void saa7191_exit(void){ i2c_del_driver(&i2c_driver_saa7191);}module_init(saa7191_init);module_exit(saa7191_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -