static int s2250_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct s2250 *dec = i2c_get_clientdata(client); switch (cmd) { case VIDIOC_S_INPUT: { int vidsys; int *input = arg; vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00; if (*input == 0) { /* composite */ write_reg_fp(client, 0x20, 0x020 | vidsys); write_reg_fp(client, 0x21, 0x662); write_reg_fp(client, 0x140, 0x060); } else { /* S-Video */ write_reg_fp(client, 0x20, 0x040 | vidsys); write_reg_fp(client, 0x21, 0x666); write_reg_fp(client, 0x140, 0x060); } dec->input = *input; break; } case VIDIOC_S_STD: { v4l2_std_id *std = arg; u16 vidsource; vidsource = (dec->input == 1) ? 0x040 : 0x020; dec->std = *std; switch (dec->std) { case V4L2_STD_NTSC: write_regs_fp(client, vid_regs_fp); write_reg_fp(client, 0x20, vidsource | 1); break; case V4L2_STD_PAL: write_regs_fp(client, vid_regs_fp); write_regs_fp(client, vid_regs_fp_pal); write_reg_fp(client, 0x20, vidsource); break; default: return -EINVAL; } break; } case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *ctrl = arg; static const u32 user_ctrls[] = { V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_SATURATION, V4L2_CID_HUE, 0 }; static const u32 *ctrl_classes[] = { user_ctrls, NULL }; ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); break; case V4L2_CID_CONTRAST: v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); break; case V4L2_CID_SATURATION: v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); break; case V4L2_CID_HUE: v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0); break; default: ctrl->name[0] = '\0'; return -EINVAL; } break; } case VIDIOC_S_CTRL: { struct v4l2_control *ctrl = arg; int value1; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: printk(KERN_INFO "s2250: future setting\n"); return -EINVAL; case V4L2_CID_CONTRAST: printk(KERN_INFO "s2250: future setting\n"); return -EINVAL; break; case V4L2_CID_SATURATION: if (ctrl->value > 127) dec->saturation = 127; else if (ctrl->value < 0) dec->saturation = 0; else dec->saturation = ctrl->value; value1 = dec->saturation * 4140 / 100; if (value1 > 4094) value1 = 4094; write_reg_fp(client, VPX322_ADDR_SAT, value1); break; case V4L2_CID_HUE: if (ctrl->value > 50) dec->hue = 50; else if (ctrl->value < -50) dec->hue = -50; else dec->hue = ctrl->value; /* clamp the hue range */ value1 = dec->hue * 280 / 50; write_reg_fp(client, VPX322_ADDR_HUE, value1); break; } break; } case VIDIOC_G_CTRL: { struct v4l2_control *ctrl = arg; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = dec->brightness; break; case V4L2_CID_CONTRAST: ctrl->value = dec->contrast; break; case V4L2_CID_SATURATION: ctrl->value = dec->saturation; break; case V4L2_CID_HUE: ctrl->value = dec->hue; break; } break; } case VIDIOC_S_FMT: { struct v4l2_format *fmt = arg; if (fmt->fmt.pix.height < 640) { write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400); write_reg_fp(client, 0x140, 0x060); } else { write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400); write_reg_fp(client, 0x140, 0x060); } return 0; } case VIDIOC_G_AUDIO: { struct v4l2_audio *audio = arg; memset(audio, 0, sizeof(*audio)); audio->index = dec->audio_input; /* fall through */ } case VIDIOC_ENUMAUDIO: { struct v4l2_audio *audio = arg; switch (audio->index) { case 0: strcpy(audio->name, "Line In"); break; case 1: strcpy(audio->name, "Mic"); break; case 2: strcpy(audio->name, "Mic Boost"); break; default: audio->name[0] = '\0'; return 0; } audio->capability = V4L2_AUDCAP_STEREO; audio->mode = 0; return 0; } case VIDIOC_S_AUDIO: { struct v4l2_audio *audio = arg; client->addr = TLV320_ADDRESS; switch (audio->index) { case 0: write_reg(client, 0x08, 0x02); /* Line In */ break; case 1: write_reg(client, 0x08, 0x04); /* Mic */ break; case 2: write_reg(client, 0x08, 0x05); /* Mic Boost */ break; default: return -EINVAL; } dec->audio_input = audio->index; return 0; } default: printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd); break; } return 0; }
static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind) { struct i2c_client *client; struct s2250 *dec; u8 *data; struct go7007 *go = i2c_get_adapdata(adapter); struct go7007_usb *usb = go->hpi_context; client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == NULL) return -ENOMEM; memcpy(client, &s2250_client_templ, sizeof(s2250_client_templ)); client->adapter = adapter; dec = kmalloc(sizeof(struct s2250), GFP_KERNEL); if (dec == NULL) { kfree(client); return -ENOMEM; } dec->std = V4L2_STD_NTSC; dec->brightness = 50; dec->contrast = 50; dec->saturation = 50; dec->hue = 0; client->addr = TLV320_ADDRESS; i2c_set_clientdata(client, dec); printk(KERN_DEBUG "s2250: initializing video decoder on %s\n", adapter->name); /* initialize the audio */ client->addr = TLV320_ADDRESS; if (write_regs(client, aud_regs) < 0) { printk(KERN_ERR "s2250: error initializing audio\n"); kfree(client); kfree(dec); return 0; } client->addr = S2250_VIDDEC; i2c_set_clientdata(client, dec); if (write_regs(client, vid_regs) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); kfree(client); kfree(dec); return 0; } if (write_regs_fp(client, vid_regs_fp) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); kfree(client); kfree(dec); return 0; } /* set default channel */ /* composite */ write_reg_fp(client, 0x20, 0x020 | 1); write_reg_fp(client, 0x21, 0x662); write_reg_fp(client, 0x140, 0x060); /* set default audio input */ dec->audio_input = 0; write_reg(client, 0x08, 0x02); /* Line In */ if (down_interruptible(&usb->i2c_lock) == 0) { data = kzalloc(16, GFP_KERNEL); if (data != NULL) { int rc; rc = go7007_usb_vendor_request(go, 0x41, 0, 0, data, 16, 1); if (rc > 0) { u8 mask; data[0] = 0; mask = 1<<5; data[0] &= ~mask; data[1] |= mask; go7007_usb_vendor_request(go, 0x40, 0, (data[1]<<8) + data[1], data, 16, 0); } kfree(data); } up(&usb->i2c_lock); } i2c_attach_client(client); printk("s2250: initialized successfully\n"); return 0; }
static int s2250_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_client *audio; struct i2c_adapter *adapter = client->adapter; struct s2250 *dec; u8 *data; struct go7007 *go = i2c_get_adapdata(adapter); struct go7007_usb *usb = go->hpi_context; audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1); if (audio == NULL) return -ENOMEM; dec = kmalloc(sizeof(struct s2250), GFP_KERNEL); if (dec == NULL) { i2c_unregister_device(audio); return -ENOMEM; } dec->std = V4L2_STD_NTSC; dec->brightness = 50; dec->contrast = 50; dec->saturation = 50; dec->hue = 0; dec->audio = audio; i2c_set_clientdata(client, dec); printk(KERN_DEBUG "s2250: initializing video decoder on %s\n", adapter->name); /* initialize the audio */ if (write_regs(audio, aud_regs) < 0) { printk(KERN_ERR "s2250: error initializing audio\n"); i2c_unregister_device(audio); kfree(dec); return 0; } if (write_regs(client, vid_regs) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); i2c_unregister_device(audio); kfree(dec); return 0; } if (write_regs_fp(client, vid_regs_fp) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); i2c_unregister_device(audio); kfree(dec); return 0; } /* set default channel */ /* composite */ write_reg_fp(client, 0x20, 0x020 | 1); write_reg_fp(client, 0x21, 0x662); write_reg_fp(client, 0x140, 0x060); /* set default audio input */ dec->audio_input = 0; write_reg(client, 0x08, 0x02); /* Line In */ if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { data = kzalloc(16, GFP_KERNEL); if (data != NULL) { int rc; rc = go7007_usb_vendor_request(go, 0x41, 0, 0, data, 16, 1); if (rc > 0) { u8 mask; data[0] = 0; mask = 1<<5; data[0] &= ~mask; data[1] |= mask; go7007_usb_vendor_request(go, 0x40, 0, (data[1]<<8) + data[1], data, 16, 0); } kfree(data); } mutex_unlock(&usb->i2c_lock); } printk("s2250: initialized successfully\n"); return 0; }