diff options
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r-- | drivers/media/video/ivtv/Kconfig | 3 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-cards.c | 5 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-cards.h | 4 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 28 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 4 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-i2c.c | 43 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.c | 115 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.h | 5 |
8 files changed, 151 insertions, 56 deletions
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index be4af1fa557e..89f65914cc8e 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,9 +1,8 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" depends on VIDEO_V4L2 && PCI && I2C - depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT - depends on VIDEO_IR + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 87afbbee2063..145e4749a69d 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -405,7 +405,8 @@ static const struct ivtv_card ivtv_card_avc2410 = { .hw_audio_ctrl = IVTV_HW_MSP34XX, .hw_muxer = IVTV_HW_CS53L32A, .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A | - IVTV_HW_SAA7115 | IVTV_HW_TUNER, + IVTV_HW_SAA7115 | IVTV_HW_TUNER | + IVTV_HW_I2C_IR_RX_ADAPTEC, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, @@ -1313,7 +1314,6 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input) "Composite 3" }; - memset(input, 0, sizeof(*input)); if (index >= itv->nof_inputs) return -EINVAL; input->index = index; @@ -1331,7 +1331,6 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output) { const struct ivtv_card_output *card_output = itv->card->video_outputs + index; - memset(output, 0, sizeof(*output)); if (index >= itv->card->nof_outputs) return -EINVAL; output->index = index; diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 78eca992e1fd..e6f5c02981f1 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -111,6 +111,7 @@ #define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) #define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) #define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) +#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 21) #define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ IVTV_HW_Z8F0811_IR_TX_HAUP) @@ -120,7 +121,8 @@ #define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ IVTV_HW_I2C_IR_RX_HAUP_EXT | \ IVTV_HW_I2C_IR_RX_HAUP_INT | \ - IVTV_HW_Z8F0811_IR_RX_HAUP) + IVTV_HW_Z8F0811_IR_RX_HAUP | \ + IVTV_HW_I2C_IR_RX_ADAPTEC) #define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e421d15b0f5c..39946420b301 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1029,8 +1029,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); if (!itv->enc_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " + "encoder memory\n"); + IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of " + "vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } @@ -1041,8 +1046,14 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); if (!itv->dec_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into " + "CX23415 decoder memory\n"); + IVTV_ERR("Each capture card with a CX23415 needs 8 MB " + "of vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc " + "/proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option " + "to set VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } @@ -1057,8 +1068,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->reg_mem = ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); if (!itv->reg_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " + "register space\n"); + IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of " + "vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_io; } diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index d727485da886..c57a58523ca8 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -570,8 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c int elems = count / sizeof(struct v4l2_sliced_vbi_data); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems); - return elems * sizeof(struct v4l2_sliced_vbi_data); + return ivtv_write_vbi_from_user(itv, + (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); } mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 665191c9b407..e103b8fc7452 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -94,6 +94,7 @@ #define IVTV_HAUP_INT_IR_RX_I2C_ADDR 0x18 #define IVTV_Z8F0811_IR_TX_I2C_ADDR 0x70 #define IVTV_Z8F0811_IR_RX_I2C_ADDR 0x71 +#define IVTV_ADAPTEC_IR_ADDR 0x6b /* This array should match the IVTV_HW_ defines */ static const u8 hw_addrs[] = { @@ -118,6 +119,7 @@ static const u8 hw_addrs[] = { IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + IVTV_ADAPTEC_IR_ADDR, /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; /* This array should match the IVTV_HW_ defines */ @@ -143,8 +145,34 @@ static const char * const hw_devicenames[] = { "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + "ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; +static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char keybuf[4]; + + keybuf[0] = 0x00; + i2c_master_send(ir->c, keybuf, 1); + /* poll IR chip */ + if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { + return 0; + } + + /* key pressed ? */ + if (keybuf[2] == 0xff) + return 0; + + /* remove repeat bit */ + keybuf[2] &= 0x7f; + keybuf[3] |= 0x80; + + *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24; + *ir_raw = *ir_key; + + return 1; +} + static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) { struct i2c_board_info info; @@ -172,7 +200,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS; init_data->internal_get_key_func = IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; - init_data->type = IR_TYPE_OTHER; + init_data->type = RC_TYPE_OTHER; init_data->name = "AVerMedia AVerTV card"; break; case IVTV_HW_I2C_IR_RX_HAUP_EXT: @@ -180,15 +208,22 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) /* Default to old black remote */ init_data->ir_codes = RC_MAP_RC5_TV; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; init_data->name = itv->card_name; break; case IVTV_HW_Z8F0811_IR_RX_HAUP: /* Default to grey remote */ init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; + init_data->name = itv->card_name; + break; + case IVTV_HW_I2C_IR_RX_ADAPTEC: + init_data->get_key = get_key_adaptec; init_data->name = itv->card_name; + /* FIXME: The protocol and RC_MAP needs to be corrected */ + init_data->ir_codes = RC_MAP_EMPTY; + init_data->type = RC_TYPE_UNKNOWN; break; } @@ -218,8 +253,6 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) const unsigned short addr_list[] = { 0x1a, /* Hauppauge IR external - collides with WM8739 */ 0x18, /* Hauppauge IR internal */ - 0x71, /* Hauppauge IR (PVR150) */ - 0x6b, /* Adaptec IR */ I2C_CLIENT_END }; diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index e1c347e5ebd8..2dfa957b0fd5 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -92,54 +92,97 @@ static int odd_parity(u8 c) return c & 1; } -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt) +static void ivtv_write_vbi_line(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *d, + struct vbi_cc *cc, int *found_cc) { struct vbi_info *vi = &itv->vbi; - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - int found_cc = 0; - size_t i; - - for (i = 0; i < cnt; i++) { - const struct v4l2_sliced_vbi_data *d = sliced + i; - if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { - if (d->field) { - cc.even[0] = d->data[0]; - cc.even[1] = d->data[1]; - } else { - cc.odd[0] = d->data[0]; - cc.odd[1] = d->data[1]; - } - found_cc = 1; + if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { + if (d->field) { + cc->even[0] = d->data[0]; + cc->even[1] = d->data[1]; + } else { + cc->odd[0] = d->data[0]; + cc->odd[1] = d->data[1]; } - else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { - struct vbi_vps vps; - - vps.data[0] = d->data[2]; - vps.data[1] = d->data[8]; - vps.data[2] = d->data[9]; - vps.data[3] = d->data[10]; - vps.data[4] = d->data[11]; - if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { - vi->vps_payload = vps; - set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); - } + *found_cc = 1; + } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { + struct vbi_vps vps; + + vps.data[0] = d->data[2]; + vps.data[1] = d->data[8]; + vps.data[2] = d->data[9]; + vps.data[3] = d->data[10]; + vps.data[4] = d->data[11]; + if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { + vi->vps_payload = vps; + set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); } - else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { - int wss = d->data[0] | d->data[1] << 8; + } else if (d->id == V4L2_SLICED_WSS_625 && + d->line == 23 && d->field == 0) { + int wss = d->data[0] | d->data[1] << 8; - if (vi->wss_payload != wss) { - vi->wss_payload = wss; - set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); - } + if (vi->wss_payload != wss) { + vi->wss_payload = wss; + set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); } } - if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { - vi->cc_payload[vi->cc_payload_idx++] = cc; +} + +static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc) +{ + struct vbi_info *vi = &itv->vbi; + + if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { + memcpy(&vi->cc_payload[vi->cc_payload_idx], cc, + sizeof(struct vbi_cc)); + vi->cc_payload_idx++; set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); } } +static void ivtv_write_vbi(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + + for (i = 0; i < cnt; i++) + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); +} + +ssize_t +ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + struct v4l2_sliced_vbi_data d; + ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data); + + for (i = 0; i < cnt; i++) { + if (copy_from_user(&d, sliced + i, + sizeof(struct v4l2_sliced_vbi_data))) { + ret = -EFAULT; + break; + } + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + } + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); + + return ret; +} + static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) { int line = 0; diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index 970567b9194d..166dd0b75d0f 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -20,7 +20,10 @@ #ifndef IVTV_VBI_H #define IVTV_VBI_H -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count); +ssize_t +ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t count); void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, u64 pts_stamp, int streamtype); int ivtv_used_line(struct ivtv *itv, int line, int field); |