summaryrefslogtreecommitdiff
path: root/drivers/media/video/ivtv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r--drivers/media/video/ivtv/Kconfig3
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.c5
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.h4
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c28
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c4
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c43
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c115
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.h5
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);