diff options
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r-- | drivers/media/video/ivtv/Makefile | 8 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-controls.c | 62 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-controls.h | 2 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 41 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 13 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 2 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 188 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 20 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-udma.c | 4 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtvfb.c | 2 |
10 files changed, 221 insertions, 121 deletions
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile index 71ab76a5ab26..77de8a45b46f 100644 --- a/drivers/media/video/ivtv/Makefile +++ b/drivers/media/video/ivtv/Makefile @@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \ obj-$(CONFIG_VIDEO_IVTV) += ivtv.o obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/common/tuners -ccflags-y += -Idrivers/media/dvb/dvb-core -ccflags-y += -Idrivers/media/dvb/frontends +ccflags-y += -I$(srctree)/drivers/media/video +ccflags-y += -I$(srctree)/drivers/media/common/tuners +ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core +ccflags-y += -I$(srctree)/drivers/media/dvb/frontends diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index b31ee1bceef8..c60424601cb9 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c @@ -21,6 +21,7 @@ #include "ivtv-driver.h" #include "ivtv-ioctl.h" #include "ivtv-controls.h" +#include "ivtv-mailbox.h" static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) { @@ -99,3 +100,64 @@ struct cx2341x_handler_ops ivtv_cxhdl_ops = { .s_video_encoding = ivtv_s_video_encoding, .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, }; + +int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) +{ + u32 data[CX2341X_MBOX_MAX_DATA]; + + if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { + *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | + (u64)itv->last_dec_timing[1]; + *frame = itv->last_dec_timing[0]; + return 0; + } + *pts = 0; + *frame = 0; + if (atomic_read(&itv->decoding)) { + if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { + IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); + return -EIO; + } + memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); + set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); + *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; + *frame = data[0]; + /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ + } + return 0; +} + +static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); + + switch (ctrl->id) { + /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME + control cluster */ + case V4L2_CID_MPEG_VIDEO_DEC_PTS: + return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, + &itv->ctrl_frame->val64); + } + return 0; +} + +static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); + + switch (ctrl->id) { + /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK + control cluster */ + case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: + itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; + itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; + ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); + break; + } + return 0; +} + +const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { + .s_ctrl = ivtv_s_ctrl, + .g_volatile_ctrl = ivtv_g_volatile_ctrl, +}; diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h index d12893dd0183..3999e6358312 100644 --- a/drivers/media/video/ivtv/ivtv-controls.h +++ b/drivers/media/video/ivtv/ivtv-controls.h @@ -22,5 +22,7 @@ #define IVTV_CONTROLS_H extern struct cx2341x_handler_ops ivtv_cxhdl_ops; +extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; +int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); #endif diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 3949b7dc2368..679262ed13bc 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -55,7 +55,7 @@ #include "ivtv-routing.h" #include "ivtv-controls.h" #include "ivtv-gpio.h" - +#include <linux/dma-mapping.h> #include <media/tveeprom.h> #include <media/saa7115.h> #include <media/v4l2-chip-ident.h> @@ -99,7 +99,7 @@ static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, static unsigned int cardtype_c = 1; static unsigned int tuner_c = 1; -static bool radio_c = 1; +static int radio_c = 1; static unsigned int i2c_clock_period_c = 1; static char pal[] = "---"; static char secam[] = "--"; @@ -139,7 +139,7 @@ static int tunertype = -1; static int newi2c = -1; module_param_array(tuner, int, &tuner_c, 0644); -module_param_array(radio, bool, &radio_c, 0644); +module_param_array(radio, int, &radio_c, 0644); module_param_array(cardtype, int, &cardtype_c, 0644); module_param_string(pal, pal, sizeof(pal), 0644); module_param_string(secam, secam, sizeof(secam), 0644); @@ -744,8 +744,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->cur_dma_stream = -1; itv->cur_pio_stream = -1; - itv->audio_stereo_mode = AUDIO_STEREO; - itv->audio_bilingual_mode = AUDIO_MONO_LEFT; /* Ctrls */ itv->speed = 1000; @@ -815,7 +813,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, IVTV_ERR("Can't enable device!\n"); return -EIO; } - if (pci_set_dma_mask(pdev, 0xffffffff)) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { IVTV_ERR("No suitable DMA available.\n"); return -EIO; } @@ -1200,6 +1198,32 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->tuner_std = itv->std; if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { + struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; + + itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, + V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 1, 0); + itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, + V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0x7fffffff, 1, 0); + /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, + mask that menu item. */ + itv->ctrl_audio_playback = + v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, + V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, + 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); + itv->ctrl_audio_multilingual_playback = + v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, + V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, + 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, + V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); + if (hdl->error) { + retval = hdl->error; + goto free_i2c; + } + v4l2_ctrl_cluster(2, &itv->ctrl_pts); + v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); ivtv_call_all(itv, video, s_std_output, itv->std); /* Turn off the output signal. The mpeg decoder is not yet active so without this you would get a green image until the @@ -1236,6 +1260,7 @@ free_streams: free_irq: free_irq(itv->pdev->irq, (void *)itv); free_i2c: + v4l2_ctrl_handler_free(&itv->cxhdl.hdl); exit_ivtv_i2c(itv); free_io: ivtv_iounmap(itv); @@ -1375,7 +1400,7 @@ static void ivtv_remove(struct pci_dev *pdev) else type = IVTV_DEC_STREAM_TYPE_MPG; ivtv_stop_v4l2_decode_stream(&itv->streams[type], - VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); + V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); } ivtv_halt_firmware(itv); } @@ -1391,6 +1416,8 @@ static void ivtv_remove(struct pci_dev *pdev) ivtv_streams_cleanup(itv, 1); ivtv_udma_free(itv); + v4l2_ctrl_handler_free(&itv->cxhdl.hdl); + exit_ivtv_i2c(itv); free_irq(itv->pdev->irq, (void *)itv); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 06f3d78389bf..2e220028aad2 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -54,7 +54,6 @@ #include <linux/mutex.h> #include <linux/slab.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <asm/byteorder.h> #include <linux/dvb/video.h> @@ -331,6 +330,7 @@ struct ivtv_stream { struct ivtv *itv; /* for ease of use */ const char *name; /* name of the stream */ int type; /* stream type */ + u32 caps; /* V4L2 capabilities */ struct v4l2_fh *fh; /* pointer to the streaming filehandle */ spinlock_t qlock; /* locks access to the queues */ @@ -630,6 +630,16 @@ struct ivtv { struct v4l2_device v4l2_dev; struct cx2341x_handler cxhdl; + struct { + /* PTS/Frame count control cluster */ + struct v4l2_ctrl *ctrl_pts; + struct v4l2_ctrl *ctrl_frame; + }; + struct { + /* Audio Playback control cluster */ + struct v4l2_ctrl *ctrl_audio_playback; + struct v4l2_ctrl *ctrl_audio_multilingual_playback; + }; struct v4l2_ctrl_handler hdl_gpio; struct v4l2_subdev sd_gpio; /* GPIO sub-device */ u16 instance; @@ -649,7 +659,6 @@ struct ivtv { u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ - /* Locking */ spinlock_t lock; /* lock access to this struct */ struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 2cd6c89b7d91..c9663e885b9f 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -900,7 +900,7 @@ int ivtv_v4l2_close(struct file *filp) if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; - ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); + ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); /* If all output streams are closed, and if the user doesn't have IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index c4bc48143098..989e556913ed 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_speed, int new_speed) } static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, - struct video_command *vc, int try) + struct v4l2_decoder_cmd *dc, int try) { struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; - switch (vc->cmd) { - case VIDEO_CMD_PLAY: { - vc->flags = 0; - vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); - if (vc->play.speed < 0) - vc->play.format = VIDEO_PLAY_FMT_GOP; + switch (dc->cmd) { + case V4L2_DEC_CMD_START: { + dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; + dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed); + if (dc->start.speed < 0) + dc->start.format = V4L2_DEC_START_FMT_GOP; + else + dc->start.format = V4L2_DEC_START_FMT_NONE; + if (dc->start.speed != 500 && dc->start.speed != 1500) + dc->flags = dc->start.speed == 1000 ? 0 : + V4L2_DEC_CMD_START_MUTE_AUDIO; if (try) break; + itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) return -EBUSY; if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { /* forces ivtv_set_speed to be called */ itv->speed = 0; } - return ivtv_start_decoding(id, vc->play.speed); + return ivtv_start_decoding(id, dc->start.speed); } - case VIDEO_CMD_STOP: - vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; - if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) - vc->stop.pts = 0; + case V4L2_DEC_CMD_STOP: + dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; + if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) + dc->stop.pts = 0; if (try) break; if (atomic_read(&itv->decoding) == 0) return 0; @@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, return -EBUSY; itv->output_mode = OUT_NONE; - return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); + return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); - case VIDEO_CMD_FREEZE: - vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; + case V4L2_DEC_CMD_PAUSE: + dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; if (try) break; if (itv->output_mode != OUT_MPG) return -EBUSY; if (atomic_read(&itv->decoding) > 0) { ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, - (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); + (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); } break; - case VIDEO_CMD_CONTINUE: - vc->flags = 0; + case V4L2_DEC_CMD_RESUME: + dc->flags = 0; if (try) break; if (itv->output_mode != OUT_MPG) return -EBUSY; @@ -754,12 +760,15 @@ static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) { - struct ivtv *itv = fh2id(fh)->itv; + struct ivtv_open_id *id = fh2id(file->private_data); + struct ivtv *itv = id->itv; + struct ivtv_stream *s = &itv->streams[id->type]; strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); - vcap->capabilities = itv->v4l2_cap; /* capabilities */ + vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; + vcap->device_caps = s->caps; return 0; } @@ -1476,8 +1485,6 @@ static int ivtv_log_status(struct file *file, void *fh) struct v4l2_audio audin; int i; - IVTV_INFO("================= START STATUS CARD #%d =================\n", - itv->instance); IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); if (itv->hw_flags & IVTV_HW_TVEEPROM) { struct tveeprom tv; @@ -1501,13 +1508,6 @@ static int ivtv_log_status(struct file *file, void *fh) "YUV Frames", "Passthrough", }; - static const char * const audio_modes[5] = { - "Stereo", - "Left", - "Right", - "Mono", - "Swapped" - }; static const char * const alpha_mode[4] = { "None", "Global", @@ -1536,9 +1536,6 @@ static int ivtv_log_status(struct file *file, void *fh) ivtv_get_output(itv, itv->active_output, &vidout); ivtv_get_audio_output(itv, 0, &audout); IVTV_INFO("Video Output: %s\n", vidout.name); - IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, - audio_modes[itv->audio_stereo_mode], - audio_modes[itv->audio_bilingual_mode]); if (mode < 0 || mode > OUT_PASSTHROUGH) mode = OUT_NONE; IVTV_INFO("Output Mode: %s\n", output_modes[mode]); @@ -1566,12 +1563,27 @@ static int ivtv_log_status(struct file *file, void *fh) IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); - IVTV_INFO("================== END STATUS CARD #%d ==================\n", - itv->instance); - return 0; } +static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) +{ + struct ivtv_open_id *id = fh2id(file->private_data); + struct ivtv *itv = id->itv; + + IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); + return ivtv_video_command(itv, id, dec, false); +} + +static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) +{ + struct ivtv_open_id *id = fh2id(file->private_data); + struct ivtv *itv = id->itv; + + IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); + return ivtv_video_command(itv, id, dec, true); +} + static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) { struct ivtv_open_id *id = fh2id(filp->private_data); @@ -1605,9 +1617,15 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) return ivtv_yuv_prep_frame(itv, args); } + case IVTV_IOC_PASSTHROUGH_MODE: + IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); + if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) + return -EINVAL; + return ivtv_passthrough_mode(itv, *(int *)arg != 0); + case VIDEO_GET_PTS: { - u32 data[CX2341X_MBOX_MAX_DATA]; - u64 *pts = arg; + s64 *pts = arg; + s64 frame; IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { @@ -1616,29 +1634,12 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) } if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; - - if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { - *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | - (u64)itv->last_dec_timing[1]; - break; - } - *pts = 0; - if (atomic_read(&itv->decoding)) { - if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { - IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); - return -EIO; - } - memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); - set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); - *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; - /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ - } - break; + return ivtv_g_pts_frame(itv, pts, &frame); } case VIDEO_GET_FRAME_COUNT: { - u32 data[CX2341X_MBOX_MAX_DATA]; - u64 *frame = arg; + s64 *frame = arg; + s64 pts; IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { @@ -1647,71 +1648,58 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) } if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) return -EINVAL; - - if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { - *frame = itv->last_dec_timing[0]; - break; - } - *frame = 0; - if (atomic_read(&itv->decoding)) { - if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { - IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); - return -EIO; - } - memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); - set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); - *frame = data[0]; - } - break; + return ivtv_g_pts_frame(itv, &pts, frame); } case VIDEO_PLAY: { - struct video_command vc; + struct v4l2_decoder_cmd dc; IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); - memset(&vc, 0, sizeof(vc)); - vc.cmd = VIDEO_CMD_PLAY; - return ivtv_video_command(itv, id, &vc, 0); + memset(&dc, 0, sizeof(dc)); + dc.cmd = V4L2_DEC_CMD_START; + return ivtv_video_command(itv, id, &dc, 0); } case VIDEO_STOP: { - struct video_command vc; + struct v4l2_decoder_cmd dc; IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); - memset(&vc, 0, sizeof(vc)); - vc.cmd = VIDEO_CMD_STOP; - vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; - return ivtv_video_command(itv, id, &vc, 0); + memset(&dc, 0, sizeof(dc)); + dc.cmd = V4L2_DEC_CMD_STOP; + dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; + return ivtv_video_command(itv, id, &dc, 0); } case VIDEO_FREEZE: { - struct video_command vc; + struct v4l2_decoder_cmd dc; IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); - memset(&vc, 0, sizeof(vc)); - vc.cmd = VIDEO_CMD_FREEZE; - return ivtv_video_command(itv, id, &vc, 0); + memset(&dc, 0, sizeof(dc)); + dc.cmd = V4L2_DEC_CMD_PAUSE; + return ivtv_video_command(itv, id, &dc, 0); } case VIDEO_CONTINUE: { - struct video_command vc; + struct v4l2_decoder_cmd dc; IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); - memset(&vc, 0, sizeof(vc)); - vc.cmd = VIDEO_CMD_CONTINUE; - return ivtv_video_command(itv, id, &vc, 0); + memset(&dc, 0, sizeof(dc)); + dc.cmd = V4L2_DEC_CMD_RESUME; + return ivtv_video_command(itv, id, &dc, 0); } case VIDEO_COMMAND: case VIDEO_TRY_COMMAND: { - struct video_command *vc = arg; + /* Note: struct v4l2_decoder_cmd has the same layout as + struct video_command */ + struct v4l2_decoder_cmd *dc = arg; int try = (cmd == VIDEO_TRY_COMMAND); if (try) - IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); + IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); else - IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); - return ivtv_video_command(itv, id, vc, try); + IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); + return ivtv_video_command(itv, id, dc, try); } case VIDEO_GET_EVENT: { @@ -1775,17 +1763,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); if (iarg > AUDIO_STEREO_SWAPPED) return -EINVAL; - itv->audio_stereo_mode = iarg; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - return 0; + return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); case AUDIO_BILINGUAL_CHANNEL_SELECT: IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); if (iarg > AUDIO_STEREO_SWAPPED) return -EINVAL; - itv->audio_bilingual_mode = iarg; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - return 0; + return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); default: return -EINVAL; @@ -1800,6 +1784,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, if (!valid_prio) { switch (cmd) { + case IVTV_IOC_PASSTHROUGH_MODE: case VIDEO_PLAY: case VIDEO_STOP: case VIDEO_FREEZE: @@ -1825,6 +1810,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, } case IVTV_IOC_DMA_FRAME: + case IVTV_IOC_PASSTHROUGH_MODE: case VIDEO_GET_PTS: case VIDEO_GET_FRAME_COUNT: case VIDEO_GET_EVENT: @@ -1889,6 +1875,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, .vidioc_encoder_cmd = ivtv_encoder_cmd, .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, + .vidioc_decoder_cmd = ivtv_decoder_cmd, + .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index c6e28b4ebbed..7ea5ca7f012b 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -78,60 +78,73 @@ static struct { int num_offset; int dma, pio; enum v4l2_buf_type buf_type; + u32 v4l2_caps; const struct v4l2_file_operations *fops; } ivtv_stream_info[] = { { /* IVTV_ENC_STREAM_TYPE_MPG */ "encoder MPG", VFL_TYPE_GRABBER, 0, PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_ENC_STREAM_TYPE_YUV */ "encoder YUV", VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_ENC_STREAM_TYPE_VBI */ "encoder VBI", VFL_TYPE_VBI, 0, PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, + V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_ENC_STREAM_TYPE_PCM */ "encoder PCM", VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, + V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_ENC_STREAM_TYPE_RAD */ "encoder radio", VFL_TYPE_RADIO, 0, PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, + V4L2_CAP_RADIO | V4L2_CAP_TUNER, &ivtv_v4l2_enc_fops }, { /* IVTV_DEC_STREAM_TYPE_MPG */ "decoder MPG", VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_dec_fops }, { /* IVTV_DEC_STREAM_TYPE_VBI */ "decoder VBI", VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, + V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, &ivtv_v4l2_enc_fops }, { /* IVTV_DEC_STREAM_TYPE_VOUT */ "decoder VOUT", VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, + V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_dec_fops }, { /* IVTV_DEC_STREAM_TYPE_YUV */ "decoder YUV", VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, &ivtv_v4l2_dec_fops } }; @@ -149,6 +162,7 @@ static void ivtv_stream_init(struct ivtv *itv, int type) s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; + s->caps = ivtv_stream_info[type].v4l2_caps; if (ivtv_stream_info[type].pio) s->dma = PCI_DMA_NONE; @@ -209,8 +223,8 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) s->vdev->num = num; s->vdev->v4l2_dev = &itv->v4l2_dev; - s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; s->vdev->fops = ivtv_stream_info[type].fops; + s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; s->vdev->release = video_device_release; s->vdev->tvnorms = V4L2_STD_ALL; s->vdev->lock = &itv->serialize_lock; @@ -891,7 +905,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); /* Stop Decoder */ - if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { + if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) { u32 tmp = 0; /* Wait until the decoder is no longer running */ @@ -911,7 +925,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) break; } } - ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); + ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0); /* turn off notification of dual/stereo mode change */ ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index 69cc8166b20b..7338cb2d0a38 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c @@ -57,9 +57,9 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info if (dma->bouncemap[map_offset] == NULL) return -1; local_irq_save(flags); - src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset; + src = kmap_atomic(dma->map[map_offset]) + offset; memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); - kunmap_atomic(src, KM_BOUNCE_READ); + kunmap_atomic(src); local_irq_restore(flags); sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); } diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index d0fbfcf7133d..e5e7fa9e737b 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) drv = driver_find("ivtv", &pci_bus_type); err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); - put_driver(drv); if (!registered) { printk(KERN_ERR "ivtvfb: no cards found\n"); return -ENODEV; @@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) drv = driver_find("ivtv", &pci_bus_type); err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); - put_driver(drv); } module_init(ivtvfb_init); |