aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/pci/saa7134
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/saa7134')
-rw-r--r--drivers/media/pci/saa7134/Kconfig5
-rw-r--r--drivers/media/pci/saa7134/Makefile2
-rw-r--r--drivers/media/pci/saa7134/saa6752hs.c797
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c117
-rw-r--r--drivers/media/pci/saa7134/saa7134-cards.c6
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c143
-rw-r--r--drivers/media/pci/saa7134/saa7134-dvb.c50
-rw-r--r--drivers/media/pci/saa7134/saa7134-empress.c460
-rw-r--r--drivers/media/pci/saa7134/saa7134-i2c.c7
-rw-r--r--drivers/media/pci/saa7134/saa7134-reg.h12
-rw-r--r--drivers/media/pci/saa7134/saa7134-ts.c191
-rw-r--r--drivers/media/pci/saa7134/saa7134-tvaudio.c7
-rw-r--r--drivers/media/pci/saa7134/saa7134-vbi.c178
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c1271
-rw-r--r--drivers/media/pci/saa7134/saa7134.h128
15 files changed, 1057 insertions, 2317 deletions
diff --git a/drivers/media/pci/saa7134/Kconfig b/drivers/media/pci/saa7134/Kconfig
index 15b90d6e913..18ae7554630 100644
--- a/drivers/media/pci/saa7134/Kconfig
+++ b/drivers/media/pci/saa7134/Kconfig
@@ -1,11 +1,12 @@
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
depends on VIDEO_DEV && PCI && I2C
- select VIDEOBUF_DMA_SG
+ select VIDEOBUF2_DMA_SG
select VIDEO_TUNER
select VIDEO_TVEEPROM
select CRC32
select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
+ select VIDEO_SAA6752HS if MEDIA_SUBDRV_AUTOSELECT
---help---
This is a video4linux driver for Philips SAA713x based
TV cards.
@@ -36,7 +37,7 @@ config VIDEO_SAA7134_RC
config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
- select VIDEOBUF_DVB
+ select VIDEOBUF2_DVB
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/saa7134/Makefile b/drivers/media/pci/saa7134/Makefile
index 35375480ed4..58de9b08568 100644
--- a/drivers/media/pci/saa7134/Makefile
+++ b/drivers/media/pci/saa7134/Makefile
@@ -4,7 +4,7 @@ saa7134-y += saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
saa7134-y += saa7134-video.o
saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
-obj-$(CONFIG_VIDEO_SAA7134) += saa6752hs.o saa7134.o saa7134-empress.o
+obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o
obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
deleted file mode 100644
index 8ac4b1f2322..00000000000
--- a/drivers/media/pci/saa7134/saa6752hs.c
+++ /dev/null
@@ -1,797 +0,0 @@
- /*
- saa6752hs - i2c-driver for the saa6752hs by Philips
-
- Copyright (C) 2004 Andrew de Quincey
-
- AC-3 support:
-
- Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License vs published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-common.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-
-#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
-#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
-#define MPEG_TOTAL_TARGET_BITRATE_MAX 27000
-#define MPEG_PID_MAX ((1 << 14) - 1)
-
-
-MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
-MODULE_AUTHOR("Andrew de Quincey");
-MODULE_LICENSE("GPL");
-
-enum saa6752hs_videoformat {
- SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */
- SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
- SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
- SAA6752HS_VF_SIF = 3, /* SIF video format: 352x288 */
- SAA6752HS_VF_UNKNOWN,
-};
-
-struct saa6752hs_mpeg_params {
- /* transport streams */
- __u16 ts_pid_pmt;
- __u16 ts_pid_audio;
- __u16 ts_pid_video;
- __u16 ts_pid_pcr;
-
- /* audio */
- enum v4l2_mpeg_audio_encoding au_encoding;
- enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
- enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
-
- /* video */
- enum v4l2_mpeg_video_aspect vi_aspect;
- enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
- __u32 vi_bitrate;
- __u32 vi_bitrate_peak;
-};
-
-static const struct v4l2_format v4l2_format_table[] =
-{
- [SAA6752HS_VF_D1] =
- { .fmt = { .pix = { .width = 720, .height = 576 }}},
- [SAA6752HS_VF_2_3_D1] =
- { .fmt = { .pix = { .width = 480, .height = 576 }}},
- [SAA6752HS_VF_1_2_D1] =
- { .fmt = { .pix = { .width = 352, .height = 576 }}},
- [SAA6752HS_VF_SIF] =
- { .fmt = { .pix = { .width = 352, .height = 288 }}},
- [SAA6752HS_VF_UNKNOWN] =
- { .fmt = { .pix = { .width = 0, .height = 0}}},
-};
-
-struct saa6752hs_state {
- struct v4l2_subdev sd;
- struct v4l2_ctrl_handler hdl;
- struct { /* video bitrate mode control cluster */
- struct v4l2_ctrl *video_bitrate_mode;
- struct v4l2_ctrl *video_bitrate;
- struct v4l2_ctrl *video_bitrate_peak;
- };
- u32 revision;
- int has_ac3;
- struct saa6752hs_mpeg_params params;
- enum saa6752hs_videoformat video_format;
- v4l2_std_id standard;
-};
-
-enum saa6752hs_command {
- SAA6752HS_COMMAND_RESET = 0,
- SAA6752HS_COMMAND_STOP = 1,
- SAA6752HS_COMMAND_START = 2,
- SAA6752HS_COMMAND_PAUSE = 3,
- SAA6752HS_COMMAND_RECONFIGURE = 4,
- SAA6752HS_COMMAND_SLEEP = 5,
- SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
-
- SAA6752HS_COMMAND_MAX
-};
-
-static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
-{
- return container_of(sd, struct saa6752hs_state, sd);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static u8 PAT[] = {
- 0xc2, /* i2c register */
- 0x00, /* table number for encoder */
-
- 0x47, /* sync */
- 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
- 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
- 0x00, /* PSI pointer to start of table */
-
- 0x00, /* tid(0) */
- 0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
-
- 0x00, 0x01, /* transport_stream_id(1) */
-
- 0xc1, /* version_number(0), current_next_indicator(1) */
-
- 0x00, 0x00, /* section_number(0), last_section_number(0) */
-
- 0x00, 0x01, /* program_number(1) */
-
- 0xe0, 0x00, /* PMT PID */
-
- 0x00, 0x00, 0x00, 0x00 /* CRC32 */
-};
-
-static u8 PMT[] = {
- 0xc2, /* i2c register */
- 0x01, /* table number for encoder */
-
- 0x47, /* sync */
- 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
- 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
- 0x00, /* PSI pointer to start of table */
-
- 0x02, /* tid(2) */
- 0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
-
- 0x00, 0x01, /* program_number(1) */
-
- 0xc1, /* version_number(0), current_next_indicator(1) */
-
- 0x00, 0x00, /* section_number(0), last_section_number(0) */
-
- 0xe0, 0x00, /* PCR_PID */
-
- 0xf0, 0x00, /* program_info_length(0) */
-
- 0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
- 0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
-
- 0x00, 0x00, 0x00, 0x00 /* CRC32 */
-};
-
-static u8 PMT_AC3[] = {
- 0xc2, /* i2c register */
- 0x01, /* table number for encoder(1) */
- 0x47, /* sync */
-
- 0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
- 0x10, /* PMT PID (0x0010) */
- 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
- 0x00, /* PSI pointer to start of table */
-
- 0x02, /* TID (2) */
- 0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
-
- 0x00, 0x01, /* program_number(1) */
-
- 0xc1, /* version_number(0), current_next_indicator(1) */
-
- 0x00, 0x00, /* section_number(0), last_section_number(0) */
-
- 0xe1, 0x04, /* PCR_PID (0x0104) */
-
- 0xf0, 0x00, /* program_info_length(0) */
-
- 0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
- 0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
- 0x6a, /* AC3 */
- 0x01, /* Descriptor_length(1) */
- 0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
-
- 0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
-};
-
-static struct saa6752hs_mpeg_params param_defaults =
-{
- .ts_pid_pmt = 16,
- .ts_pid_video = 260,
- .ts_pid_audio = 256,
- .ts_pid_pcr = 259,
-
- .vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
- .vi_bitrate = 4000,
- .vi_bitrate_peak = 6000,
- .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-
- .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
- .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int saa6752hs_chip_command(struct i2c_client *client,
- enum saa6752hs_command command)
-{
- unsigned char buf[3];
- unsigned long timeout;
- int status = 0;
-
- /* execute the command */
- switch(command) {
- case SAA6752HS_COMMAND_RESET:
- buf[0] = 0x00;
- break;
-
- case SAA6752HS_COMMAND_STOP:
- buf[0] = 0x03;
- break;
-
- case SAA6752HS_COMMAND_START:
- buf[0] = 0x02;
- break;
-
- case SAA6752HS_COMMAND_PAUSE:
- buf[0] = 0x04;
- break;
-
- case SAA6752HS_COMMAND_RECONFIGURE:
- buf[0] = 0x05;
- break;
-
- case SAA6752HS_COMMAND_SLEEP:
- buf[0] = 0x06;
- break;
-
- case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
- buf[0] = 0x07;
- break;
-
- default:
- return -EINVAL;
- }
-
- /* set it and wait for it to be so */
- i2c_master_send(client, buf, 1);
- timeout = jiffies + HZ * 3;
- for (;;) {
- /* get the current status */
- buf[0] = 0x10;
- i2c_master_send(client, buf, 1);
- i2c_master_recv(client, buf, 1);
-
- if (!(buf[0] & 0x20))
- break;
- if (time_after(jiffies,timeout)) {
- status = -ETIMEDOUT;
- break;
- }
-
- msleep(10);
- }
-
- /* delay a bit to let encoder settle */
- msleep(50);
-
- return status;
-}
-
-
-static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
-{
- u8 buf[2];
-
- buf[0] = reg;
- buf[1] = val;
- i2c_master_send(client, buf, 2);
-}
-
-static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
-{
- u8 buf[3];
-
- buf[0] = reg;
- buf[1] = val >> 8;
- buf[2] = val & 0xff;
- i2c_master_send(client, buf, 3);
-}
-
-static int saa6752hs_set_bitrate(struct i2c_client *client,
- struct saa6752hs_state *h)
-{
- struct saa6752hs_mpeg_params *params = &h->params;
- int tot_bitrate;
- int is_384k;
-
- /* set the bitrate mode */
- set_reg8(client, 0x71,
- params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-
- /* set the video bitrate */
- if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
- /* set the target bitrate */
- set_reg16(client, 0x80, params->vi_bitrate);
-
- /* set the max bitrate */
- set_reg16(client, 0x81, params->vi_bitrate_peak);
- tot_bitrate = params->vi_bitrate_peak;
- } else {
- /* set the target bitrate (no max bitrate for CBR) */
- set_reg16(client, 0x81, params->vi_bitrate);
- tot_bitrate = params->vi_bitrate;
- }
-
- /* set the audio encoding */
- set_reg8(client, 0x93,
- params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
-
- /* set the audio bitrate */
- if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
- is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
- else
- is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
- set_reg8(client, 0x94, is_384k);
- tot_bitrate += is_384k ? 384 : 256;
-
- /* Note: the total max bitrate is determined by adding the video and audio
- bitrates together and also adding an extra 768kbit/s to stay on the
- safe side. If more control should be required, then an extra MPEG control
- should be added. */
- tot_bitrate += 768;
- if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
- tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
-
- /* set the total bitrate */
- set_reg16(client, 0xb1, tot_bitrate);
- return 0;
-}
-
-static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct saa6752hs_state *h =
- container_of(ctrl->handler, struct saa6752hs_state, hdl);
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- /* peak bitrate shall be >= normal bitrate */
- if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
- h->video_bitrate_peak->val < h->video_bitrate->val)
- h->video_bitrate_peak->val = h->video_bitrate->val;
- break;
- }
- return 0;
-}
-
-static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct saa6752hs_state *h =
- container_of(ctrl->handler, struct saa6752hs_state, hdl);
- struct saa6752hs_mpeg_params *params = &h->params;
-
- switch (ctrl->id) {
- case V4L2_CID_MPEG_STREAM_TYPE:
- break;
- case V4L2_CID_MPEG_STREAM_PID_PMT:
- params->ts_pid_pmt = ctrl->val;
- break;
- case V4L2_CID_MPEG_STREAM_PID_AUDIO:
- params->ts_pid_audio = ctrl->val;
- break;
- case V4L2_CID_MPEG_STREAM_PID_VIDEO:
- params->ts_pid_video = ctrl->val;
- break;
- case V4L2_CID_MPEG_STREAM_PID_PCR:
- params->ts_pid_pcr = ctrl->val;
- break;
- case V4L2_CID_MPEG_AUDIO_ENCODING:
- params->au_encoding = ctrl->val;
- break;
- case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
- params->au_l2_bitrate = ctrl->val;
- break;
- case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
- params->au_ac3_bitrate = ctrl->val;
- break;
- case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
- break;
- case V4L2_CID_MPEG_VIDEO_ENCODING:
- break;
- case V4L2_CID_MPEG_VIDEO_ASPECT:
- params->vi_aspect = ctrl->val;
- break;
- case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
- params->vi_bitrate_mode = ctrl->val;
- params->vi_bitrate = h->video_bitrate->val / 1000;
- params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000;
- v4l2_ctrl_activate(h->video_bitrate_peak,
- ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
-{
- unsigned char buf[9], buf2[4];
- struct saa6752hs_state *h = to_state(sd);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- unsigned size;
- u32 crc;
- unsigned char localPAT[256];
- unsigned char localPMT[256];
-
- /* Set video format - must be done first as it resets other settings */
- set_reg8(client, 0x41, h->video_format);
-
- /* Set number of lines in input signal */
- set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
-
- /* set bitrate */
- saa6752hs_set_bitrate(client, h);
-
- /* Set GOP structure {3, 13} */
- set_reg16(client, 0x72, 0x030d);
-
- /* Set minimum Q-scale {4} */
- set_reg8(client, 0x82, 0x04);
-
- /* Set maximum Q-scale {12} */
- set_reg8(client, 0x83, 0x0c);
-
- /* Set Output Protocol */
- set_reg8(client, 0xd0, 0x81);
-
- /* Set video output stream format {TS} */
- set_reg8(client, 0xb0, 0x05);
-
- /* Set leading null byte for TS */
- set_reg16(client, 0xf6, leading_null_bytes);
-
- /* compute PAT */
- memcpy(localPAT, PAT, sizeof(PAT));
- localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
- localPAT[18] = h->params.ts_pid_pmt & 0xff;
- crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
- localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
- localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
- localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
- localPAT[sizeof(PAT) - 1] = crc & 0xFF;
-
- /* compute PMT */
- if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
- size = sizeof(PMT_AC3);
- memcpy(localPMT, PMT_AC3, size);
- } else {
- size = sizeof(PMT);
- memcpy(localPMT, PMT, size);
- }
- localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
- localPMT[4] = h->params.ts_pid_pmt & 0xff;
- localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
- localPMT[16] = h->params.ts_pid_pcr & 0xFF;
- localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
- localPMT[21] = h->params.ts_pid_video & 0xFF;
- localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
- localPMT[26] = h->params.ts_pid_audio & 0xFF;
- crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
- localPMT[size - 4] = (crc >> 24) & 0xFF;
- localPMT[size - 3] = (crc >> 16) & 0xFF;
- localPMT[size - 2] = (crc >> 8) & 0xFF;
- localPMT[size - 1] = crc & 0xFF;
-
- /* Set Audio PID */
- set_reg16(client, 0xc1, h->params.ts_pid_audio);
-
- /* Set Video PID */
- set_reg16(client, 0xc0, h->params.ts_pid_video);
-
- /* Set PCR PID */
- set_reg16(client, 0xc4, h->params.ts_pid_pcr);
-
- /* Send SI tables */
- i2c_master_send(client, localPAT, sizeof(PAT));
- i2c_master_send(client, localPMT, size);
-
- /* mute then unmute audio. This removes buzzing artefacts */
- set_reg8(client, 0xa4, 1);
- set_reg8(client, 0xa4, 0);
-
- /* start it going */
- saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
-
- /* readout current state */
- buf[0] = 0xE1;
- buf[1] = 0xA7;
- buf[2] = 0xFE;
- buf[3] = 0x82;
- buf[4] = 0xB0;
- i2c_master_send(client, buf, 5);
- i2c_master_recv(client, buf2, 4);
-
- /* change aspect ratio */
- buf[0] = 0xE0;
- buf[1] = 0xA7;
- buf[2] = 0xFE;
- buf[3] = 0x82;
- buf[4] = 0xB0;
- buf[5] = buf2[0];
- switch (h->params.vi_aspect) {
- case V4L2_MPEG_VIDEO_ASPECT_16x9:
- buf[6] = buf2[1] | 0x40;
- break;
- case V4L2_MPEG_VIDEO_ASPECT_4x3:
- default:
- buf[6] = buf2[1] & 0xBF;
- break;
- }
- buf[7] = buf2[2];
- buf[8] = buf2[3];
- i2c_master_send(client, buf, 9);
-
- return 0;
-}
-
-static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct saa6752hs_state *h = to_state(sd);
-
- if (h->video_format == SAA6752HS_VF_UNKNOWN)
- h->video_format = SAA6752HS_VF_D1;
- f->width = v4l2_format_table[h->video_format].fmt.pix.width;
- f->height = v4l2_format_table[h->video_format].fmt.pix.height;
- f->code = V4L2_MBUS_FMT_FIXED;
- f->field = V4L2_FIELD_INTERLACED;
- f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- return 0;
-}
-
-static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- int dist_352, dist_480, dist_720;
-
- f->code = V4L2_MBUS_FMT_FIXED;
-
- dist_352 = abs(f->width - 352);
- dist_480 = abs(f->width - 480);
- dist_720 = abs(f->width - 720);
- if (dist_720 < dist_480) {
- f->width = 720;
- f->height = 576;
- } else if (dist_480 < dist_352) {
- f->width = 480;
- f->height = 576;
- } else {
- f->width = 352;
- if (abs(f->height - 576) < abs(f->height - 288))
- f->height = 576;
- else
- f->height = 288;
- }
- f->field = V4L2_FIELD_INTERLACED;
- f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- return 0;
-}
-
-static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct saa6752hs_state *h = to_state(sd);
-
- if (f->code != V4L2_MBUS_FMT_FIXED)
- return -EINVAL;
-
- /*
- FIXME: translate and round width/height into EMPRESS
- subsample type:
-
- type | PAL | NTSC
- ---------------------------
- SIF | 352x288 | 352x240
- 1/2 D1 | 352x576 | 352x480
- 2/3 D1 | 480x576 | 480x480
- D1 | 720x576 | 720x480
- */
-
- saa6752hs_try_mbus_fmt(sd, f);
- if (f->width == 720)
- h->video_format = SAA6752HS_VF_D1;
- else if (f->width == 480)
- h->video_format = SAA6752HS_VF_2_3_D1;
- else if (f->height == 576)
- h->video_format = SAA6752HS_VF_1_2_D1;
- else
- h->video_format = SAA6752HS_VF_SIF;
- return 0;
-}
-
-static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
-{
- struct saa6752hs_state *h = to_state(sd);
-
- h->standard = std;
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = {
- .try_ctrl = saa6752hs_try_ctrl,
- .s_ctrl = saa6752hs_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
- .init = saa6752hs_init,
- .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
- .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
- .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
- .g_ctrl = v4l2_subdev_g_ctrl,
- .s_ctrl = v4l2_subdev_s_ctrl,
- .queryctrl = v4l2_subdev_queryctrl,
- .querymenu = v4l2_subdev_querymenu,
- .s_std = saa6752hs_s_std,
-};
-
-static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
- .s_mbus_fmt = saa6752hs_s_mbus_fmt,
- .try_mbus_fmt = saa6752hs_try_mbus_fmt,
- .g_mbus_fmt = saa6752hs_g_mbus_fmt,
-};
-
-static const struct v4l2_subdev_ops saa6752hs_ops = {
- .core = &saa6752hs_core_ops,
- .video = &saa6752hs_video_ops,
-};
-
-static int saa6752hs_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
- struct v4l2_subdev *sd;
- struct v4l2_ctrl_handler *hdl;
- u8 addr = 0x13;
- u8 data[12];
-
- v4l_info(client, "chip found @ 0x%x (%s)\n",
- client->addr << 1, client->adapter->name);
- if (h == NULL)
- return -ENOMEM;
- sd = &h->sd;
- v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops);
-
- i2c_master_send(client, &addr, 1);
- i2c_master_recv(client, data, sizeof(data));
- h->revision = (data[8] << 8) | data[9];
- h->has_ac3 = 0;
- if (h->revision == 0x0206) {
- h->has_ac3 = 1;
- v4l_info(client, "supports AC-3\n");
- }
- h->params = param_defaults;
-
- hdl = &h->hdl;
- v4l2_ctrl_handler_init(hdl, 14);
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_AUDIO_ENCODING,
- h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- 0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
-
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_AUDIO_L2_BITRATE,
- V4L2_MPEG_AUDIO_L2_BITRATE_384K,
- ~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) |
- (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)),
- V4L2_MPEG_AUDIO_L2_BITRATE_256K);
-
- if (h->has_ac3)
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
- V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
- ~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) |
- (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)),
- V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
-
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
- ~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000),
- V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
-
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_ENCODING,
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
- ~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2),
- V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_ASPECT,
- V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01,
- V4L2_MPEG_VIDEO_ASPECT_4x3);
-
- h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- 1000000, 27000000, 1000, 8000000);
-
- v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_STREAM_TYPE,
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
- ~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS),
- V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
-
- h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
- V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
- h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000);
- v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16);
- v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260);
- v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256);
- v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops,
- V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259);
- sd->ctrl_handler = hdl;
- if (hdl->error) {
- int err = hdl->error;
-
- v4l2_ctrl_handler_free(hdl);
- kfree(h);
- return err;
- }
- v4l2_ctrl_cluster(3, &h->video_bitrate_mode);
- v4l2_ctrl_handler_setup(hdl);
- h->standard = 0; /* Assume 625 input lines */
- return 0;
-}
-
-static int saa6752hs_remove(struct i2c_client *client)
-{
- struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
- v4l2_device_unregister_subdev(sd);
- v4l2_ctrl_handler_free(&to_state(sd)->hdl);
- kfree(to_state(sd));
- return 0;
-}
-
-static const struct i2c_device_id saa6752hs_id[] = {
- { "saa6752hs", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
-
-static struct i2c_driver saa6752hs_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "saa6752hs",
- },
- .probe = saa6752hs_probe,
- .remove = saa6752hs_remove,
- .id_table = saa6752hs_id,
-};
-
-module_i2c_driver(saa6752hs_driver);
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index 10460fd3ce3..40569894c1c 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -27,6 +27,7 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
#include "saa7134.h"
#include "saa7134-reg.h"
@@ -172,7 +173,9 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
dev->dmasound.bufsize, dev->dmasound.blocks);
spin_unlock(&dev->slock);
+ snd_pcm_stream_lock(dev->dmasound.substream);
snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock(dev->dmasound.substream);
return;
}
@@ -272,6 +275,82 @@ static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream
return err;
}
+static int saa7134_alsa_dma_init(struct saa7134_dev *dev, int nr_pages)
+{
+ struct saa7134_dmasound *dma = &dev->dmasound;
+ struct page *pg;
+ int i;
+
+ dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == dma->vaddr) {
+ dprintk("vmalloc_32(%d pages) failed\n", nr_pages);
+ return -ENOMEM;
+ }
+
+ dprintk("vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)dma->vaddr,
+ nr_pages << PAGE_SHIFT);
+
+ memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT);
+ dma->nr_pages = nr_pages;
+
+ dma->sglist = vzalloc(dma->nr_pages * sizeof(*dma->sglist));
+ if (NULL == dma->sglist)
+ goto vzalloc_err;
+
+ sg_init_table(dma->sglist, dma->nr_pages);
+ for (i = 0; i < dma->nr_pages; i++) {
+ pg = vmalloc_to_page(dma->vaddr + i * PAGE_SIZE);
+ if (NULL == pg)
+ goto vmalloc_to_page_err;
+ sg_set_page(&dma->sglist[i], pg, PAGE_SIZE, 0);
+ }
+ return 0;
+
+vmalloc_to_page_err:
+ vfree(dma->sglist);
+ dma->sglist = NULL;
+vzalloc_err:
+ vfree(dma->vaddr);
+ dma->vaddr = NULL;
+ return -ENOMEM;
+}
+
+static int saa7134_alsa_dma_map(struct saa7134_dev *dev)
+{
+ struct saa7134_dmasound *dma = &dev->dmasound;
+
+ dma->sglen = dma_map_sg(&dev->pci->dev, dma->sglist,
+ dma->nr_pages, PCI_DMA_FROMDEVICE);
+
+ if (0 == dma->sglen) {
+ pr_warn("%s: saa7134_alsa_map_sg failed\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int saa7134_alsa_dma_unmap(struct saa7134_dev *dev)
+{
+ struct saa7134_dmasound *dma = &dev->dmasound;
+
+ if (!dma->sglen)
+ return 0;
+
+ dma_unmap_sg(&dev->pci->dev, dma->sglist, dma->sglen, PCI_DMA_FROMDEVICE);
+ dma->sglen = 0;
+ return 0;
+}
+
+static int saa7134_alsa_dma_free(struct saa7134_dmasound *dma)
+{
+ vfree(dma->sglist);
+ dma->sglist = NULL;
+ vfree(dma->vaddr);
+ dma->vaddr = NULL;
+ return 0;
+}
+
/*
* DMA buffer initialization
*
@@ -289,9 +368,8 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
BUG_ON(!dev->dmasound.bufsize);
- videobuf_dma_init(&dev->dmasound.dma);
- err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
- (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
+ err = saa7134_alsa_dma_init(dev,
+ (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
if (0 != err)
return err;
return 0;
@@ -308,7 +386,7 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
{
BUG_ON(!dev->dmasound.blksize);
- videobuf_dma_free(&dev->dmasound.dma);
+ saa7134_alsa_dma_free(&dev->dmasound);
dev->dmasound.blocks = 0;
dev->dmasound.blksize = 0;
@@ -630,7 +708,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
/* release the old buffer */
if (substream->runtime->dma_area) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
- videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ saa7134_alsa_dma_unmap(dev);
dsp_buffer_free(dev);
substream->runtime->dma_area = NULL;
}
@@ -646,21 +724,22 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
return err;
}
- if (0 != (err = videobuf_dma_map(&dev->pci->dev, &dev->dmasound.dma))) {
+ err = saa7134_alsa_dma_map(dev);
+ if (err) {
dsp_buffer_free(dev);
return err;
}
- if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
- videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ err = saa7134_pgtable_alloc(dev->pci, &dev->dmasound.pt);
+ if (err) {
+ saa7134_alsa_dma_unmap(dev);
dsp_buffer_free(dev);
return err;
}
- if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
- dev->dmasound.dma.sglist,
- dev->dmasound.dma.sglen,
- 0))) {
+ err = saa7134_pgtable_build(dev->pci, &dev->dmasound.pt,
+ dev->dmasound.sglist, dev->dmasound.sglen, 0);
+ if (err) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
- videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ saa7134_alsa_dma_unmap(dev);
dsp_buffer_free(dev);
return err;
}
@@ -669,7 +748,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
byte, but it doesn't work. So I allocate the DMA using the
V4L functions, and force ALSA to use that as the DMA area */
- substream->runtime->dma_area = dev->dmasound.dma.vaddr;
+ substream->runtime->dma_area = dev->dmasound.vaddr;
substream->runtime->dma_bytes = dev->dmasound.bufsize;
substream->runtime->dma_addr = 0;
@@ -696,7 +775,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
if (substream->runtime->dma_area) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
- videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ saa7134_alsa_dma_unmap(dev);
dsp_buffer_free(dev);
substream->runtime->dma_area = NULL;
}
@@ -1070,8 +1149,8 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
if (!enable[devnum])
return -ENODEV;
- err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
- sizeof(snd_card_saa7134_t), &card);
+ err = snd_card_new(&dev->pci->dev, index[devnum], id[devnum],
+ THIS_MODULE, sizeof(snd_card_saa7134_t), &card);
if (err < 0)
return err;
@@ -1094,7 +1173,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
err = request_irq(dev->pci->irq, saa7134_alsa_irq,
- IRQF_SHARED | IRQF_DISABLED, dev->name,
+ IRQF_SHARED, dev->name,
(void*) &dev->dmasound);
if (err < 0) {
@@ -1113,8 +1192,6 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
if ((err = snd_card_saa7134_pcm(chip, 0)) < 0)
goto __nodev;
- snd_card_set_dev(card, &chip->pci->dev);
-
/* End of "creation" */
strcpy(card->shortname, "SAA7134");
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
index d45e7f6ff33..6e4bdb90aa9 100644
--- a/drivers/media/pci/saa7134/saa7134-cards.c
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -2590,7 +2590,7 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
- /* Michael Krufky <mkrufky@m1k.net>
+ /* Michael Krufky <mkrufky@linuxtv.org>
* Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
* AFAIK, there is no analog demod, thus,
* no support for analog television.
@@ -8045,8 +8045,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
break;
} /* switch() */
- /* initialize tuner */
- if (TUNER_ABSENT != dev->tuner_type) {
+ /* initialize tuner (don't do this when resuming) */
+ if (!dev->insuspend && TUNER_ABSENT != dev->tuner_type) {
int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
/* Note: radio tuner address is always filled in,
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 45f0aca597a..be19a051a49 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -69,6 +69,10 @@ module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
" [some VIA/SIS chipsets are known to have problem with overlay]");
+bool saa7134_userptr;
+module_param(saa7134_userptr, bool, 0644);
+MODULE_PARM_DESC(saa7134_userptr, "enable page-aligned userptr support");
+
static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
@@ -203,16 +207,16 @@ int saa7134_buffer_count(unsigned int size, unsigned int count)
int saa7134_buffer_startpage(struct saa7134_buf *buf)
{
- return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i;
+ return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index;
}
unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
{
unsigned long base;
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
base = saa7134_buffer_startpage(buf) * 4096;
- base += dma->sglist[0].offset;
+ base += dma->sgl[0].offset;
return base;
}
@@ -237,14 +241,16 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
unsigned int startpage)
{
__le32 *ptr;
- unsigned int i,p;
+ unsigned int i, p;
BUG_ON(NULL == pt || NULL == pt->cpu);
ptr = pt->cpu + startpage;
- for (i = 0; i < length; i++, list++)
+ for (i = 0; i < length; i++, list = sg_next(list)) {
for (p = 0; p * 4096 < list->length; p++, ptr++)
- *ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
+ *ptr = cpu_to_le32(sg_dma_address(list) +
+ list->offset + p * 4096);
+ }
return 0;
}
@@ -258,44 +264,31 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
/* ------------------------------------------------------------------ */
-void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
-{
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- BUG_ON(in_interrupt());
-
- videobuf_waiton(q, &buf->vb, 0, 0);
- videobuf_dma_unmap(q->dev, dma);
- videobuf_dma_free(dma);
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-/* ------------------------------------------------------------------ */
-
int saa7134_buffer_queue(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
struct saa7134_buf *buf)
{
struct saa7134_buf *next = NULL;
+ unsigned long flags;
- assert_spin_locked(&dev->slock);
- dprintk("buffer_queue %p\n",buf);
+ spin_lock_irqsave(&dev->slock, flags);
+ dprintk("buffer_queue %p\n", buf);
if (NULL == q->curr) {
if (!q->need_two) {
q->curr = buf;
- buf->activate(dev,buf,NULL);
+ buf->activate(dev, buf, NULL);
} else if (list_empty(&q->queue)) {
- list_add_tail(&buf->vb.queue,&q->queue);
- buf->vb.state = VIDEOBUF_QUEUED;
+ list_add_tail(&buf->entry, &q->queue);
} else {
- next = list_entry(q->queue.next,struct saa7134_buf,
- vb.queue);
+ next = list_entry(q->queue.next, struct saa7134_buf,
+ entry);
q->curr = buf;
- buf->activate(dev,buf,next);
+ buf->activate(dev, buf, next);
}
} else {
- list_add_tail(&buf->vb.queue,&q->queue);
- buf->vb.state = VIDEOBUF_QUEUED;
+ list_add_tail(&buf->entry, &q->queue);
}
+ spin_unlock_irqrestore(&dev->slock, flags);
return 0;
}
@@ -303,13 +296,12 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
unsigned int state)
{
- assert_spin_locked(&dev->slock);
- dprintk("buffer_finish %p\n",q->curr);
+ dprintk("buffer_finish %p\n", q->curr);
/* finish current buffer */
- q->curr->vb.state = state;
- v4l2_get_timestamp(&q->curr->vb.ts);
- wake_up(&q->curr->vb.done);
+ v4l2_get_timestamp(&q->curr->vb2.v4l2_buf.timestamp);
+ q->curr->vb2.v4l2_buf.sequence = q->seq_nr++;
+ vb2_buffer_done(&q->curr->vb2, state);
q->curr = NULL;
}
@@ -323,36 +315,31 @@ void saa7134_buffer_next(struct saa7134_dev *dev,
if (!list_empty(&q->queue)) {
/* activate next one from queue */
- buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue);
+ buf = list_entry(q->queue.next, struct saa7134_buf, entry);
dprintk("buffer_next %p [prev=%p/next=%p]\n",
- buf,q->queue.prev,q->queue.next);
- list_del(&buf->vb.queue);
+ buf, q->queue.prev, q->queue.next);
+ list_del(&buf->entry);
if (!list_empty(&q->queue))
- next = list_entry(q->queue.next,struct saa7134_buf,
- vb.queue);
+ next = list_entry(q->queue.next, struct saa7134_buf, entry);
q->curr = buf;
- buf->activate(dev,buf,next);
+ buf->activate(dev, buf, next);
dprintk("buffer_next #2 prev=%p/next=%p\n",
- q->queue.prev,q->queue.next);
+ q->queue.prev, q->queue.next);
} else {
/* nothing to do -- just stop DMA */
- dprintk("buffer_next %p\n",NULL);
+ dprintk("buffer_next %p\n", NULL);
saa7134_set_dmabits(dev);
del_timer(&q->timeout);
-
- if (card_has_mpeg(dev))
- if (dev->ts_started)
- saa7134_ts_stop(dev);
}
}
void saa7134_buffer_timeout(unsigned long data)
{
- struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data;
+ struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue *)data;
struct saa7134_dev *dev = q->dev;
unsigned long flags;
- spin_lock_irqsave(&dev->slock,flags);
+ spin_lock_irqsave(&dev->slock, flags);
/* try to reset the hardware (SWRST) */
saa_writeb(SAA7134_REGION_ENABLE, 0x00);
@@ -362,13 +349,33 @@ void saa7134_buffer_timeout(unsigned long data)
/* flag current buffer as failed,
try to start over with the next one. */
if (q->curr) {
- dprintk("timeout on %p\n",q->curr);
- saa7134_buffer_finish(dev,q,VIDEOBUF_ERROR);
+ dprintk("timeout on %p\n", q->curr);
+ saa7134_buffer_finish(dev, q, VB2_BUF_STATE_ERROR);
}
- saa7134_buffer_next(dev,q);
- spin_unlock_irqrestore(&dev->slock,flags);
+ saa7134_buffer_next(dev, q);
+ spin_unlock_irqrestore(&dev->slock, flags);
}
+void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q)
+{
+ unsigned long flags;
+ struct list_head *pos, *n;
+ struct saa7134_buf *tmp;
+
+ spin_lock_irqsave(&dev->slock, flags);
+ if (!list_empty(&q->queue)) {
+ list_for_each_safe(pos, n, &q->queue) {
+ tmp = list_entry(pos, struct saa7134_buf, entry);
+ vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR);
+ list_del(pos);
+ tmp = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&dev->slock, flags);
+ saa7134_buffer_timeout((unsigned long)q); /* also calls del_timer(&q->timeout) */
+}
+EXPORT_SYMBOL_GPL(saa7134_stop_streaming);
+
/* ------------------------------------------------------------------ */
int saa7134_set_dmabits(struct saa7134_dev *dev)
@@ -388,12 +395,11 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
ctrl |= SAA7134_MAIN_CTRL_TE0;
irq |= SAA7134_IRQ1_INTE_RA0_1 |
SAA7134_IRQ1_INTE_RA0_0;
- cap = dev->video_q.curr->vb.field;
+ cap = dev->field;
}
/* video capture -- dma 1+2 (planar modes) */
- if (dev->video_q.curr &&
- dev->video_q.curr->fmt->planar) {
+ if (dev->video_q.curr && dev->fmt->planar) {
ctrl |= SAA7134_MAIN_CTRL_TE4 |
SAA7134_MAIN_CTRL_TE5;
}
@@ -751,6 +757,7 @@ static int saa7134_hwfini(struct saa7134_dev *dev)
saa7134_input_fini(dev);
saa7134_vbi_fini(dev);
saa7134_tvaudio_fini(dev);
+ saa7134_video_fini(dev);
return 0;
}
@@ -802,7 +809,6 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
*vfd = *template;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->release = video_device_release;
- vfd->debug = video_debug;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
dev->name, type, saa7134_boards[dev->board].name);
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
@@ -992,7 +998,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
/* get irq */
err = request_irq(pci_dev->irq, saa7134_irq,
- IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+ IRQF_SHARED, dev->name, dev);
if (err < 0) {
printk(KERN_ERR "%s: can't get IRQ %d\n",
dev->name,pci_dev->irq);
@@ -1008,13 +1014,13 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
/* load i2c helpers */
if (card_is_empress(dev)) {
- struct v4l2_subdev *sd =
+ dev->empress_sd =
v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
"saa6752hs",
saa7134_boards[dev->board].empress_addr, NULL);
- if (sd)
- sd->grp_id = GRP_EMPRESS;
+ if (dev->empress_sd)
+ dev->empress_sd->grp_id = GRP_EMPRESS;
}
if (saa7134_boards[dev->board].rds_addr) {
@@ -1046,6 +1052,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
+ dev->video_dev->ctrl_handler = &dev->ctrl_handler;
+ dev->video_dev->lock = &dev->lock;
+ dev->video_dev->queue = &dev->video_vbq;
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[dev->nr]);
if (err < 0) {
@@ -1057,6 +1066,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->name, video_device_node_name(dev->video_dev));
dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
+ dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
+ dev->vbi_dev->lock = &dev->lock;
+ dev->vbi_dev->queue = &dev->vbi_vbq;
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[dev->nr]);
@@ -1067,6 +1079,8 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
if (card_has_radio(dev)) {
dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
+ dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
+ dev->radio_dev->lock = &dev->lock;
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
radio_nr[dev->nr]);
if (err < 0)
@@ -1186,7 +1200,7 @@ static int saa7134_buffer_requeue(struct saa7134_dev *dev,
if (!list_empty(&q->queue))
next = list_entry(q->queue.next, struct saa7134_buf,
- vb.queue);
+ entry);
buf->activate(dev, buf, next);
return 0;
@@ -1357,10 +1371,3 @@ EXPORT_SYMBOL(saa7134_pgtable_free);
EXPORT_SYMBOL(saa7134_pgtable_build);
EXPORT_SYMBOL(saa7134_pgtable_alloc);
EXPORT_SYMBOL(saa7134_set_dmabits);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c
index 4a08ae31df2..73ffbabf831 100644
--- a/drivers/media/pci/saa7134/saa7134-dvb.c
+++ b/drivers/media/pci/saa7134/saa7134-dvb.c
@@ -602,10 +602,10 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
struct tda1004x_config *cdec_conf,
struct tda827x_config *tuner_conf)
{
- struct videobuf_dvb_frontend *fe0;
+ struct vb2_dvb_frontend *fe0;
/* Get the first frontend */
- fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
@@ -1215,29 +1215,38 @@ static int dvb_init(struct saa7134_dev *dev)
{
int ret;
int attach_xc3028 = 0;
- struct videobuf_dvb_frontend *fe0;
+ struct vb2_dvb_frontend *fe0;
+ struct vb2_queue *q;
/* FIXME: add support for multi-frontend */
mutex_init(&dev->frontends.lock);
INIT_LIST_HEAD(&dev->frontends.felist);
printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
- fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
+ fe0 = vb2_dvb_alloc_frontend(&dev->frontends, 1);
if (!fe0) {
printk(KERN_ERR "%s() failed to alloc\n", __func__);
return -ENOMEM;
}
- /* init struct videobuf_dvb */
+ /* init struct vb2_dvb */
dev->ts.nr_bufs = 32;
dev->ts.nr_packets = 32*4;
fe0->dvb.name = dev->name;
- videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_ALTERNATE,
- sizeof(struct saa7134_buf),
- dev, NULL);
+ q = &fe0->dvb.dvbq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_READ;
+ q->drv_priv = &dev->ts_q;
+ q->ops = &saa7134_ts_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->buf_struct_size = sizeof(struct saa7134_buf);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &dev->lock;
+ ret = vb2_queue_init(q);
+ if (ret) {
+ vb2_dvb_dealloc_frontends(&dev->frontends);
+ return ret;
+ }
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
@@ -1876,7 +1885,7 @@ static int dvb_init(struct saa7134_dev *dev)
fe0->dvb.frontend->callback = saa7134_tuner_callback;
/* register everything else */
- ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
&dev->pci->dev, adapter_nr, 0);
/* this sequence is necessary to make the tda1004x load its firmware
@@ -1893,16 +1902,17 @@ static int dvb_init(struct saa7134_dev *dev)
return ret;
detach_frontend:
- videobuf_dvb_dealloc_frontends(&dev->frontends);
+ vb2_dvb_dealloc_frontends(&dev->frontends);
+ vb2_queue_release(&fe0->dvb.dvbq);
return -EINVAL;
}
static int dvb_fini(struct saa7134_dev *dev)
{
- struct videobuf_dvb_frontend *fe0;
+ struct vb2_dvb_frontend *fe0;
/* Get the first frontend */
- fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
@@ -1933,7 +1943,8 @@ static int dvb_fini(struct saa7134_dev *dev)
}
}
}
- videobuf_dvb_unregister_bus(&dev->frontends);
+ vb2_dvb_unregister_bus(&dev->frontends);
+ vb2_queue_release(&fe0->dvb.dvbq);
return 0;
}
@@ -1955,10 +1966,3 @@ static void __exit dvb_unregister(void)
module_init(dvb_register);
module_exit(dvb_unregister);
-
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 3022eb2a792..0006d6bf8c1 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -23,12 +23,12 @@
#include <linux/kernel.h>
#include <linux/delay.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+
#include "saa7134-reg.h"
#include "saa7134.h"
-#include <media/saa6752hs.h>
-#include <media/v4l2-common.h>
-
/* ------------------------------------------------------------------ */
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -48,21 +48,16 @@ MODULE_PARM_DESC(debug,"enable debug messages");
/* ------------------------------------------------------------------ */
-static void ts_reset_encoder(struct saa7134_dev* dev)
-{
- if (!dev->empress_started)
- return;
-
- saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
- msleep(10);
- saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
- msleep(100);
- dev->empress_started = 0;
-}
-
-static int ts_init_encoder(struct saa7134_dev* dev)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
+ struct saa7134_dmaqueue *dmaq = vq->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
u32 leading_null_bytes = 0;
+ int err;
+
+ err = saa7134_ts_start_streaming(vq, count);
+ if (err)
+ return err;
/* If more cards start to need this, then this
should probably be added to the card definitions. */
@@ -73,136 +68,43 @@ static int ts_init_encoder(struct saa7134_dev* dev)
leading_null_bytes = 1;
break;
}
- ts_reset_encoder(dev);
saa_call_all(dev, core, init, leading_null_bytes);
- dev->empress_started = 1;
- return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int ts_open(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
- struct saa7134_dev *dev = video_drvdata(file);
- int err;
-
- dprintk("open dev=%s\n", video_device_node_name(vdev));
- err = -EBUSY;
- if (!mutex_trylock(&dev->empress_tsq.vb_lock))
- return err;
- if (atomic_read(&dev->empress_users))
- goto done;
-
/* Unmute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
- saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
-
- atomic_inc(&dev->empress_users);
- file->private_data = dev;
- err = 0;
-
-done:
- mutex_unlock(&dev->empress_tsq.vb_lock);
- return err;
+ saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
+ dev->empress_started = 1;
+ return 0;
}
-static int ts_release(struct file *file)
+static void stop_streaming(struct vb2_queue *vq)
{
- struct saa7134_dev *dev = file->private_data;
-
- videobuf_stop(&dev->empress_tsq);
- videobuf_mmap_free(&dev->empress_tsq);
-
- /* stop the encoder */
- ts_reset_encoder(dev);
+ struct saa7134_dmaqueue *dmaq = vq->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ saa7134_ts_stop_streaming(vq);
+ saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
+ msleep(20);
+ saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+ msleep(100);
/* Mute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
- saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
-
- atomic_dec(&dev->empress_users);
-
- return 0;
-}
-
-static ssize_t
-ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
- struct saa7134_dev *dev = file->private_data;
-
- if (!dev->empress_started)
- ts_init_encoder(dev);
-
- return videobuf_read_stream(&dev->empress_tsq,
- data, count, ppos, 0,
- file->f_flags & O_NONBLOCK);
-}
-
-static unsigned int
-ts_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_poll_stream(file, &dev->empress_tsq, wait);
-}
-
-
-static int
-ts_mmap(struct file *file, struct vm_area_struct * vma)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_mmap_mapper(&dev->empress_tsq, vma);
-}
-
-/*
- * This function is _not_ called directly, but from
- * video_generic_ioctl (and maybe others). userspace
- * copying is done already, arg is a kernel pointer.
- */
-
-static int empress_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
-{
- struct saa7134_dev *dev = file->private_data;
-
- strcpy(cap->driver, "saa7134");
- strlcpy(cap->card, saa7134_boards[dev->board].name,
- sizeof(cap->card));
- sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->capabilities =
- V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING;
- return 0;
-}
-
-static int empress_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- i->type = V4L2_INPUT_TYPE_CAMERA;
- strcpy(i->name, "CCIR656");
-
- return 0;
-}
-
-static int empress_g_input(struct file *file, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
+ saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
+ dev->empress_started = 0;
}
-static int empress_s_input(struct file *file, void *priv, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
+static struct vb2_ops saa7134_empress_qops = {
+ .queue_setup = saa7134_ts_queue_setup,
+ .buf_init = saa7134_ts_buffer_init,
+ .buf_prepare = saa7134_ts_buffer_prepare,
+ .buf_finish = saa7134_ts_buffer_finish,
+ .buf_queue = saa7134_vb2_buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = start_streaming,
+ .stop_streaming = stop_streaming,
+};
- return 0;
-}
+/* ------------------------------------------------------------------ */
static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
@@ -219,7 +121,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
static int empress_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_dev *dev = file->private_data;
+ struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_mbus_framefmt mbus_fmt;
saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
@@ -236,7 +138,7 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
static int empress_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_dev *dev = file->private_data;
+ struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_mbus_framefmt mbus_fmt;
v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
@@ -254,7 +156,7 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
static int empress_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_dev *dev = file->private_data;
+ struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_mbus_framefmt mbus_fmt;
v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
@@ -269,209 +171,42 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
-static int empress_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *p)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_reqbufs(&dev->empress_tsq, p);
-}
-
-static int empress_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *b)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_querybuf(&dev->empress_tsq, b);
-}
-
-static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_qbuf(&dev->empress_tsq, b);
-}
-
-static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_dqbuf(&dev->empress_tsq, b,
- file->f_flags & O_NONBLOCK);
-}
-
-static int empress_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_streamon(&dev->empress_tsq);
-}
-
-static int empress_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return videobuf_streamoff(&dev->empress_tsq);
-}
-
-static int empress_s_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7134_dev *dev = file->private_data;
- int err;
-
- /* count == 0 is abused in saa6752hs.c, so that special
- case is handled here explicitly. */
- if (ctrls->count == 0)
- return 0;
-
- if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
-
- err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
- ts_init_encoder(dev);
-
- return err;
-}
-
-static int empress_g_ext_ctrls(struct file *file, void *priv,
- struct v4l2_ext_controls *ctrls)
-{
- struct saa7134_dev *dev = file->private_data;
-
- if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
- return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
-}
-
-static int empress_g_ctrl(struct file *file, void *priv,
- struct v4l2_control *c)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return saa7134_g_ctrl_internal(dev, NULL, c);
-}
-
-static int empress_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *c)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return saa7134_s_ctrl_internal(dev, NULL, c);
-}
-
-static int empress_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- /* Must be sorted from low to high control ID! */
- static const u32 user_ctrls[] = {
- V4L2_CID_USER_CLASS,
- V4L2_CID_BRIGHTNESS,
- V4L2_CID_CONTRAST,
- V4L2_CID_SATURATION,
- V4L2_CID_HUE,
- V4L2_CID_AUDIO_VOLUME,
- V4L2_CID_AUDIO_MUTE,
- V4L2_CID_HFLIP,
- 0
- };
-
- /* Must be sorted from low to high control ID! */
- static const u32 mpeg_ctrls[] = {
- V4L2_CID_MPEG_CLASS,
- V4L2_CID_MPEG_STREAM_TYPE,
- V4L2_CID_MPEG_STREAM_PID_PMT,
- V4L2_CID_MPEG_STREAM_PID_AUDIO,
- V4L2_CID_MPEG_STREAM_PID_VIDEO,
- V4L2_CID_MPEG_STREAM_PID_PCR,
- V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
- V4L2_CID_MPEG_AUDIO_ENCODING,
- V4L2_CID_MPEG_AUDIO_L2_BITRATE,
- V4L2_CID_MPEG_VIDEO_ENCODING,
- V4L2_CID_MPEG_VIDEO_ASPECT,
- V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- V4L2_CID_MPEG_VIDEO_BITRATE,
- V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- 0
- };
- static const u32 *ctrl_classes[] = {
- user_ctrls,
- mpeg_ctrls,
- NULL
- };
- struct saa7134_dev *dev = file->private_data;
-
- c->id = v4l2_ctrl_next(ctrl_classes, c->id);
- if (c->id == 0)
- return -EINVAL;
- if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
- return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
- if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
- return saa7134_queryctrl(file, priv, c);
- return saa_call_empress(dev, core, queryctrl, c);
-}
-
-static int empress_querymenu(struct file *file, void *priv,
- struct v4l2_querymenu *c)
-{
- struct saa7134_dev *dev = file->private_data;
-
- if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
- return -EINVAL;
- return saa_call_empress(dev, core, querymenu, c);
-}
-
-static int empress_s_std(struct file *file, void *priv, v4l2_std_id id)
-{
- struct saa7134_dev *dev = file->private_data;
-
- return saa7134_s_std_internal(dev, NULL, id);
-}
-
-static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
- struct saa7134_dev *dev = file->private_data;
-
- *id = dev->tvnorm->id;
- return 0;
-}
-
static const struct v4l2_file_operations ts_fops =
{
.owner = THIS_MODULE,
- .open = ts_open,
- .release = ts_release,
- .read = ts_read,
- .poll = ts_poll,
- .mmap = ts_mmap,
- .ioctl = video_ioctl2,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .unlocked_ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops ts_ioctl_ops = {
- .vidioc_querycap = empress_querycap,
+ .vidioc_querycap = saa7134_querycap,
.vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap,
- .vidioc_reqbufs = empress_reqbufs,
- .vidioc_querybuf = empress_querybuf,
- .vidioc_qbuf = empress_qbuf,
- .vidioc_dqbuf = empress_dqbuf,
- .vidioc_streamon = empress_streamon,
- .vidioc_streamoff = empress_streamoff,
- .vidioc_s_ext_ctrls = empress_s_ext_ctrls,
- .vidioc_g_ext_ctrls = empress_g_ext_ctrls,
- .vidioc_enum_input = empress_enum_input,
- .vidioc_g_input = empress_g_input,
- .vidioc_s_input = empress_s_input,
- .vidioc_queryctrl = empress_queryctrl,
- .vidioc_querymenu = empress_querymenu,
- .vidioc_g_ctrl = empress_g_ctrl,
- .vidioc_s_ctrl = empress_s_ctrl,
- .vidioc_s_std = empress_s_std,
- .vidioc_g_std = empress_g_std,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_g_frequency = saa7134_g_frequency,
+ .vidioc_s_frequency = saa7134_s_frequency,
+ .vidioc_g_tuner = saa7134_g_tuner,
+ .vidioc_s_tuner = saa7134_s_tuner,
+ .vidioc_enum_input = saa7134_enum_input,
+ .vidioc_g_input = saa7134_g_input,
+ .vidioc_s_input = saa7134_s_input,
+ .vidioc_s_std = saa7134_s_std,
+ .vidioc_g_std = saa7134_g_std,
+ .vidioc_querystd = saa7134_querystd,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
/* ----------------------------------------------------------- */
@@ -501,9 +236,27 @@ static void empress_signal_change(struct saa7134_dev *dev)
schedule_work(&dev->empress_workqueue);
}
+static bool empress_ctrl_filter(const struct v4l2_ctrl *ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ case V4L2_CID_HUE:
+ case V4L2_CID_CONTRAST:
+ case V4L2_CID_SATURATION:
+ case V4L2_CID_AUDIO_MUTE:
+ case V4L2_CID_AUDIO_VOLUME:
+ case V4L2_CID_PRIVATE_INVERT:
+ case V4L2_CID_PRIVATE_AUTOMUTE:
+ return true;
+ default:
+ return false;
+ }
+}
static int empress_init(struct saa7134_dev *dev)
{
+ struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler;
+ struct vb2_queue *q;
int err;
dprintk("%s: %s\n",dev->name,__func__);
@@ -513,12 +266,43 @@ static int empress_init(struct saa7134_dev *dev)
*(dev->empress_dev) = saa7134_empress_template;
dev->empress_dev->v4l2_dev = &dev->v4l2_dev;
dev->empress_dev->release = video_device_release;
+ dev->empress_dev->lock = &dev->lock;
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
+ set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
+ v4l2_ctrl_handler_init(hdl, 21);
+ v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
+ if (dev->empress_sd)
+ v4l2_ctrl_add_handler(hdl, dev->empress_sd->ctrl_handler, NULL);
+ if (hdl->error) {
+ video_device_release(dev->empress_dev);
+ return hdl->error;
+ }
+ dev->empress_dev->ctrl_handler = hdl;
INIT_WORK(&dev->empress_workqueue, empress_signal_update);
+ q = &dev->empress_vbq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /*
+ * Do not add VB2_USERPTR: the saa7134 DMA engine cannot handle
+ * transfers that do not start at the beginning of a page. A USERPTR
+ * can start anywhere in a page, so USERPTR support is a no-go.
+ */
+ q->io_modes = VB2_MMAP | VB2_READ;
+ q->drv_priv = &dev->ts_q;
+ q->ops = &saa7134_empress_qops;
+ q->gfp_flags = GFP_DMA32;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->buf_struct_size = sizeof(struct saa7134_buf);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &dev->lock;
+ err = vb2_queue_init(q);
+ if (err)
+ return err;
+ dev->empress_dev->queue = q;
+
video_set_drvdata(dev->empress_dev, dev);
err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
empress_nr[dev->nr]);
@@ -532,13 +316,6 @@ static int empress_init(struct saa7134_dev *dev)
printk(KERN_INFO "%s: registered device %s [mpeg]\n",
dev->name, video_device_node_name(dev->empress_dev));
- videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_ALTERNATE,
- sizeof(struct saa7134_buf),
- dev, NULL);
-
empress_signal_update(&dev->empress_workqueue);
return 0;
}
@@ -551,6 +328,8 @@ static int empress_fini(struct saa7134_dev *dev)
return 0;
flush_work(&dev->empress_workqueue);
video_unregister_device(dev->empress_dev);
+ vb2_queue_release(&dev->empress_vbq);
+ v4l2_ctrl_handler_free(&dev->empress_ctrl_handler);
dev->empress_dev = NULL;
return 0;
}
@@ -574,10 +353,3 @@ static void __exit empress_unregister(void)
module_init(empress_register);
module_exit(empress_unregister);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
index c68169d7580..f4da674e7f2 100644
--- a/drivers/media/pci/saa7134/saa7134-i2c.c
+++ b/drivers/media/pci/saa7134/saa7134-i2c.c
@@ -427,10 +427,3 @@ int saa7134_i2c_unregister(struct saa7134_dev *dev)
i2c_del_adapter(&dev->i2c_adap);
return 0;
}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-reg.h b/drivers/media/pci/saa7134/saa7134-reg.h
index e7e0af101fa..b6ea6f4f9b6 100644
--- a/drivers/media/pci/saa7134/saa7134-reg.h
+++ b/drivers/media/pci/saa7134/saa7134-reg.h
@@ -167,17 +167,22 @@
#define SAA7134_HSYNC_START 0x106
#define SAA7134_HSYNC_STOP 0x107
#define SAA7134_SYNC_CTRL 0x108
+#define SAA7134_SYNC_CTRL_AUFD (1 << 7)
#define SAA7134_LUMA_CTRL 0x109
+#define SAA7134_LUMA_CTRL_LDEL (1 << 5)
#define SAA7134_DEC_LUMA_BRIGHT 0x10a
#define SAA7134_DEC_LUMA_CONTRAST 0x10b
#define SAA7134_DEC_CHROMA_SATURATION 0x10c
#define SAA7134_DEC_CHROMA_HUE 0x10d
#define SAA7134_CHROMA_CTRL1 0x10e
+#define SAA7134_CHROMA_CTRL1_AUTO0 (1 << 1)
+#define SAA7134_CHROMA_CTRL1_FCTC (1 << 2)
#define SAA7134_CHROMA_GAIN 0x10f
#define SAA7134_CHROMA_CTRL2 0x110
#define SAA7134_MODE_DELAY_CTRL 0x111
#define SAA7134_ANALOG_ADC 0x114
+#define SAA7134_ANALOG_ADC_AUTO1 (1 << 2)
#define SAA7134_VGATE_START 0x115
#define SAA7134_VGATE_STOP 0x116
#define SAA7134_MISC_VGATE_MSB 0x117
@@ -369,10 +374,3 @@
#define SAA7135_DSP_RWCLEAR_RERR 1
#define SAA7133_I2S_AUDIO_CONTROL 0x591
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 2e3f4b412d8..bd25323bd94 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -39,26 +39,29 @@ MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
-
static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
dprintk("buffer_activate [%p]",buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
buf->top_seen = 0;
+ if (!dev->ts_started)
+ dev->ts_field = V4L2_FIELD_TOP;
+
if (NULL == next)
next = buf;
- if (V4L2_FIELD_TOP == buf->vb.field) {
+ if (V4L2_FIELD_TOP == dev->ts_field) {
dprintk("- [top] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
+ dev->ts_field = V4L2_FIELD_BOTTOM;
} else {
dprintk("- [bottom] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
+ dev->ts_field = V4L2_FIELD_TOP;
}
/* start DMA */
@@ -72,96 +75,123 @@ static int buffer_activate(struct saa7134_dev *dev,
return 0;
}
-static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
+int saa7134_ts_buffer_init(struct vb2_buffer *vb2)
{
- struct saa7134_dev *dev = q->priv_data;
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+
+ dmaq->curr = NULL;
+ buf->activate = buffer_activate;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init);
+
+int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
+{
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int lines, llength, size;
- int err;
+ int ret;
- dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
+ dprintk("buffer_prepare [%p]\n", buf);
llength = TS_PACKET_SIZE;
lines = dev->ts.nr_packets;
size = lines * llength;
- if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ if (vb2_plane_size(vb2, 0) < size)
return -EINVAL;
- if (buf->vb.size != size) {
- saa7134_dma_free(q,buf);
- }
-
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
- dprintk("buffer_prepare: needs_init\n");
-
- buf->vb.width = llength;
- buf->vb.height = lines;
- buf->vb.size = size;
- buf->pt = &dev->ts.pt_ts;
-
- err = videobuf_iolock(q,&buf->vb,NULL);
- if (err)
- goto oops;
- err = saa7134_pgtable_build(dev->pci,buf->pt,
- dma->sglist,
- dma->sglen,
- saa7134_buffer_startpage(buf));
- if (err)
- goto oops;
- }
-
- buf->vb.state = VIDEOBUF_PREPARED;
- buf->activate = buffer_activate;
- buf->vb.field = field;
- return 0;
+ vb2_set_plane_payload(vb2, 0, size);
+ vb2->v4l2_buf.field = dev->field;
- oops:
- saa7134_dma_free(q,buf);
- return err;
+ ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
+ return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
+ saa7134_buffer_startpage(buf));
}
+EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+void saa7134_ts_buffer_finish(struct vb2_buffer *vb2)
{
- struct saa7134_dev *dev = q->priv_data;
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
- *size = TS_PACKET_SIZE * dev->ts.nr_packets;
- if (0 == *count)
- *count = dev->ts.nr_bufs;
- *count = saa7134_buffer_count(*size,*count);
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish);
+int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct saa7134_dmaqueue *dmaq = q->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ int size = TS_PACKET_SIZE * dev->ts.nr_packets;
+
+ if (0 == *nbuffers)
+ *nbuffers = dev->ts.nr_bufs;
+ *nbuffers = saa7134_buffer_count(size, *nbuffers);
+ if (*nbuffers < 3)
+ *nbuffers = 3;
+ *nplanes = 1;
+ sizes[0] = size;
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count)
{
- struct saa7134_dev *dev = q->priv_data;
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-
- saa7134_buffer_queue(dev,&dev->ts_q,buf);
+ struct saa7134_dmaqueue *dmaq = vq->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+
+ /*
+ * Planar video capture and TS share the same DMA channel,
+ * so only one can be active at a time.
+ */
+ if (vb2_is_busy(&dev->video_vbq) && dev->fmt->planar) {
+ struct saa7134_buf *buf, *tmp;
+
+ list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
+ list_del(&buf->entry);
+ vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+ }
+ if (dmaq->curr) {
+ vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+ dmaq->curr = NULL;
+ }
+ return -EBUSY;
+ }
+ dmaq->seq_nr = 0;
+ return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_ts_start_streaming);
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+void saa7134_ts_stop_streaming(struct vb2_queue *vq)
{
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
- struct saa7134_dev *dev = q->priv_data;
-
- if (dev->ts_started)
- saa7134_ts_stop(dev);
+ struct saa7134_dmaqueue *dmaq = vq->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
- saa7134_dma_free(q,buf);
+ saa7134_ts_stop(dev);
+ saa7134_stop_streaming(dev, dmaq);
}
-
-struct videobuf_queue_ops saa7134_ts_qops = {
- .buf_setup = buffer_setup,
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .buf_release = buffer_release,
+EXPORT_SYMBOL_GPL(saa7134_ts_stop_streaming);
+
+struct vb2_ops saa7134_ts_qops = {
+ .queue_setup = saa7134_ts_queue_setup,
+ .buf_init = saa7134_ts_buffer_init,
+ .buf_prepare = saa7134_ts_buffer_prepare,
+ .buf_finish = saa7134_ts_buffer_finish,
+ .buf_queue = saa7134_vb2_buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .stop_streaming = saa7134_ts_stop_streaming,
};
EXPORT_SYMBOL_GPL(saa7134_ts_qops);
@@ -213,7 +243,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev)
dev->ts_q.dev = dev;
dev->ts_q.need_two = 1;
dev->ts_started = 0;
- saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
+ saa7134_pgtable_alloc(dev->pci, &dev->ts_q.pt);
/* init TS hw */
saa7134_ts_init_hw(dev);
@@ -226,7 +256,8 @@ int saa7134_ts_stop(struct saa7134_dev *dev)
{
dprintk("TS stop\n");
- BUG_ON(!dev->ts_started);
+ if (!dev->ts_started)
+ return 0;
/* Stop TS stream */
switch (saa7134_boards[dev->board].ts_type) {
@@ -247,7 +278,8 @@ int saa7134_ts_start(struct saa7134_dev *dev)
{
dprintk("TS start\n");
- BUG_ON(dev->ts_started);
+ if (WARN_ON(dev->ts_started))
+ return 0;
/* dma: setup channel 5 (= TS) */
saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
@@ -259,7 +291,7 @@ int saa7134_ts_start(struct saa7134_dev *dev)
saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
- (dev->ts.pt_ts.dma >> 12));
+ (dev->ts_q.pt.dma >> 12));
/* reset hardware TS buffers */
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
@@ -293,7 +325,7 @@ int saa7134_ts_start(struct saa7134_dev *dev)
int saa7134_ts_fini(struct saa7134_dev *dev)
{
- saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
+ saa7134_pgtable_free(dev->pci, &dev->ts_q.pt);
return 0;
}
@@ -303,25 +335,18 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
spin_lock(&dev->slock);
if (dev->ts_q.curr) {
- field = dev->ts_q.curr->vb.field;
- if (field == V4L2_FIELD_TOP) {
+ field = dev->ts_field;
+ if (field != V4L2_FIELD_TOP) {
if ((status & 0x100000) != 0x000000)
goto done;
} else {
if ((status & 0x100000) != 0x100000)
goto done;
}
- saa7134_buffer_finish(dev,&dev->ts_q,VIDEOBUF_DONE);
+ saa7134_buffer_finish(dev, &dev->ts_q, VB2_BUF_STATE_DONE);
}
saa7134_buffer_next(dev,&dev->ts_q);
done:
spin_unlock(&dev->slock);
}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c
index 0f34e09d98d..3afbcb70b51 100644
--- a/drivers/media/pci/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/pci/saa7134/saa7134-tvaudio.c
@@ -1079,10 +1079,3 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
EXPORT_SYMBOL(saa_dsp_writel);
EXPORT_SYMBOL(saa7134_tvaudio_setmute);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index e9aa94b807f..c06dbe17a87 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -67,10 +67,10 @@ static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task), 0x00);
saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00);
- saa_writeb(SAA7134_VBI_H_LEN1(task), buf->vb.width & 0xff);
- saa_writeb(SAA7134_VBI_H_LEN2(task), buf->vb.width >> 8);
- saa_writeb(SAA7134_VBI_V_LEN1(task), buf->vb.height & 0xff);
- saa_writeb(SAA7134_VBI_V_LEN2(task), buf->vb.height >> 8);
+ saa_writeb(SAA7134_VBI_H_LEN1(task), dev->vbi_hlen & 0xff);
+ saa_writeb(SAA7134_VBI_H_LEN2(task), dev->vbi_hlen >> 8);
+ saa_writeb(SAA7134_VBI_V_LEN1(task), dev->vbi_vlen & 0xff);
+ saa_writeb(SAA7134_VBI_V_LEN2(task), dev->vbi_vlen >> 8);
saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00);
}
@@ -81,14 +81,14 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
- unsigned long control,base;
+ struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+ unsigned long control, base;
- dprintk("buffer_activate [%p]\n",buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ dprintk("buffer_activate [%p]\n", buf);
buf->top_seen = 0;
- task_init(dev,buf,TASK_A);
- task_init(dev,buf,TASK_B);
+ task_init(dev, buf, TASK_A);
+ task_init(dev, buf, TASK_B);
saa_writeb(SAA7134_OFMT_DATA_A, 0x06);
saa_writeb(SAA7134_OFMT_DATA_B, 0x06);
@@ -96,110 +96,99 @@ static int buffer_activate(struct saa7134_dev *dev,
base = saa7134_buffer_base(buf);
control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
- (buf->pt->dma >> 12);
- saa_writel(SAA7134_RS_BA1(2),base);
- saa_writel(SAA7134_RS_BA2(2),base + buf->vb.size/2);
- saa_writel(SAA7134_RS_PITCH(2),buf->vb.width);
- saa_writel(SAA7134_RS_CONTROL(2),control);
- saa_writel(SAA7134_RS_BA1(3),base);
- saa_writel(SAA7134_RS_BA2(3),base + buf->vb.size/2);
- saa_writel(SAA7134_RS_PITCH(3),buf->vb.width);
- saa_writel(SAA7134_RS_CONTROL(3),control);
+ (dmaq->pt.dma >> 12);
+ saa_writel(SAA7134_RS_BA1(2), base);
+ saa_writel(SAA7134_RS_BA2(2), base + dev->vbi_hlen * dev->vbi_vlen);
+ saa_writel(SAA7134_RS_PITCH(2), dev->vbi_hlen);
+ saa_writel(SAA7134_RS_CONTROL(2), control);
+ saa_writel(SAA7134_RS_BA1(3), base);
+ saa_writel(SAA7134_RS_BA2(3), base + dev->vbi_hlen * dev->vbi_vlen);
+ saa_writel(SAA7134_RS_PITCH(3), dev->vbi_hlen);
+ saa_writel(SAA7134_RS_CONTROL(3), control);
/* start DMA */
saa7134_set_dmabits(dev);
- mod_timer(&dev->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
+ mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT);
return 0;
}
-static int buffer_prepare(struct videobuf_queue *q,
- struct videobuf_buffer *vb,
- enum v4l2_field field)
+static int buffer_prepare(struct vb2_buffer *vb2)
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_dev *dev = fh->dev;
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
- struct saa7134_tvnorm *norm = dev->tvnorm;
- unsigned int lines, llength, size;
- int err;
-
- lines = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
- if (lines > VBI_LINE_COUNT)
- lines = VBI_LINE_COUNT;
- llength = VBI_LINE_LENGTH;
- size = lines * llength * 2;
- if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+ unsigned int size;
+ int ret;
+
+ if (dma->sgl->offset) {
+ pr_err("The buffer is not page-aligned\n");
return -EINVAL;
-
- if (buf->vb.size != size)
- saa7134_dma_free(q,buf);
-
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
- buf->vb.width = llength;
- buf->vb.height = lines;
- buf->vb.size = size;
- buf->pt = &fh->pt_vbi;
-
- err = videobuf_iolock(q,&buf->vb,NULL);
- if (err)
- goto oops;
- err = saa7134_pgtable_build(dev->pci,buf->pt,
- dma->sglist,
- dma->sglen,
- saa7134_buffer_startpage(buf));
- if (err)
- goto oops;
}
- buf->vb.state = VIDEOBUF_PREPARED;
- buf->activate = buffer_activate;
- buf->vb.field = field;
- return 0;
+ size = dev->vbi_hlen * dev->vbi_vlen * 2;
+ if (vb2_plane_size(vb2, 0) < size)
+ return -EINVAL;
+
+ vb2_set_plane_payload(vb2, 0, size);
- oops:
- saa7134_dma_free(q,buf);
- return err;
+ ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
+ return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
+ saa7134_buffer_startpage(buf));
}
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_dev *dev = fh->dev;
- int llength,lines;
-
- lines = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
- llength = VBI_LINE_LENGTH;
- *size = lines * llength * 2;
- if (0 == *count)
- *count = vbibufs;
- *count = saa7134_buffer_count(*size,*count);
+ struct saa7134_dmaqueue *dmaq = q->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ unsigned int size;
+
+ dev->vbi_vlen = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 + 1;
+ if (dev->vbi_vlen > VBI_LINE_COUNT)
+ dev->vbi_vlen = VBI_LINE_COUNT;
+ dev->vbi_hlen = VBI_LINE_LENGTH;
+ size = dev->vbi_hlen * dev->vbi_vlen * 2;
+
+ *nbuffers = saa7134_buffer_count(size, *nbuffers);
+ *nplanes = 1;
+ sizes[0] = size;
return 0;
}
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int buffer_init(struct vb2_buffer *vb2)
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_dev *dev = fh->dev;
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
- saa7134_buffer_queue(dev,&dev->vbi_q,buf);
+ dmaq->curr = NULL;
+ buf->activate = buffer_activate;
+ return 0;
}
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void buffer_finish(struct vb2_buffer *vb2)
{
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
- saa7134_dma_free(q,buf);
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
}
-struct videobuf_queue_ops saa7134_vbi_qops = {
- .buf_setup = buffer_setup,
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .buf_release = buffer_release,
+struct vb2_ops saa7134_vbi_qops = {
+ .queue_setup = queue_setup,
+ .buf_init = buffer_init,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_queue = saa7134_vb2_buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = saa7134_vb2_start_streaming,
+ .stop_streaming = saa7134_vb2_stop_streaming,
};
/* ------------------------------------------------------------------ */
@@ -229,7 +218,6 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
{
spin_lock(&dev->slock);
if (dev->vbi_q.curr) {
- dev->vbi_fieldcount++;
/* make sure we have seen both fields */
if ((status & 0x10) == 0x00) {
dev->vbi_q.curr->top_seen = 1;
@@ -238,18 +226,10 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
if (!dev->vbi_q.curr->top_seen)
goto done;
- dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount;
- saa7134_buffer_finish(dev,&dev->vbi_q,VIDEOBUF_DONE);
+ saa7134_buffer_finish(dev, &dev->vbi_q, VB2_BUF_STATE_DONE);
}
- saa7134_buffer_next(dev,&dev->vbi_q);
+ saa7134_buffer_next(dev, &dev->vbi_q);
done:
spin_unlock(&dev->slock);
}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index e12bbd8c3f0..d3759998076 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -27,11 +27,13 @@
#include <linux/slab.h>
#include <linux/sort.h>
-#include "saa7134-reg.h"
-#include "saa7134.h"
#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
#include <media/saa6588.h>
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
/* ------------------------------------------------------------------ */
unsigned int video_debug;
@@ -369,117 +371,6 @@ static struct saa7134_tvnorm tvnorms[] = {
};
#define TVNORMS ARRAY_SIZE(tvnorms)
-#define V4L2_CID_PRIVATE_INVERT (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_Y_EVEN (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 4)
-
-static const struct v4l2_queryctrl no_ctrl = {
- .name = "42",
- .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl video_ctrls[] = {
- /* --- video --- */
- {
- .id = V4L2_CID_BRIGHTNESS,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 255,
- .step = 1,
- .default_value = 128,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_CONTRAST,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 127,
- .step = 1,
- .default_value = 68,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_SATURATION,
- .name = "Saturation",
- .minimum = 0,
- .maximum = 127,
- .step = 1,
- .default_value = 64,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_HUE,
- .name = "Hue",
- .minimum = -128,
- .maximum = 127,
- .step = 1,
- .default_value = 0,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_HFLIP,
- .name = "Mirror",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },
- /* --- audio --- */
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_AUDIO_VOLUME,
- .name = "Volume",
- .minimum = -15,
- .maximum = 15,
- .step = 1,
- .default_value = 0,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },
- /* --- private --- */
- {
- .id = V4L2_CID_PRIVATE_INVERT,
- .name = "Invert",
- .minimum = 0,
- .maximum = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_PRIVATE_Y_ODD,
- .name = "y offset odd field",
- .minimum = 0,
- .maximum = 128,
- .step = 1,
- .default_value = 0,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_PRIVATE_Y_EVEN,
- .name = "y offset even field",
- .minimum = 0,
- .maximum = 128,
- .step = 1,
- .default_value = 0,
- .type = V4L2_CTRL_TYPE_INTEGER,
- },{
- .id = V4L2_CID_PRIVATE_AUTOMUTE,
- .name = "automute",
- .minimum = 0,
- .maximum = 1,
- .default_value = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- }
-};
-static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
-
-static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
-{
- unsigned int i;
-
- for (i = 0; i < CTRLS; i++)
- if (video_ctrls[i].id == id)
- return video_ctrls+i;
- return NULL;
-}
-
static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
{
unsigned int i;
@@ -490,52 +381,6 @@ static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
return NULL;
}
-/* ----------------------------------------------------------------------- */
-/* resource management */
-
-static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit)
-{
- if (fh->resources & bit)
- /* have it already allocated */
- return 1;
-
- /* is it free? */
- mutex_lock(&dev->lock);
- if (dev->resources & bit) {
- /* no, someone else uses it */
- mutex_unlock(&dev->lock);
- return 0;
- }
- /* it's free, grab it */
- fh->resources |= bit;
- dev->resources |= bit;
- dprintk("res: get %d\n",bit);
- mutex_unlock(&dev->lock);
- return 1;
-}
-
-static int res_check(struct saa7134_fh *fh, unsigned int bit)
-{
- return (fh->resources & bit);
-}
-
-static int res_locked(struct saa7134_dev *dev, unsigned int bit)
-{
- return (dev->resources & bit);
-}
-
-static
-void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
-{
- BUG_ON((fh->resources & bits) != bits);
-
- mutex_lock(&dev->lock);
- fh->resources &= ~bits;
- dev->resources &= ~bits;
- dprintk("res: put %d\n",bits);
- mutex_unlock(&dev->lock);
-}
-
/* ------------------------------------------------------------------ */
static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
@@ -571,19 +416,26 @@ static void video_mux(struct saa7134_dev *dev, int input)
static void saa7134_set_decoder(struct saa7134_dev *dev)
{
- int luma_control, sync_control, mux;
+ int luma_control, sync_control, chroma_ctrl1, mux;
struct saa7134_tvnorm *norm = dev->tvnorm;
mux = card_in(dev, dev->ctl_input).vmux;
luma_control = norm->luma_control;
sync_control = norm->sync_control;
+ chroma_ctrl1 = norm->chroma_ctrl1;
if (mux > 5)
luma_control |= 0x80; /* svideo */
if (noninterlaced || dev->nosignal)
sync_control |= 0x20;
+ /* switch on auto standard detection */
+ sync_control |= SAA7134_SYNC_CTRL_AUFD;
+ chroma_ctrl1 |= SAA7134_CHROMA_CTRL1_AUTO0;
+ chroma_ctrl1 &= ~SAA7134_CHROMA_CTRL1_FCTC;
+ luma_control &= ~SAA7134_LUMA_CTRL_LDEL;
+
/* setup video decoder */
saa_writeb(SAA7134_INCR_DELAY, 0x08);
saa_writeb(SAA7134_ANALOG_IN_CTRL1, 0xc0 | mux);
@@ -606,7 +458,7 @@ static void saa7134_set_decoder(struct saa7134_dev *dev)
dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);
- saa_writeb(SAA7134_CHROMA_CTRL1, norm->chroma_ctrl1);
+ saa_writeb(SAA7134_CHROMA_CTRL1, chroma_ctrl1);
saa_writeb(SAA7134_CHROMA_GAIN, norm->chroma_gain);
saa_writeb(SAA7134_CHROMA_CTRL2, norm->chroma_ctrl2);
@@ -625,10 +477,10 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
saa7134_set_decoder(dev);
if (card_in(dev, dev->ctl_input).tv)
- saa_call_all(dev, core, s_std, dev->tvnorm->id);
+ saa_call_all(dev, video, s_std, dev->tvnorm->id);
/* Set the correct norm for the saa6752hs. This function
does nothing if there is no saa6752hs. */
- saa_call_empress(dev, core, s_std, dev->tvnorm->id);
+ saa_call_empress(dev, video, s_std, dev->tvnorm->id);
}
static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -868,7 +720,7 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win, bool
return 0;
}
-static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
+static int start_preview(struct saa7134_dev *dev)
{
unsigned long base,control,bpl;
int err;
@@ -923,7 +775,7 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
return 0;
}
-static int stop_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
+static int stop_preview(struct saa7134_dev *dev)
{
dev->ovenable = 0;
saa7134_set_dmabits(dev);
@@ -936,35 +788,35 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
+ struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
unsigned long base,control,bpl;
unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */
dprintk("buffer_activate buf=%p\n",buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
buf->top_seen = 0;
- set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
- V4L2_FIELD_HAS_BOTH(buf->vb.field));
- if (buf->fmt->yuv)
+ set_size(dev, TASK_A, dev->width, dev->height,
+ V4L2_FIELD_HAS_BOTH(dev->field));
+ if (dev->fmt->yuv)
saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x03);
else
saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x01);
- saa_writeb(SAA7134_OFMT_VIDEO_A, buf->fmt->pm);
+ saa_writeb(SAA7134_OFMT_VIDEO_A, dev->fmt->pm);
/* DMA: setup channel 0 (= Video Task A0) */
base = saa7134_buffer_base(buf);
- if (buf->fmt->planar)
- bpl = buf->vb.width;
+ if (dev->fmt->planar)
+ bpl = dev->width;
else
- bpl = (buf->vb.width * buf->fmt->depth) / 8;
+ bpl = (dev->width * dev->fmt->depth) / 8;
control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
- (buf->pt->dma >> 12);
- if (buf->fmt->bswap)
+ (dmaq->pt.dma >> 12);
+ if (dev->fmt->bswap)
control |= SAA7134_RS_CONTROL_BSWAP;
- if (buf->fmt->wswap)
+ if (dev->fmt->wswap)
control |= SAA7134_RS_CONTROL_WSWAP;
- if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {
+ if (V4L2_FIELD_HAS_BOTH(dev->field)) {
/* interlaced */
saa_writel(SAA7134_RS_BA1(0),base);
saa_writel(SAA7134_RS_BA2(0),base+bpl);
@@ -977,17 +829,17 @@ static int buffer_activate(struct saa7134_dev *dev,
}
saa_writel(SAA7134_RS_CONTROL(0),control);
- if (buf->fmt->planar) {
+ if (dev->fmt->planar) {
/* DMA: setup channel 4+5 (= planar task A) */
- bpl_uv = bpl >> buf->fmt->hshift;
- lines_uv = buf->vb.height >> buf->fmt->vshift;
- base2 = base + bpl * buf->vb.height;
+ bpl_uv = bpl >> dev->fmt->hshift;
+ lines_uv = dev->height >> dev->fmt->vshift;
+ base2 = base + bpl * dev->height;
base3 = base2 + bpl_uv * lines_uv;
- if (buf->fmt->uvswap)
+ if (dev->fmt->uvswap)
tmp = base2, base2 = base3, base3 = tmp;
dprintk("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",
bpl_uv,lines_uv,base2,base3);
- if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {
+ if (V4L2_FIELD_HAS_BOTH(dev->field)) {
/* interlaced */
saa_writel(SAA7134_RS_BA1(4),base2);
saa_writel(SAA7134_RS_BA2(4),base2+bpl_uv);
@@ -1010,239 +862,208 @@ static int buffer_activate(struct saa7134_dev *dev,
/* start DMA */
saa7134_set_dmabits(dev);
- mod_timer(&dev->video_q.timeout, jiffies+BUFFER_TIMEOUT);
+ mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT);
+ return 0;
+}
+
+static int buffer_init(struct vb2_buffer *vb2)
+{
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+
+ dmaq->curr = NULL;
+ buf->activate = buffer_activate;
return 0;
}
-static int buffer_prepare(struct videobuf_queue *q,
- struct videobuf_buffer *vb,
- enum v4l2_field field)
+static int buffer_prepare(struct vb2_buffer *vb2)
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_dev *dev = fh->dev;
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
unsigned int size;
- int err;
+ int ret;
- /* sanity checks */
- if (NULL == dev->fmt)
- return -EINVAL;
- if (dev->width < 48 ||
- dev->height < 32 ||
- dev->width/4 > dev->crop_current.width ||
- dev->height/4 > dev->crop_current.height ||
- dev->width > dev->crop_bounds.width ||
- dev->height > dev->crop_bounds.height)
+ if (dma->sgl->offset) {
+ pr_err("The buffer is not page-aligned\n");
return -EINVAL;
+ }
size = (dev->width * dev->height * dev->fmt->depth) >> 3;
- if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ if (vb2_plane_size(vb2, 0) < size)
return -EINVAL;
- dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
- vb->i, dev->width, dev->height, size, v4l2_field_names[field],
- dev->fmt->name);
- if (buf->vb.width != dev->width ||
- buf->vb.height != dev->height ||
- buf->vb.size != size ||
- buf->vb.field != field ||
- buf->fmt != dev->fmt) {
- saa7134_dma_free(q,buf);
- }
+ vb2_set_plane_payload(vb2, 0, size);
+ vb2->v4l2_buf.field = dev->field;
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
- buf->vb.width = dev->width;
- buf->vb.height = dev->height;
- buf->vb.size = size;
- buf->vb.field = field;
- buf->fmt = dev->fmt;
- buf->pt = &fh->pt_cap;
- dev->video_q.curr = NULL;
-
- err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
- if (err)
- goto oops;
- err = saa7134_pgtable_build(dev->pci,buf->pt,
- dma->sglist,
- dma->sglen,
- saa7134_buffer_startpage(buf));
- if (err)
- goto oops;
- }
- buf->vb.state = VIDEOBUF_PREPARED;
- buf->activate = buffer_activate;
- return 0;
-
- oops:
- saa7134_dma_free(q,buf);
- return err;
+ ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
+ return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
+ saa7134_buffer_startpage(buf));
}
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+static void buffer_finish(struct vb2_buffer *vb2)
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
- *size = dev->fmt->depth * dev->width * dev->height >> 3;
- if (0 == *count)
- *count = gbuffers;
- *count = saa7134_buffer_count(*size,*count);
- return 0;
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
}
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dmaqueue *dmaq = q->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ int size = dev->fmt->depth * dev->width * dev->height >> 3;
+
+ if (dev->width < 48 ||
+ dev->height < 32 ||
+ dev->width/4 > dev->crop_current.width ||
+ dev->height/4 > dev->crop_current.height ||
+ dev->width > dev->crop_bounds.width ||
+ dev->height > dev->crop_bounds.height)
+ return -EINVAL;
- saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf);
+ *nbuffers = saa7134_buffer_count(size, *nbuffers);
+ *nplanes = 1;
+ sizes[0] = size;
+ return 0;
}
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+/*
+ * move buffer to hardware queue
+ */
+void saa7134_vb2_buffer_queue(struct vb2_buffer *vb)
{
- struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb2);
- saa7134_dma_free(q,buf);
+ saa7134_buffer_queue(dev, dmaq, buf);
}
+EXPORT_SYMBOL_GPL(saa7134_vb2_buffer_queue);
-static struct videobuf_queue_ops video_qops = {
- .buf_setup = buffer_setup,
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .buf_release = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
+int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
{
- const struct v4l2_queryctrl* ctrl;
+ struct saa7134_dmaqueue *dmaq = vq->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
- ctrl = ctrl_by_id(c->id);
- if (NULL == ctrl)
- return -EINVAL;
- switch (c->id) {
- case V4L2_CID_BRIGHTNESS:
- c->value = dev->ctl_bright;
- break;
- case V4L2_CID_HUE:
- c->value = dev->ctl_hue;
- break;
- case V4L2_CID_CONTRAST:
- c->value = dev->ctl_contrast;
- break;
- case V4L2_CID_SATURATION:
- c->value = dev->ctl_saturation;
- break;
- case V4L2_CID_AUDIO_MUTE:
- c->value = dev->ctl_mute;
- break;
- case V4L2_CID_AUDIO_VOLUME:
- c->value = dev->ctl_volume;
- break;
- case V4L2_CID_PRIVATE_INVERT:
- c->value = dev->ctl_invert;
- break;
- case V4L2_CID_HFLIP:
- c->value = dev->ctl_mirror;
- break;
- case V4L2_CID_PRIVATE_Y_EVEN:
- c->value = dev->ctl_y_even;
- break;
- case V4L2_CID_PRIVATE_Y_ODD:
- c->value = dev->ctl_y_odd;
- break;
- case V4L2_CID_PRIVATE_AUTOMUTE:
- c->value = dev->ctl_automute;
- break;
- default:
- return -EINVAL;
+ /*
+ * Planar video capture and TS share the same DMA channel,
+ * so only one can be active at a time.
+ */
+ if (card_is_empress(dev) && vb2_is_busy(&dev->empress_vbq) &&
+ dmaq == &dev->video_q && dev->fmt->planar) {
+ struct saa7134_buf *buf, *tmp;
+
+ list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
+ list_del(&buf->entry);
+ vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+ }
+ if (dmaq->curr) {
+ vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+ dmaq->curr = NULL;
+ }
+ return -EBUSY;
}
+
+ /* The SAA7134 has a 1K FIFO; the datasheet suggests that when
+ * configured conservatively, there's 22 usec of buffering for video.
+ * We therefore request a DMA latency of 20 usec, giving us 2 usec of
+ * margin in case the FIFO is configured differently to the datasheet.
+ * Unfortunately, I lack register-level documentation to check the
+ * Linux FIFO setup and confirm the perfect value.
+ */
+ if ((dmaq == &dev->video_q && !vb2_is_streaming(&dev->vbi_vbq)) ||
+ (dmaq == &dev->vbi_q && !vb2_is_streaming(&dev->video_vbq)))
+ pm_qos_add_request(&dev->qos_request,
+ PM_QOS_CPU_DMA_LATENCY, 20);
+ dmaq->seq_nr = 0;
+
return 0;
}
-EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);
-static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+void saa7134_vb2_stop_streaming(struct vb2_queue *vq)
{
- struct saa7134_fh *fh = priv;
+ struct saa7134_dmaqueue *dmaq = vq->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+
+ saa7134_stop_streaming(dev, dmaq);
- return saa7134_g_ctrl_internal(fh->dev, fh, c);
+ if ((dmaq == &dev->video_q && !vb2_is_streaming(&dev->vbi_vbq)) ||
+ (dmaq == &dev->vbi_q && !vb2_is_streaming(&dev->video_vbq)))
+ pm_qos_remove_request(&dev->qos_request);
}
-int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
+static struct vb2_ops vb2_qops = {
+ .queue_setup = queue_setup,
+ .buf_init = buffer_init,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_queue = saa7134_vb2_buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = saa7134_vb2_start_streaming,
+ .stop_streaming = saa7134_vb2_stop_streaming,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int saa7134_s_ctrl(struct v4l2_ctrl *ctrl)
{
- const struct v4l2_queryctrl* ctrl;
+ struct saa7134_dev *dev = container_of(ctrl->handler, struct saa7134_dev, ctrl_handler);
unsigned long flags;
int restart_overlay = 0;
- int err;
-
- err = -EINVAL;
- mutex_lock(&dev->lock);
-
- ctrl = ctrl_by_id(c->id);
- if (NULL == ctrl)
- goto error;
-
- dprintk("set_control name=%s val=%d\n",ctrl->name,c->value);
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_BOOLEAN:
- case V4L2_CTRL_TYPE_MENU:
- case V4L2_CTRL_TYPE_INTEGER:
- if (c->value < ctrl->minimum)
- c->value = ctrl->minimum;
- if (c->value > ctrl->maximum)
- c->value = ctrl->maximum;
- break;
- default:
- /* nothing */;
- }
- switch (c->id) {
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
- dev->ctl_bright = c->value;
- saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
+ dev->ctl_bright = ctrl->val;
+ saa_writeb(SAA7134_DEC_LUMA_BRIGHT, ctrl->val);
break;
case V4L2_CID_HUE:
- dev->ctl_hue = c->value;
- saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);
+ dev->ctl_hue = ctrl->val;
+ saa_writeb(SAA7134_DEC_CHROMA_HUE, ctrl->val);
break;
case V4L2_CID_CONTRAST:
- dev->ctl_contrast = c->value;
+ dev->ctl_contrast = ctrl->val;
saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
break;
case V4L2_CID_SATURATION:
- dev->ctl_saturation = c->value;
+ dev->ctl_saturation = ctrl->val;
saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
break;
case V4L2_CID_AUDIO_MUTE:
- dev->ctl_mute = c->value;
+ dev->ctl_mute = ctrl->val;
saa7134_tvaudio_setmute(dev);
break;
case V4L2_CID_AUDIO_VOLUME:
- dev->ctl_volume = c->value;
+ dev->ctl_volume = ctrl->val;
saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
break;
case V4L2_CID_PRIVATE_INVERT:
- dev->ctl_invert = c->value;
+ dev->ctl_invert = ctrl->val;
saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
break;
case V4L2_CID_HFLIP:
- dev->ctl_mirror = c->value;
+ dev->ctl_mirror = ctrl->val;
restart_overlay = 1;
break;
case V4L2_CID_PRIVATE_Y_EVEN:
- dev->ctl_y_even = c->value;
+ dev->ctl_y_even = ctrl->val;
restart_overlay = 1;
break;
case V4L2_CID_PRIVATE_Y_ODD:
- dev->ctl_y_odd = c->value;
+ dev->ctl_y_odd = ctrl->val;
restart_overlay = 1;
break;
case V4L2_CID_PRIVATE_AUTOMUTE:
@@ -1252,7 +1073,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str
tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &dev->tda9887_conf;
- dev->ctl_automute = c->value;
+ dev->ctl_automute = ctrl->val;
if (dev->tda9887_conf) {
if (dev->ctl_automute)
dev->tda9887_conf |= TDA9887_AUTOMUTE;
@@ -1264,210 +1085,70 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str
break;
}
default:
- goto error;
+ return -EINVAL;
}
- if (restart_overlay && fh && res_check(fh, RESOURCE_OVERLAY)) {
- spin_lock_irqsave(&dev->slock,flags);
- stop_preview(dev,fh);
- start_preview(dev,fh);
- spin_unlock_irqrestore(&dev->slock,flags);
+ if (restart_overlay && dev->overlay_owner) {
+ spin_lock_irqsave(&dev->slock, flags);
+ stop_preview(dev);
+ start_preview(dev);
+ spin_unlock_irqrestore(&dev->slock, flags);
}
- err = 0;
-
-error:
- mutex_unlock(&dev->lock);
- return err;
-}
-EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);
-
-static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
-{
- struct saa7134_fh *fh = f;
-
- return saa7134_s_ctrl_internal(fh->dev, fh, c);
+ return 0;
}
/* ------------------------------------------------------------------ */
-static struct videobuf_queue *saa7134_queue(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
- struct saa7134_fh *fh = file->private_data;
- struct videobuf_queue *q = NULL;
-
- switch (vdev->vfl_type) {
- case VFL_TYPE_GRABBER:
- q = &fh->cap;
- break;
- case VFL_TYPE_VBI:
- q = &fh->vbi;
- break;
- default:
- BUG();
- }
- return q;
-}
-
-static int saa7134_resource(struct file *file)
+static inline struct vb2_queue *saa7134_queue(struct file *file)
{
- struct video_device *vdev = video_devdata(file);
-
- if (vdev->vfl_type == VFL_TYPE_GRABBER)
- return RESOURCE_VIDEO;
-
- if (vdev->vfl_type == VFL_TYPE_VBI)
- return RESOURCE_VBI;
-
- BUG();
- return 0;
+ return video_devdata(file)->queue;
}
static int video_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct saa7134_dev *dev = video_drvdata(file);
- struct saa7134_fh *fh;
-
- /* allocate + initialize per filehandle data */
- fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh)
- return -ENOMEM;
-
- v4l2_fh_init(&fh->fh, vdev);
- file->private_data = fh;
- fh->dev = dev;
-
- videobuf_queue_sg_init(&fh->cap, &video_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_INTERLACED,
- sizeof(struct saa7134_buf),
- fh, NULL);
- videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VBI_CAPTURE,
- V4L2_FIELD_SEQ_TB,
- sizeof(struct saa7134_buf),
- fh, NULL);
- saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
- saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
+ int ret = v4l2_fh_open(file);
+
+ if (ret < 0)
+ return ret;
+ mutex_lock(&dev->lock);
if (vdev->vfl_type == VFL_TYPE_RADIO) {
/* switch to radio mode */
- saa7134_tvaudio_setinput(dev,&card(dev).radio);
+ saa7134_tvaudio_setinput(dev, &card(dev).radio);
saa_call_all(dev, tuner, s_radio);
} else {
/* switch to video/vbi mode */
- video_mux(dev,dev->ctl_input);
+ video_mux(dev, dev->ctl_input);
}
- v4l2_fh_add(&fh->fh);
+ mutex_unlock(&dev->lock);
return 0;
}
-static ssize_t
-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
- struct video_device *vdev = video_devdata(file);
- struct saa7134_fh *fh = file->private_data;
-
- switch (vdev->vfl_type) {
- case VFL_TYPE_GRABBER:
- if (res_locked(fh->dev,RESOURCE_VIDEO))
- return -EBUSY;
- return videobuf_read_one(saa7134_queue(file),
- data, count, ppos,
- file->f_flags & O_NONBLOCK);
- case VFL_TYPE_VBI:
- if (!res_get(fh->dev,fh,RESOURCE_VBI))
- return -EBUSY;
- return videobuf_read_stream(saa7134_queue(file),
- data, count, ppos, 1,
- file->f_flags & O_NONBLOCK);
- break;
- default:
- BUG();
- return 0;
- }
-}
-
-static unsigned int
-video_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct video_device *vdev = video_devdata(file);
- struct saa7134_fh *fh = file->private_data;
- struct videobuf_buffer *buf = NULL;
- unsigned int rc = 0;
-
- if (vdev->vfl_type == VFL_TYPE_VBI)
- return videobuf_poll_stream(file, &fh->vbi, wait);
-
- if (res_check(fh,RESOURCE_VIDEO)) {
- mutex_lock(&fh->cap.vb_lock);
- if (!list_empty(&fh->cap.stream))
- buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
- } else {
- mutex_lock(&fh->cap.vb_lock);
- if (UNSET == fh->cap.read_off) {
- /* need to capture a new frame */
- if (res_locked(fh->dev,RESOURCE_VIDEO))
- goto err;
- if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field))
- goto err;
- fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
- fh->cap.read_off = 0;
- }
- buf = fh->cap.read_buf;
- }
-
- if (!buf)
- goto err;
-
- poll_wait(file, &buf->done, wait);
- if (buf->state == VIDEOBUF_DONE ||
- buf->state == VIDEOBUF_ERROR)
- rc = POLLIN|POLLRDNORM;
- mutex_unlock(&fh->cap.vb_lock);
- return rc;
-
-err:
- mutex_unlock(&fh->cap.vb_lock);
- return POLLERR;
-}
-
static int video_release(struct file *file)
{
struct video_device *vdev = video_devdata(file);
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
+ struct v4l2_fh *fh = file->private_data;
struct saa6588_command cmd;
unsigned long flags;
+ mutex_lock(&dev->lock);
saa7134_tvaudio_close(dev);
/* turn off overlay */
- if (res_check(fh, RESOURCE_OVERLAY)) {
+ if (fh == dev->overlay_owner) {
spin_lock_irqsave(&dev->slock,flags);
- stop_preview(dev,fh);
+ stop_preview(dev);
spin_unlock_irqrestore(&dev->slock,flags);
- res_free(dev,fh,RESOURCE_OVERLAY);
+ dev->overlay_owner = NULL;
}
- /* stop video capture */
- if (res_check(fh, RESOURCE_VIDEO)) {
- videobuf_streamoff(&fh->cap);
- res_free(dev,fh,RESOURCE_VIDEO);
- }
- if (fh->cap.read_buf) {
- buffer_release(&fh->cap,fh->cap.read_buf);
- kfree(fh->cap.read_buf);
- }
-
- /* stop vbi capture */
- if (res_check(fh, RESOURCE_VBI)) {
- videobuf_stop(&fh->vbi);
- res_free(dev,fh,RESOURCE_VBI);
- }
+ if (vdev->vfl_type == VFL_TYPE_RADIO)
+ v4l2_fh_release(file);
+ else
+ _vb2_fop_release(file, NULL);
/* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/
saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0);
@@ -1478,54 +1159,44 @@ static int video_release(struct file *file)
saa_call_all(dev, core, s_power, 0);
if (vdev->vfl_type == VFL_TYPE_RADIO)
saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
+ mutex_unlock(&dev->lock);
- /* free stuff */
- videobuf_mmap_free(&fh->cap);
- videobuf_mmap_free(&fh->vbi);
- saa7134_pgtable_free(dev->pci,&fh->pt_cap);
- saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
-
- v4l2_fh_del(&fh->fh);
- v4l2_fh_exit(&fh->fh);
- file->private_data = NULL;
- kfree(fh);
return 0;
}
-static int video_mmap(struct file *file, struct vm_area_struct * vma)
-{
- return videobuf_mmap_mapper(saa7134_queue(file), vma);
-}
-
static ssize_t radio_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
{
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct saa6588_command cmd;
cmd.block_count = count/3;
+ cmd.nonblocking = file->f_flags & O_NONBLOCK;
cmd.buffer = data;
cmd.instance = file;
cmd.result = -ENODEV;
+ mutex_lock(&dev->lock);
saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd);
+ mutex_unlock(&dev->lock);
return cmd.result;
}
static unsigned int radio_poll(struct file *file, poll_table *wait)
{
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct saa6588_command cmd;
+ unsigned int rc = v4l2_ctrl_poll(file, wait);
cmd.instance = file;
cmd.event_list = wait;
- cmd.result = -ENODEV;
+ cmd.result = 0;
+ mutex_lock(&dev->lock);
saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd);
+ mutex_unlock(&dev->lock);
- return cmd.result;
+ return rc | cmd.result;
}
/* ------------------------------------------------------------------ */
@@ -1533,8 +1204,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct saa7134_tvnorm *norm = dev->tvnorm;
memset(&f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
@@ -1554,12 +1224,11 @@ static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
- f->fmt.pix.field = fh->cap.field;
+ f->fmt.pix.field = dev->field;
f->fmt.pix.pixelformat = dev->fmt->fourcc;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -1573,8 +1242,7 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_clip __user *clips = f->fmt.win.clips;
u32 clipcount = f->fmt.win.clipcount;
int err = 0;
@@ -1584,7 +1252,6 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
return -EINVAL;
}
- mutex_lock(&dev->lock);
f->fmt.win = dev->win;
f->fmt.win.clips = clips;
if (clips == NULL)
@@ -1598,7 +1265,6 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
sizeof(struct v4l2_rect)))
err = -EFAULT;
}
- mutex_unlock(&dev->lock);
return err;
}
@@ -1606,8 +1272,7 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct saa7134_format *fmt;
enum v4l2_field field;
unsigned int maxw, maxh;
@@ -1658,8 +1323,7 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (saa7134_no_overlay > 0) {
printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
@@ -1674,26 +1338,24 @@ static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
int err;
err = saa7134_try_fmt_vid_cap(file, priv, f);
if (0 != err)
return err;
- dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
- dev->width = f->fmt.pix.width;
- dev->height = f->fmt.pix.height;
- fh->cap.field = f->fmt.pix.field;
+ dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ dev->width = f->fmt.pix.width;
+ dev->height = f->fmt.pix.height;
+ dev->field = f->fmt.pix.field;
return 0;
}
static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
int err;
unsigned long flags;
@@ -1707,48 +1369,26 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
if (0 != err)
return err;
- mutex_lock(&dev->lock);
-
dev->win = f->fmt.win;
dev->nclips = f->fmt.win.clipcount;
if (copy_from_user(dev->clips, f->fmt.win.clips,
- sizeof(struct v4l2_clip) * dev->nclips)) {
- mutex_unlock(&dev->lock);
+ sizeof(struct v4l2_clip) * dev->nclips))
return -EFAULT;
- }
- if (res_check(fh, RESOURCE_OVERLAY)) {
+ if (priv == dev->overlay_owner) {
spin_lock_irqsave(&dev->slock, flags);
- stop_preview(dev, fh);
- start_preview(dev, fh);
+ stop_preview(dev);
+ start_preview(dev);
spin_unlock_irqrestore(&dev->slock, flags);
}
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c)
-{
- const struct v4l2_queryctrl *ctrl;
-
- if ((c->id < V4L2_CID_BASE ||
- c->id >= V4L2_CID_LASTP1) &&
- (c->id < V4L2_CID_PRIVATE_BASE ||
- c->id >= V4L2_CID_PRIVATE_LASTP1))
- return -EINVAL;
- ctrl = ctrl_by_id(c->id);
- *c = (NULL != ctrl) ? *ctrl : no_ctrl;
return 0;
}
-EXPORT_SYMBOL_GPL(saa7134_queryctrl);
-static int saa7134_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
unsigned int n;
n = i->index;
@@ -1768,43 +1408,41 @@ static int saa7134_enum_input(struct file *file, void *priv,
if (0 != (v1 & 0x40))
i->status |= V4L2_IN_ST_NO_H_LOCK;
if (0 != (v2 & 0x40))
- i->status |= V4L2_IN_ST_NO_SYNC;
+ i->status |= V4L2_IN_ST_NO_SIGNAL;
if (0 != (v2 & 0x0e))
i->status |= V4L2_IN_ST_MACROVISION;
}
i->std = SAA7134_NORMS;
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_enum_input);
-static int saa7134_g_input(struct file *file, void *priv, unsigned int *i)
+int saa7134_g_input(struct file *file, void *priv, unsigned int *i)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
*i = dev->ctl_input;
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_g_input);
-static int saa7134_s_input(struct file *file, void *priv, unsigned int i)
+int saa7134_s_input(struct file *file, void *priv, unsigned int i)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (i >= SAA7134_INPUT_MAX)
return -EINVAL;
if (NULL == card_in(dev, i).name)
return -EINVAL;
- mutex_lock(&dev->lock);
video_mux(dev, i);
- mutex_unlock(&dev->lock);
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_s_input);
-static int saa7134_querycap(struct file *file, void *priv,
+int saa7134_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct video_device *vdev = video_devdata(file);
u32 radio_caps, video_caps, vbi_caps;
@@ -1824,7 +1462,7 @@ static int saa7134_querycap(struct file *file, void *priv,
radio_caps |= V4L2_CAP_RDS_CAPTURE;
video_caps = V4L2_CAP_VIDEO_CAPTURE;
- if (saa7134_no_overlay <= 0)
+ if (saa7134_no_overlay <= 0 && !is_empress(file))
video_caps |= V4L2_CAP_VIDEO_OVERLAY;
vbi_caps = V4L2_CAP_VBI_CAPTURE;
@@ -1850,14 +1488,17 @@ static int saa7134_querycap(struct file *file, void *priv,
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_querycap);
-int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id id)
+int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
{
+ struct saa7134_dev *dev = video_drvdata(file);
+ struct v4l2_fh *fh = priv;
unsigned long flags;
unsigned int i;
v4l2_std_id fixup;
- if (!fh && res_locked(dev, RESOURCE_OVERLAY)) {
+ if (is_empress(file) && dev->overlay_owner) {
/* Don't change the std from the mpeg device
if overlay is active. */
return -EBUSY;
@@ -1896,47 +1537,66 @@ int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_
id = tvnorms[i].id;
- mutex_lock(&dev->lock);
- if (fh && res_check(fh, RESOURCE_OVERLAY)) {
+ if (!is_empress(file) && fh == dev->overlay_owner) {
spin_lock_irqsave(&dev->slock, flags);
- stop_preview(dev, fh);
+ stop_preview(dev);
spin_unlock_irqrestore(&dev->slock, flags);
set_tvnorm(dev, &tvnorms[i]);
spin_lock_irqsave(&dev->slock, flags);
- start_preview(dev, fh);
+ start_preview(dev);
spin_unlock_irqrestore(&dev->slock, flags);
} else
set_tvnorm(dev, &tvnorms[i]);
saa7134_tvaudio_do_scan(dev);
- mutex_unlock(&dev->lock);
return 0;
}
-EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+EXPORT_SYMBOL_GPL(saa7134_s_std);
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id)
+int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
{
- struct saa7134_fh *fh = priv;
+ struct saa7134_dev *dev = video_drvdata(file);
- return saa7134_s_std_internal(fh->dev, fh, id);
+ *id = dev->tvnorm->id;
+ return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_g_std);
-static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
+static v4l2_std_id saa7134_read_std(struct saa7134_dev *dev)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ static v4l2_std_id stds[] = {
+ V4L2_STD_UNKNOWN,
+ V4L2_STD_NTSC,
+ V4L2_STD_PAL,
+ V4L2_STD_SECAM };
- *id = dev->tvnorm->id;
+ v4l2_std_id result = 0;
+
+ u8 st1 = saa_readb(SAA7134_STATUS_VIDEO1);
+ u8 st2 = saa_readb(SAA7134_STATUS_VIDEO2);
+
+ if (!(st2 & 0x1)) /* RDCAP == 0 */
+ result = V4L2_STD_UNKNOWN;
+ else
+ result = stds[st1 & 0x03];
+
+ return result;
+}
+
+int saa7134_querystd(struct file *file, void *priv, v4l2_std_id *std)
+{
+ struct saa7134_dev *dev = video_drvdata(file);
+ *std &= saa7134_read_std(dev);
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_querystd);
static int saa7134_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cap)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
@@ -1958,8 +1618,7 @@ static int saa7134_cropcap(struct file *file, void *priv,
static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
{
- struct saa7134_fh *fh = f;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
@@ -1970,22 +1629,17 @@ static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
{
- struct saa7134_fh *fh = f;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_rect *b = &dev->crop_bounds;
struct v4l2_rect *c = &dev->crop_current;
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
return -EINVAL;
- if (crop->c.height < 0)
- return -EINVAL;
- if (crop->c.width < 0)
- return -EINVAL;
- if (res_locked(fh->dev, RESOURCE_OVERLAY))
+ if (dev->overlay_owner)
return -EBUSY;
- if (res_locked(fh->dev, RESOURCE_VIDEO))
+ if (vb2_is_streaming(&dev->video_vbq))
return -EBUSY;
*c = crop->c;
@@ -2005,11 +1659,10 @@ static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *cr
return 0;
}
-static int saa7134_g_tuner(struct file *file, void *priv,
+int saa7134_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
int n;
if (0 != t->index)
@@ -2036,12 +1689,12 @@ static int saa7134_g_tuner(struct file *file, void *priv,
t->signal = 0xffff;
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_g_tuner);
-static int saa7134_s_tuner(struct file *file, void *priv,
+int saa7134_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
int rx, mode;
if (0 != t->index)
@@ -2057,12 +1710,12 @@ static int saa7134_s_tuner(struct file *file, void *priv,
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_s_tuner);
-static int saa7134_g_frequency(struct file *file, void *priv,
+int saa7134_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (0 != f->tuner)
return -EINVAL;
@@ -2071,23 +1724,22 @@ static int saa7134_g_frequency(struct file *file, void *priv,
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_g_frequency);
-static int saa7134_s_frequency(struct file *file, void *priv,
+int saa7134_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (0 != f->tuner)
return -EINVAL;
- mutex_lock(&dev->lock);
saa_call_all(dev, tuner, s_frequency, f);
saa7134_tvaudio_do_scan(dev);
- mutex_unlock(&dev->lock);
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_s_frequency);
static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
@@ -2125,8 +1777,7 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv,
static int saa7134_g_fbuf(struct file *file, void *f,
struct v4l2_framebuffer *fb)
{
- struct saa7134_fh *fh = f;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
*fb = dev->ovbuf;
fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
@@ -2137,8 +1788,7 @@ static int saa7134_g_fbuf(struct file *file, void *f,
static int saa7134_s_fbuf(struct file *file, void *f,
const struct v4l2_framebuffer *fb)
{
- struct saa7134_fh *fh = f;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
struct saa7134_format *fmt;
if (!capable(CAP_SYS_ADMIN) &&
@@ -2159,10 +1809,9 @@ static int saa7134_s_fbuf(struct file *file, void *f,
return 0;
}
-static int saa7134_overlay(struct file *file, void *f, unsigned int on)
+static int saa7134_overlay(struct file *file, void *priv, unsigned int on)
{
- struct saa7134_fh *fh = f;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
unsigned long flags;
if (on) {
@@ -2171,93 +1820,29 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on)
return -EINVAL;
}
- if (!res_get(dev, fh, RESOURCE_OVERLAY))
+ if (dev->overlay_owner && priv != dev->overlay_owner)
return -EBUSY;
+ dev->overlay_owner = priv;
spin_lock_irqsave(&dev->slock, flags);
- start_preview(dev, fh);
+ start_preview(dev);
spin_unlock_irqrestore(&dev->slock, flags);
}
if (!on) {
- if (!res_check(fh, RESOURCE_OVERLAY))
+ if (priv != dev->overlay_owner)
return -EINVAL;
spin_lock_irqsave(&dev->slock, flags);
- stop_preview(dev, fh);
+ stop_preview(dev);
spin_unlock_irqrestore(&dev->slock, flags);
- res_free(dev, fh, RESOURCE_OVERLAY);
+ dev->overlay_owner = NULL;
}
return 0;
}
-static int saa7134_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *p)
-{
- return videobuf_reqbufs(saa7134_queue(file), p);
-}
-
-static int saa7134_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *b)
-{
- return videobuf_querybuf(saa7134_queue(file), b);
-}
-
-static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- return videobuf_qbuf(saa7134_queue(file), b);
-}
-
-static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
- return videobuf_dqbuf(saa7134_queue(file), b,
- file->f_flags & O_NONBLOCK);
-}
-
-static int saa7134_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
- int res = saa7134_resource(file);
-
- if (!res_get(dev, fh, res))
- return -EBUSY;
-
- /* The SAA7134 has a 1K FIFO; the datasheet suggests that when
- * configured conservatively, there's 22 usec of buffering for video.
- * We therefore request a DMA latency of 20 usec, giving us 2 usec of
- * margin in case the FIFO is configured differently to the datasheet.
- * Unfortunately, I lack register-level documentation to check the
- * Linux FIFO setup and confirm the perfect value.
- */
- pm_qos_add_request(&dev->qos_request,
- PM_QOS_CPU_DMA_LATENCY,
- 20);
-
- return videobuf_streamon(saa7134_queue(file));
-}
-
-static int saa7134_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- int err;
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
- int res = saa7134_resource(file);
-
- pm_qos_remove_request(&dev->qos_request);
-
- err = videobuf_streamoff(saa7134_queue(file));
- if (err < 0)
- return err;
- res_free(dev, fh, res);
- return 0;
-}
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register (struct file *file, void *priv,
struct v4l2_dbg_register *reg)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
reg->val = saa_readb(reg->reg & 0xffffff);
reg->size = 1;
@@ -2267,8 +1852,7 @@ static int vidioc_g_register (struct file *file, void *priv,
static int vidioc_s_register (struct file *file, void *priv,
const struct v4l2_dbg_register *reg)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
saa_writeb(reg->reg & 0xffffff, reg->val);
return 0;
@@ -2278,8 +1862,7 @@ static int vidioc_s_register (struct file *file, void *priv,
static int radio_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (0 != t->index)
return -EINVAL;
@@ -2298,8 +1881,7 @@ static int radio_g_tuner(struct file *file, void *priv,
static int radio_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct saa7134_fh *fh = file->private_data;
- struct saa7134_dev *dev = fh->dev;
+ struct saa7134_dev *dev = video_drvdata(file);
if (0 != t->index)
return -EINVAL;
@@ -2308,59 +1890,15 @@ static int radio_s_tuner(struct file *file, void *priv,
return 0;
}
-static int radio_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
-{
- if (i->index != 0)
- return -EINVAL;
-
- strcpy(i->name, "Radio");
- i->type = V4L2_INPUT_TYPE_TUNER;
-
- return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
- return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id norm)
-{
- return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *c)
-{
- const struct v4l2_queryctrl *ctrl;
-
- if (c->id < V4L2_CID_BASE ||
- c->id >= V4L2_CID_LASTP1)
- return -EINVAL;
- if (c->id == V4L2_CID_AUDIO_MUTE) {
- ctrl = ctrl_by_id(c->id);
- *c = *ctrl;
- } else
- *c = no_ctrl;
- return 0;
-}
-
static const struct v4l2_file_operations video_fops =
{
.owner = THIS_MODULE,
.open = video_open,
.release = video_release,
- .read = video_read,
- .poll = video_poll,
- .mmap = video_mmap,
- .ioctl = video_ioctl2,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .unlocked_ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -2377,20 +1915,18 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
.vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
.vidioc_cropcap = saa7134_cropcap,
- .vidioc_reqbufs = saa7134_reqbufs,
- .vidioc_querybuf = saa7134_querybuf,
- .vidioc_qbuf = saa7134_qbuf,
- .vidioc_dqbuf = saa7134_dqbuf,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_s_std = saa7134_s_std,
.vidioc_g_std = saa7134_g_std,
+ .vidioc_querystd = saa7134_querystd,
.vidioc_enum_input = saa7134_enum_input,
.vidioc_g_input = saa7134_g_input,
.vidioc_s_input = saa7134_s_input,
- .vidioc_queryctrl = saa7134_queryctrl,
- .vidioc_g_ctrl = saa7134_g_ctrl,
- .vidioc_s_ctrl = saa7134_s_ctrl,
- .vidioc_streamon = saa7134_streamon,
- .vidioc_streamoff = saa7134_streamoff,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_g_tuner = saa7134_g_tuner,
.vidioc_s_tuner = saa7134_s_tuner,
.vidioc_g_crop = saa7134_g_crop,
@@ -2404,6 +1940,9 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_g_register = vidioc_g_register,
.vidioc_s_register = vidioc_s_register,
#endif
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
static const struct v4l2_file_operations radio_fops = {
@@ -2411,23 +1950,18 @@ static const struct v4l2_file_operations radio_fops = {
.open = video_open,
.read = radio_read,
.release = video_release,
- .ioctl = video_ioctl2,
+ .unlocked_ioctl = video_ioctl2,
.poll = radio_poll,
};
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
.vidioc_querycap = saa7134_querycap,
.vidioc_g_tuner = radio_g_tuner,
- .vidioc_enum_input = radio_enum_input,
.vidioc_s_tuner = radio_s_tuner,
- .vidioc_s_input = radio_s_input,
- .vidioc_s_std = radio_s_std,
- .vidioc_queryctrl = radio_queryctrl,
- .vidioc_g_input = radio_g_input,
- .vidioc_g_ctrl = saa7134_g_ctrl,
- .vidioc_s_ctrl = saa7134_s_ctrl,
.vidioc_g_frequency = saa7134_g_frequency,
.vidioc_s_frequency = saa7134_s_frequency,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
/* ----------------------------------------------------------- */
@@ -2446,8 +1980,57 @@ struct video_device saa7134_radio_template = {
.ioctl_ops = &radio_ioctl_ops,
};
+static const struct v4l2_ctrl_ops saa7134_ctrl_ops = {
+ .s_ctrl = saa7134_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_invert = {
+ .ops = &saa7134_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_INVERT,
+ .name = "Invert",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_y_odd = {
+ .ops = &saa7134_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_Y_ODD,
+ .name = "Y Offset Odd Field",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 128,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_y_even = {
+ .ops = &saa7134_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_Y_EVEN,
+ .name = "Y Offset Even Field",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 0,
+ .max = 128,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config saa7134_ctrl_automute = {
+ .ops = &saa7134_ctrl_ops,
+ .id = V4L2_CID_PRIVATE_AUTOMUTE,
+ .name = "Automute",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+ .def = 1,
+};
+
int saa7134_video_init1(struct saa7134_dev *dev)
{
+ struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
+ struct vb2_queue *q;
+ int ret;
+
/* sanitycheck insmod options */
if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
gbuffers = 2;
@@ -2455,17 +2038,38 @@ int saa7134_video_init1(struct saa7134_dev *dev)
gbufsize = gbufsize_max;
gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
- /* put some sensible defaults into the data structures ... */
- dev->ctl_bright = ctrl_by_id(V4L2_CID_BRIGHTNESS)->default_value;
- dev->ctl_contrast = ctrl_by_id(V4L2_CID_CONTRAST)->default_value;
- dev->ctl_hue = ctrl_by_id(V4L2_CID_HUE)->default_value;
- dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
- dev->ctl_volume = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
- dev->ctl_mute = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
- dev->ctl_invert = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
- dev->ctl_automute = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
-
- if (dev->tda9887_conf && dev->ctl_automute)
+ v4l2_ctrl_handler_init(hdl, 11);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 127, 1, 68);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 127, 1, 64);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_HUE, -128, 127, 1, 0);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(hdl, &saa7134_ctrl_ops,
+ V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0);
+ v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_invert, NULL);
+ v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_y_odd, NULL);
+ v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_y_even, NULL);
+ v4l2_ctrl_new_custom(hdl, &saa7134_ctrl_automute, NULL);
+ if (hdl->error)
+ return hdl->error;
+ if (card_has_radio(dev)) {
+ hdl = &dev->radio_ctrl_handler;
+ v4l2_ctrl_handler_init(hdl, 2);
+ v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler,
+ v4l2_ctrl_radio_filter);
+ if (hdl->error)
+ return hdl->error;
+ }
+ dev->ctl_mute = 1;
+
+ if (dev->tda9887_conf && saa7134_ctrl_automute.def)
dev->tda9887_conf |= TDA9887_AUTOMUTE;
dev->automute = 0;
@@ -2477,6 +2081,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
dev->width = 720;
dev->height = 576;
+ dev->field = V4L2_FIELD_INTERLACED;
dev->win.w.width = dev->width;
dev->win.w.height = dev->height;
dev->win.field = V4L2_FIELD_INTERLACED;
@@ -2488,9 +2093,63 @@ int saa7134_video_init1(struct saa7134_dev *dev)
if (saa7134_boards[dev->board].video_out)
saa7134_videoport_init(dev);
+ q = &dev->video_vbq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /*
+ * Do not add VB2_USERPTR unless explicitly requested: the saa7134 DMA
+ * engine cannot handle transfers that do not start at the beginning
+ * of a page. A user-provided pointer can start anywhere in a page, so
+ * USERPTR support is a no-go unless the application knows about these
+ * limitations and has special support for this.
+ */
+ q->io_modes = VB2_MMAP | VB2_READ;
+ if (saa7134_userptr)
+ q->io_modes |= VB2_USERPTR;
+ q->drv_priv = &dev->video_q;
+ q->ops = &vb2_qops;
+ q->gfp_flags = GFP_DMA32;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->buf_struct_size = sizeof(struct saa7134_buf);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &dev->lock;
+ ret = vb2_queue_init(q);
+ if (ret)
+ return ret;
+ saa7134_pgtable_alloc(dev->pci, &dev->video_q.pt);
+
+ q = &dev->vbi_vbq;
+ q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ /* Don't add VB2_USERPTR, see comment above */
+ q->io_modes = VB2_MMAP | VB2_READ;
+ if (saa7134_userptr)
+ q->io_modes |= VB2_USERPTR;
+ q->drv_priv = &dev->vbi_q;
+ q->ops = &saa7134_vbi_qops;
+ q->gfp_flags = GFP_DMA32;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->buf_struct_size = sizeof(struct saa7134_buf);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &dev->lock;
+ ret = vb2_queue_init(q);
+ if (ret)
+ return ret;
+ saa7134_pgtable_alloc(dev->pci, &dev->vbi_q.pt);
+
return 0;
}
+void saa7134_video_fini(struct saa7134_dev *dev)
+{
+ /* free stuff */
+ vb2_queue_release(&dev->video_vbq);
+ saa7134_pgtable_free(dev->pci, &dev->video_q.pt);
+ vb2_queue_release(&dev->vbi_vbq);
+ saa7134_pgtable_free(dev->pci, &dev->vbi_q.pt);
+ v4l2_ctrl_handler_free(&dev->ctrl_handler);
+ if (card_has_radio(dev))
+ v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
+}
+
int saa7134_videoport_init(struct saa7134_dev *dev)
{
/* enable video output */
@@ -2532,6 +2191,7 @@ int saa7134_video_init2(struct saa7134_dev *dev)
/* init video hw */
set_tvnorm(dev,&tvnorms[0]);
video_mux(dev,0);
+ v4l2_ctrl_handler_setup(&dev->ctrl_handler);
saa7134_tvaudio_setmute(dev);
saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
return 0;
@@ -2577,8 +2237,7 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
spin_lock(&dev->slock);
if (dev->video_q.curr) {
- dev->video_fieldcount++;
- field = dev->video_q.curr->vb.field;
+ field = dev->field;
if (V4L2_FIELD_HAS_BOTH(field)) {
/* make sure we have seen both fields */
if ((status & 0x10) == 0x00) {
@@ -2594,18 +2253,10 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
if ((status & 0x10) != 0x00)
goto done;
}
- dev->video_q.curr->vb.field_count = dev->video_fieldcount;
- saa7134_buffer_finish(dev,&dev->video_q,VIDEOBUF_DONE);
+ saa7134_buffer_finish(dev, &dev->video_q, VB2_BUF_STATE_DONE);
}
- saa7134_buffer_next(dev,&dev->video_q);
+ saa7134_buffer_next(dev, &dev->video_q);
done:
spin_unlock(&dev->slock);
}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 8d1453a4801..e47edd4b57c 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -37,14 +37,15 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
#include <media/tuner.h>
#include <media/rc-core.h>
#include <media/ir-kbd-i2c.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf2-dma-sg.h>
#include <sound/core.h>
#include <sound/pcm.h>
#if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB)
-#include <media/videobuf-dvb.h>
+#include <media/videobuf2-dvb.h>
#endif
#include "tda8290.h"
@@ -410,12 +411,18 @@ struct saa7134_board {
#define card(dev) (saa7134_boards[dev->board])
#define card_in(dev,n) (saa7134_boards[dev->board].inputs[n])
+#define V4L2_CID_PRIVATE_INVERT (V4L2_CID_USER_SAA7134_BASE + 0)
+#define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_USER_SAA7134_BASE + 1)
+#define V4L2_CID_PRIVATE_Y_EVEN (V4L2_CID_USER_SAA7134_BASE + 2)
+#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_USER_SAA7134_BASE + 3)
+
/* ----------------------------------------------------------- */
/* device / file handle status */
#define RESOURCE_OVERLAY 1
#define RESOURCE_VIDEO 2
#define RESOURCE_VBI 4
+#define RESOURCE_EMPRESS 8
#define INTERLACE_AUTO 0
#define INTERLACE_ON 1
@@ -446,17 +453,15 @@ struct saa7134_thread {
/* buffer for one video/vbi/ts frame */
struct saa7134_buf {
/* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
+ struct vb2_buffer vb2;
/* saa7134 specific */
- struct saa7134_format *fmt;
unsigned int top_seen;
int (*activate)(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next);
- /* page tables */
- struct saa7134_pgtable *pt;
+ struct list_head entry;
};
struct saa7134_dmaqueue {
@@ -465,21 +470,8 @@ struct saa7134_dmaqueue {
struct list_head queue;
struct timer_list timeout;
unsigned int need_two;
-};
-
-/* video filehandle status */
-struct saa7134_fh {
- struct v4l2_fh fh;
- struct saa7134_dev *dev;
- unsigned int resources;
-
- /* video capture */
- struct videobuf_queue cap;
- struct saa7134_pgtable pt_cap;
-
- /* vbi capture */
- struct videobuf_queue vbi;
- struct saa7134_pgtable pt_vbi;
+ unsigned int seq_nr;
+ struct saa7134_pgtable pt;
};
/* dmasound dsp status */
@@ -505,7 +497,10 @@ struct saa7134_dmasound {
unsigned int blksize;
unsigned int bufsize;
struct saa7134_pgtable pt;
- struct videobuf_dmabuf dma;
+ void *vaddr;
+ struct scatterlist *sglist;
+ int sglen;
+ int nr_pages;
unsigned int dma_blk;
unsigned int read_offset;
unsigned int read_count;
@@ -516,7 +511,6 @@ struct saa7134_dmasound {
/* ts/mpeg status */
struct saa7134_ts {
/* TS capture */
- struct saa7134_pgtable pt_ts;
int nr_packets;
int nr_bufs;
};
@@ -585,20 +579,39 @@ struct saa7134_dev {
struct v4l2_window win;
struct v4l2_clip clips[8];
unsigned int nclips;
+ struct v4l2_fh *overlay_owner;
/* video+ts+vbi capture */
struct saa7134_dmaqueue video_q;
+ struct vb2_queue video_vbq;
struct saa7134_dmaqueue vbi_q;
- unsigned int video_fieldcount;
- unsigned int vbi_fieldcount;
+ struct vb2_queue vbi_vbq;
+ enum v4l2_field field;
struct saa7134_format *fmt;
unsigned int width, height;
+ unsigned int vbi_hlen, vbi_vlen;
struct pm_qos_request qos_request;
+ /* SAA7134_MPEG_* */
+ struct saa7134_ts ts;
+ struct saa7134_dmaqueue ts_q;
+ enum v4l2_field ts_field;
+ int ts_started;
+ struct saa7134_mpeg_ops *mops;
+
+ /* SAA7134_MPEG_EMPRESS only */
+ struct video_device *empress_dev;
+ struct v4l2_subdev *empress_sd;
+ struct vb2_queue empress_vbq;
+ struct work_struct empress_workqueue;
+ int empress_started;
+ struct v4l2_ctrl_handler empress_ctrl_handler;
+
/* various v4l controls */
struct saa7134_tvnorm *tvnorm; /* video */
struct saa7134_tvaudio *tvaudio;
+ struct v4l2_ctrl_handler ctrl_handler;
unsigned int ctl_input;
int ctl_bright;
int ctl_contrast;
@@ -626,26 +639,14 @@ struct saa7134_dev {
int last_carrier;
int nosignal;
unsigned int insuspend;
+ struct v4l2_ctrl_handler radio_ctrl_handler;
/* I2C keyboard data */
struct IR_i2c_init_data init_data;
- /* SAA7134_MPEG_* */
- struct saa7134_ts ts;
- struct saa7134_dmaqueue ts_q;
- int ts_started;
- struct saa7134_mpeg_ops *mops;
-
- /* SAA7134_MPEG_EMPRESS only */
- struct video_device *empress_dev;
- struct videobuf_queue empress_tsq;
- atomic_t empress_users;
- struct work_struct empress_workqueue;
- int empress_started;
-
#if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB)
/* SAA7134_MPEG_DVB only */
- struct videobuf_dvb_frontends frontends;
+ struct vb2_dvb_frontends frontends;
int (*original_demod_sleep)(struct dvb_frontend *fe);
int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
@@ -699,12 +700,21 @@ struct saa7134_dev {
_rc; \
})
+static inline bool is_empress(struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct saa7134_dev *dev = video_get_drvdata(vdev);
+
+ return vdev->queue == &dev->empress_vbq;
+}
+
/* ----------------------------------------------------------- */
/* saa7134-core.c */
extern struct list_head saa7134_devlist;
extern struct mutex saa7134_devlist_lock;
extern int saa7134_no_overlay;
+extern bool saa7134_userptr;
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
@@ -727,7 +737,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
unsigned int state);
void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
void saa7134_buffer_timeout(unsigned long data);
-void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
+void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
int saa7134_set_dmabits(struct saa7134_dev *dev);
@@ -761,10 +771,26 @@ extern unsigned int video_debug;
extern struct video_device saa7134_video_template;
extern struct video_device saa7134_radio_template;
-int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c);
-int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c);
-int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
-int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id id);
+void saa7134_vb2_buffer_queue(struct vb2_buffer *vb);
+int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count);
+void saa7134_vb2_stop_streaming(struct vb2_queue *vq);
+
+int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id);
+int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id);
+int saa7134_querystd(struct file *file, void *priv, v4l2_std_id *std);
+int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i);
+int saa7134_g_input(struct file *file, void *priv, unsigned int *i);
+int saa7134_s_input(struct file *file, void *priv, unsigned int i);
+int saa7134_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap);
+int saa7134_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *t);
+int saa7134_s_tuner(struct file *file, void *priv,
+ const struct v4l2_tuner *t);
+int saa7134_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f);
+int saa7134_s_frequency(struct file *file, void *priv,
+ const struct v4l2_frequency *f);
int saa7134_videoport_init(struct saa7134_dev *dev);
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
@@ -773,6 +799,7 @@ int saa7134_video_init1(struct saa7134_dev *dev);
int saa7134_video_init2(struct saa7134_dev *dev);
void saa7134_irq_video_signalchange(struct saa7134_dev *dev);
void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
+void saa7134_video_fini(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
@@ -780,7 +807,16 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
-extern struct videobuf_queue_ops saa7134_ts_qops;
+int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
+int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
+void saa7134_ts_buffer_finish(struct vb2_buffer *vb2);
+int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[]);
+int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
+void saa7134_ts_stop_streaming(struct vb2_queue *vq);
+
+extern struct vb2_ops saa7134_ts_qops;
int saa7134_ts_init1(struct saa7134_dev *dev);
int saa7134_ts_fini(struct saa7134_dev *dev);
@@ -797,7 +833,7 @@ int saa7134_ts_stop(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
/* saa7134-vbi.c */
-extern struct videobuf_queue_ops saa7134_vbi_qops;
+extern struct vb2_ops saa7134_vbi_qops;
extern struct video_device saa7134_vbi_template;
int saa7134_vbi_init1(struct saa7134_dev *dev);