📄 cx25840-core.c
字号:
} case 0x2: return V4L2_STD_NTSC_M_JP; case 0x3: return V4L2_STD_NTSC_443; case 0x4: return V4L2_STD_PAL; case 0x5: return V4L2_STD_PAL_M; case 0x6: return V4L2_STD_PAL_N; case 0x7: return V4L2_STD_PAL_Nc; case 0x8: return V4L2_STD_PAL_60; case 0xc: return V4L2_STD_SECAM; default: return V4L2_STD_UNKNOWN; }}/* ----------------------------------------------------------------------- */static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl){ struct cx25840_state *state = i2c_get_clientdata(client); switch (ctrl->id) { case CX25840_CID_ENABLE_PVR150_WORKAROUND: state->pvr150_workaround = ctrl->value; set_input(client, state->vid_input, state->aud_input); break; case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { v4l_err(client, "invalid brightness setting %d\n", ctrl->value); return -ERANGE; } cx25840_write(client, 0x414, ctrl->value - 128); break; case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 127) { v4l_err(client, "invalid contrast setting %d\n", ctrl->value); return -ERANGE; } cx25840_write(client, 0x415, ctrl->value << 1); break; case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 127) { v4l_err(client, "invalid saturation setting %d\n", ctrl->value); return -ERANGE; } cx25840_write(client, 0x420, ctrl->value << 1); cx25840_write(client, 0x421, ctrl->value << 1); break; case V4L2_CID_HUE: if (ctrl->value < -127 || ctrl->value > 127) { v4l_err(client, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } cx25840_write(client, 0x422, ctrl->value); break; case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); default: return -EINVAL; } return 0;}static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl){ struct cx25840_state *state = i2c_get_clientdata(client); switch (ctrl->id) { case CX25840_CID_ENABLE_PVR150_WORKAROUND: ctrl->value = state->pvr150_workaround; break; case V4L2_CID_BRIGHTNESS: ctrl->value = (s8)cx25840_read(client, 0x414) + 128; break; case V4L2_CID_CONTRAST: ctrl->value = cx25840_read(client, 0x415) >> 1; break; case V4L2_CID_SATURATION: ctrl->value = cx25840_read(client, 0x420) >> 1; break; case V4L2_CID_HUE: ctrl->value = (s8)cx25840_read(client, 0x422); break; case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); default: return -EINVAL; } return 0;}/* ----------------------------------------------------------------------- */static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt){ switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return cx25840_vbi(client, VIDIOC_G_FMT, fmt); default: return -EINVAL; } return 0;}static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt){ struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: pix = &(fmt->fmt.pix); Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; Vlines = pix->height + (is_pal ? 4 : 7); if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { v4l_err(client, "%dx%d is not a valid size!\n", pix->width, pix->height); return -ERANGE; } HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); VSC &= 0x1fff; if (pix->width >= 385) filter = 0; else if (pix->width > 192) filter = 1; else if (pix->width > 96) filter = 2; else filter = 3; v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n", pix->width, pix->height, HSC, VSC); /* HSCALE=HSC */ cx25840_write(client, 0x418, HSC & 0xff); cx25840_write(client, 0x419, (HSC >> 8) & 0xff); cx25840_write(client, 0x41a, HSC >> 16); /* VSCALE=VSC */ cx25840_write(client, 0x41c, VSC & 0xff); cx25840_write(client, 0x41d, VSC >> 8); /* VS_INTRLACE=1 VFILT=filter */ cx25840_write(client, 0x41e, 0x8 | filter); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return cx25840_vbi(client, VIDIOC_S_FMT, fmt); case V4L2_BUF_TYPE_VBI_CAPTURE: return cx25840_vbi(client, VIDIOC_S_FMT, fmt); default: return -EINVAL; } return 0;}/* ----------------------------------------------------------------------- */static struct v4l2_queryctrl cx25840_qctrl[] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 0, .maximum = 255, .step = 1, .default_value = 128, .flags = 0, }, { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, .maximum = 127, .step = 1, .default_value = 64, .flags = 0, }, { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .minimum = 0, .maximum = 127, .step = 1, .default_value = 64, .flags = 0, }, { .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Hue", .minimum = -128, .maximum = 127, .step = 1, .default_value = 0, .flags = 0, }, { .id = V4L2_CID_AUDIO_VOLUME, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Volume", .minimum = 0, .maximum = 65535, .step = 65535/100, .default_value = 58880, .flags = 0, }, { .id = V4L2_CID_AUDIO_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Balance", .minimum = 0, .maximum = 65535, .step = 65535/100, .default_value = 32768, .flags = 0, }, { .id = V4L2_CID_AUDIO_MUTE, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Mute", .minimum = 0, .maximum = 1, .step = 1, .default_value = 1, .flags = 0, }, { .id = V4L2_CID_AUDIO_BASS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Bass", .minimum = 0, .maximum = 65535, .step = 65535/100, .default_value = 32768, }, { .id = V4L2_CID_AUDIO_TREBLE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Treble", .minimum = 0, .maximum = 65535, .step = 65535/100, .default_value = 32768, },};/* ----------------------------------------------------------------------- */static int cx25840_command(struct i2c_client *client, unsigned int cmd, void *arg){ struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_tuner *vt = arg; struct v4l2_routing *route = arg; switch (cmd) {#ifdef CONFIG_VIDEO_ADV_DEBUG /* ioctls to allow direct access to the * cx25840 registers for testing */ case VIDIOC_INT_G_REGISTER: { struct v4l2_register *reg = arg; if (reg->i2c_id != I2C_DRIVERID_CX25840) return -EINVAL; reg->val = cx25840_read(client, reg->reg & 0x0fff); break; } case VIDIOC_INT_S_REGISTER: { struct v4l2_register *reg = arg; if (reg->i2c_id != I2C_DRIVERID_CX25840) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); break; }#endif case VIDIOC_INT_DECODE_VBI_LINE: return cx25840_vbi(client, cmd, arg); case VIDIOC_INT_AUDIO_CLOCK_FREQ: return cx25840_audio(client, cmd, arg); case VIDIOC_STREAMON: v4l_dbg(1, cx25840_debug, client, "enable output\n"); cx25840_write(client, 0x115, 0x8c); cx25840_write(client, 0x116, 0x07); break; case VIDIOC_STREAMOFF: v4l_dbg(1, cx25840_debug, client, "disable output\n"); cx25840_write(client, 0x115, 0x00); cx25840_write(client, 0x116, 0x00); break; case VIDIOC_LOG_STATUS: log_status(client); break; case VIDIOC_G_CTRL: return get_v4lctrl(client, (struct v4l2_control *)arg); case VIDIOC_S_CTRL: return set_v4lctrl(client, (struct v4l2_control *)arg); case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; int i; for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++) if (qc->id && qc->id == cx25840_qctrl[i].id) { memcpy(qc, &cx25840_qctrl[i], sizeof(*qc)); return 0; } return -EINVAL; } case VIDIOC_G_STD: *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); break; case VIDIOC_S_STD: state->radio = 0; return set_v4lstd(client, *(v4l2_std_id *)arg); case AUDC_SET_RADIO: state->radio = 1; break; case VIDIOC_INT_G_VIDEO_ROUTING: route->input = state->vid_input; route->output = 0; break; case VIDIOC_INT_S_VIDEO_ROUTING: return set_input(client, route->input, state->aud_input); case VIDIOC_INT_G_AUDIO_ROUTING: route->input = state->aud_input; route->output = 0; break; case VIDIOC_INT_S_AUDIO_ROUTING: return set_input(client, state->vid_input, route->input); case VIDIOC_S_FREQUENCY: input_change(client); break; case VIDIOC_G_TUNER: { u8 mode = cx25840_read(client, 0x804);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -