📄 tda9887.c
字号:
: "pin3+pin22 port"); } printk("--\n");}/* ---------------------------------------------------------------------- */static int tda9887_set_tvnorm(struct tda9887 *t, char *buf){ struct tvnorm *norm = NULL; int i; if (t->radio) { norm = &radio; } else { for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { if (tvnorms[i].std & t->std) { norm = tvnorms+i; break; } } } if (NULL == norm) { dprintk(PREFIX "Oops: no tvnorm entry found\n"); return -1; } dprintk(PREFIX "configure for: %s\n",norm->name); buf[1] = norm->b; buf[2] = norm->c; buf[3] = norm->e; return 0;}static unsigned int port1 = 1;static unsigned int port2 = 1;static unsigned int qss = 0;static unsigned int adjust = 0x10;MODULE_PARM(port1,"i");MODULE_PARM(port2,"i");MODULE_PARM(qss,"i");MODULE_PARM(adjust,"i");static int tda9887_set_insmod(struct tda9887 *t, char *buf){ if (port1) buf[1] |= cOutputPort1Inactive; if (port2) buf[1] |= cOutputPort2Inactive; if (qss) buf[1] |= cQSS; if (adjust >= 0x00 && adjust < 0x20) buf[2] |= adjust;}/* ---------------------------------------------------------------------- */static int tda9887_set_pinnacle(struct tda9887 *t, char *buf){ unsigned int bCarrierMode = UNSET; if (t->std & V4L2_STD_PAL) { if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { bCarrierMode = cQSS; } } if (t->std & V4L2_STD_NTSC) { if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { bCarrierMode = cQSS; } } if (bCarrierMode != UNSET) { buf[1] &= ~0x04; buf[1] |= bCarrierMode; } return 0;}/* ---------------------------------------------------------------------- */static char *pal = "-";MODULE_PARM(pal,"s");static char *secam = "-";MODULE_PARM(secam,"s");static int tda9887_fixup_std(struct tda9887 *t){ /* get more precise norm info from insmod option */ if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { switch (pal[0]) { case 'b': case 'B': case 'g': case 'G': dprintk(PREFIX "insmod fixup: PAL => PAL-BG\n"); t->std = V4L2_STD_PAL_BG; break; case 'i': case 'I': dprintk(PREFIX "insmod fixup: PAL => PAL-I\n"); t->std = V4L2_STD_PAL_I; break; case 'd': case 'D': case 'k': case 'K': dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n"); t->std = V4L2_STD_PAL_DK; break; } } if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { switch (secam[0]) { case 'd': case 'D': case 'k': case 'K': dprintk(PREFIX "insmod fixup: SECAM => SECAM-DK\n"); t->std = V4L2_STD_SECAM_DK; break; case 'l': case 'L': dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n"); t->std = V4L2_STD_SECAM_L; break; } } return 0;}static int tda9887_configure(struct tda9887 *t){ unsigned char buf[4]; int rc; memset(buf,0,sizeof(buf)); tda9887_set_tvnorm(t,buf); if (UNSET != t->pinnacle_id) { tda9887_set_pinnacle(t,buf); } tda9887_set_insmod(t,buf); dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n", buf[1],buf[2],buf[3]); if (debug > 1) dump_write_message(buf); if (4 != (rc = i2c_master_send(&t->client,buf,4))) printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc); return 0;}static int tda9887_status(struct tda9887 *t){ unsigned char buf[1]; int rc; memset(buf,0,sizeof(buf)); if (1 != (rc = i2c_master_recv(&t->client,buf,1))) printk(PREFIX "i2c i/o error: rc == %d (should be 1)\n",rc); dump_read_message(buf);}/* ---------------------------------------------------------------------- */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)#elsestatic int tda9887_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)#endif{ struct tda9887 *t; client_template.adapter = adap; client_template.addr = addr; printk(PREFIX "chip found @ 0x%x\n", addr<<1); if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; t->std = 0;; t->pinnacle_id = UNSET; i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT;#endif return 0;}static int tda9887_probe(struct i2c_adapter *adap){#ifdef I2C_ADAP_CLASS_TV_ANALOG if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9887_attach);#else switch (adap->id) { case I2C_ALGO_BIT | I2C_HW_B_BT848: case I2C_ALGO_BIT | I2C_HW_B_RIVA: case I2C_ALGO_SAA7134: return i2c_probe(adap, &addr_data, tda9887_attach); break; }#endif return 0;}static int tda9887_detach(struct i2c_client *client){ struct tda9887 *t = i2c_get_clientdata(client); i2c_detach_client(client); kfree(t);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT;#endif return 0;}static inttda9887_command(struct i2c_client *client, unsigned int cmd, void *arg){ struct tda9887 *t = i2c_get_clientdata(client); switch (cmd) { /* --- configuration --- */ case AUDC_SET_RADIO: t->radio = 1; tda9887_configure(t); break; case AUDC_CONFIG_PINNACLE: { int *i = arg; t->pinnacle_id = *i; tda9887_configure(t); break; } /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ case VIDIOCSCHAN: { static const v4l2_std_id map[] = { [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, [ 4 /* bttv */ ] = V4L2_STD_PAL_M, [ 5 /* bttv */ ] = V4L2_STD_PAL_N, [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, }; struct video_channel *vc = arg; t->radio = 0; if (vc->norm < ARRAY_SIZE(map)) t->std = map[vc->norm]; tda9887_fixup_std(t); tda9887_configure(t); if (debug > 2) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); tda9887_status(t); } break; } case VIDIOC_S_STD: { v4l2_std_id *id = arg; t->radio = 0; t->std = *id; tda9887_fixup_std(t); tda9887_configure(t); break; } default: /* nothing */ break; } return 0;}/* ----------------------------------------------------------------------- */static struct i2c_driver driver = {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,54) .owner = THIS_MODULE,#endif .name = "i2c tda9887 driver", .id = -1, /* FIXME */ .flags = I2C_DF_NOTIFY, .attach_adapter = tda9887_probe, .detach_client = tda9887_detach, .command = tda9887_command,};static struct i2c_client client_template ={ I2C_DEVNAME("tda9887"), .flags = I2C_CLIENT_ALLOW_USE, .driver = &driver,};static int tda9887_init_module(void){ i2c_add_driver(&driver); return 0;}static void tda9887_cleanup_module(void){ i2c_del_driver(&driver);}module_init(tda9887_init_module);module_exit(tda9887_cleanup_module);/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -