summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/saa7134
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/saa7134')
-rw-r--r--linux/drivers/media/video/saa7134/saa6752hs.c444
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-core.c58
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-empress.c60
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-i2c.c10
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-ts.c56
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-video.c42
-rw-r--r--linux/drivers/media/video/saa7134/saa7134.h11
7 files changed, 438 insertions, 243 deletions
diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c
index c5c19a2e3..8ccca4d56 100644
--- a/linux/drivers/media/video/saa7134/saa6752hs.c
+++ b/linux/drivers/media/video/saa7134/saa6752hs.c
@@ -1,3 +1,27 @@
+ /*
+ 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>
@@ -11,6 +35,8 @@
#include "compat.h"
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv-legacy.h>
#include <linux/init.h>
#include <linux/crc32.h>
@@ -28,9 +54,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
MODULE_AUTHOR("Andrew de Quincey");
MODULE_LICENSE("GPL");
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
enum saa6752hs_videoformat {
SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */
SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
@@ -47,7 +70,9 @@ struct saa6752hs_mpeg_params {
__u16 ts_pid_pcr;
/* audio */
- enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
+ 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;
@@ -71,7 +96,9 @@ static const struct v4l2_format v4l2_format_table[] =
};
struct saa6752hs_state {
- struct i2c_client client;
+ int chip;
+ u32 revision;
+ int has_ac3;
struct saa6752hs_mpeg_params params;
enum saa6752hs_videoformat video_format;
v4l2_std_id standard;
@@ -146,6 +173,39 @@ static u8 PMT[] = {
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,
@@ -158,12 +218,14 @@ static struct saa6752hs_mpeg_params param_defaults =
.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,
+static int saa6752hs_chip_command(struct i2c_client *client,
enum saa6752hs_command command)
{
unsigned char buf[3];
@@ -230,45 +292,61 @@ static int saa6752hs_chip_command(struct i2c_client* client,
}
-static int saa6752hs_set_bitrate(struct i2c_client* client,
- struct saa6752hs_mpeg_params* params)
+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 */
- buf[0] = 0x71;
- buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1;
- i2c_master_send(client, buf, 2);
+ 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 */
- buf[0] = 0x80;
- buf[1] = params->vi_bitrate >> 8;
- buf[2] = params->vi_bitrate & 0xff;
- i2c_master_send(client, buf, 3);
+ set_reg16(client, 0x80, params->vi_bitrate);
/* set the max bitrate */
- buf[0] = 0x81;
- buf[1] = params->vi_bitrate_peak >> 8;
- buf[2] = params->vi_bitrate_peak & 0xff;
- i2c_master_send(client, buf, 3);
+ set_reg16(client, 0x81, params->vi_bitrate_peak);
tot_bitrate = params->vi_bitrate_peak;
} else {
/* set the target bitrate (no max bitrate for CBR) */
- buf[0] = 0x81;
- buf[1] = params->vi_bitrate >> 8;
- buf[2] = params->vi_bitrate & 0xff;
- i2c_master_send(client, buf, 3);
+ 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 */
- buf[0] = 0x94;
- buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1;
- i2c_master_send(client, buf, 2);
- tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384;
+ 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
@@ -279,16 +357,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client,
tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
/* set the total bitrate */
- buf[0] = 0xb1;
- buf[1] = tot_bitrate >> 8;
- buf[2] = tot_bitrate & 0xff;
- i2c_master_send(client, buf, 3);
-
+ set_reg16(client, 0xb1, tot_bitrate);
return 0;
}
-static void saa6752hs_set_subsampling(struct i2c_client* client,
- struct v4l2_format* f)
+static void saa6752hs_set_subsampling(struct i2c_client *client,
+ struct v4l2_format *f)
{
struct saa6752hs_state *h = i2c_get_clientdata(client);
int dist_352, dist_480, dist_720;
@@ -333,7 +407,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client,
}
-static int handle_ctrl(struct saa6752hs_mpeg_params *params,
+static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
struct v4l2_ext_control *ctrl, unsigned int cmd)
{
int old = 0, new;
@@ -380,8 +454,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
params->ts_pid_pcr = new;
break;
case V4L2_CID_MPEG_AUDIO_ENCODING:
- old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
- if (set && new != old)
+ old = params->au_encoding;
+ if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+ (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
return -ERANGE;
new = old;
break;
@@ -396,6 +471,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
params->au_l2_bitrate = new;
break;
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (!has_ac3)
+ return -EINVAL;
+ old = params->au_ac3_bitrate;
+ if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
+ new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
+ return -ERANGE;
+ if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
+ new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
+ else
+ new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
+ params->au_ac3_bitrate = new;
+ break;
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
if (set && new != old)
@@ -449,17 +537,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
return 0;
}
-static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
+static int saa6752hs_qctrl(struct saa6752hs_state *h,
struct v4l2_queryctrl *qctrl)
{
+ struct saa6752hs_mpeg_params *params = &h->params;
int err;
switch (qctrl->id) {
case V4L2_CID_MPEG_AUDIO_ENCODING:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
- V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+ h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
return v4l2_ctrl_query_fill(qctrl,
@@ -467,6 +557,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (!h->has_ac3)
+ return -EINVAL;
+ return v4l2_ctrl_query_fill(qctrl,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
@@ -513,44 +611,57 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
return -EINVAL;
}
-static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params,
+static int saa6752hs_qmenu(struct saa6752hs_state *h,
struct v4l2_querymenu *qmenu)
{
- static const char *mpeg_audio_l2_bitrate[] = {
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "256 kbps",
- "",
- "384 kbps",
- NULL
+ static const u32 mpeg_audio_encoding[] = {
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ V4L2_CTRL_MENU_IDS_END
+ };
+ static const u32 mpeg_audio_ac3_encoding[] = {
+ V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+ V4L2_MPEG_AUDIO_ENCODING_AC3,
+ V4L2_CTRL_MENU_IDS_END
+ };
+ static u32 mpeg_audio_l2_bitrate[] = {
+ V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+ V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+ V4L2_CTRL_MENU_IDS_END
+ };
+ static u32 mpeg_audio_ac3_bitrate[] = {
+ V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+ V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
+ V4L2_CTRL_MENU_IDS_END
};
struct v4l2_queryctrl qctrl;
int err;
qctrl.id = qmenu->id;
- err = saa6752hs_qctrl(params, &qctrl);
+ err = saa6752hs_qctrl(h, &qctrl);
if (err)
return err;
- if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE)
- return v4l2_ctrl_query_menu(qmenu, &qctrl,
+ switch (qmenu->id) {
+ case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+ return v4l2_ctrl_query_menu_valid_items(qmenu,
mpeg_audio_l2_bitrate);
- return v4l2_ctrl_query_menu(qmenu, &qctrl,
- v4l2_ctrl_get_menu(qmenu->id));
+ case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+ if (!h->has_ac3)
+ return -EINVAL;
+ return v4l2_ctrl_query_menu_valid_items(qmenu,
+ mpeg_audio_ac3_bitrate);
+ case V4L2_CID_MPEG_AUDIO_ENCODING:
+ return v4l2_ctrl_query_menu_valid_items(qmenu,
+ h->has_ac3 ? mpeg_audio_ac3_encoding :
+ mpeg_audio_encoding);
+ }
+ return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
}
-static int saa6752hs_init(struct i2c_client* client)
+static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes)
{
unsigned char buf[9], buf2[4];
struct saa6752hs_state *h;
+ unsigned size;
u32 crc;
unsigned char localPAT[256];
unsigned char localPMT[256];
@@ -558,45 +669,31 @@ static int saa6752hs_init(struct i2c_client* client)
h = i2c_get_clientdata(client);
/* Set video format - must be done first as it resets other settings */
- buf[0] = 0x41;
- buf[1] = h->video_format;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0x41, h->video_format);
/* Set number of lines in input signal */
- buf[0] = 0x40;
- buf[1] = 0x00;
- if (h->standard & V4L2_STD_525_60)
- buf[1] = 0x01;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
/* set bitrate */
- saa6752hs_set_bitrate(client, &h->params);
+ saa6752hs_set_bitrate(client, h);
/* Set GOP structure {3, 13} */
- buf[0] = 0x72;
- buf[1] = 0x03;
- buf[2] = 0x0D;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0x72, 0x030d);
/* Set minimum Q-scale {4} */
- buf[0] = 0x82;
- buf[1] = 0x04;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0x82, 0x04);
/* Set maximum Q-scale {12} */
- buf[0] = 0x83;
- buf[1] = 0x0C;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0x83, 0x0c);
/* Set Output Protocol */
- buf[0] = 0xD0;
- buf[1] = 0x81;
- i2c_master_send(client,buf,2);
+ set_reg8(client, 0xd0, 0x81);
/* Set video output stream format {TS} */
- buf[0] = 0xB0;
- buf[1] = 0x05;
- i2c_master_send(client,buf,2);
+ 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));
@@ -609,7 +706,13 @@ static int saa6752hs_init(struct i2c_client* client)
localPAT[sizeof(PAT) - 1] = crc & 0xFF;
/* compute PMT */
- memcpy(localPMT, PMT, sizeof(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);
@@ -618,40 +721,28 @@ static int saa6752hs_init(struct i2c_client* client)
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], sizeof(PMT) - 7 - 4);
- localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
- localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
- localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
- localPMT[sizeof(PMT) - 1] = crc & 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 */
- buf[0] = 0xC1;
- buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
- buf[2] = h->params.ts_pid_audio & 0xFF;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0xc1, h->params.ts_pid_audio);
/* Set Video PID */
- buf[0] = 0xC0;
- buf[1] = (h->params.ts_pid_video >> 8) & 0xFF;
- buf[2] = h->params.ts_pid_video & 0xFF;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0xc0, h->params.ts_pid_video);
/* Set PCR PID */
- buf[0] = 0xC4;
- buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF;
- buf[2] = h->params.ts_pid_pcr & 0xFF;
- i2c_master_send(client,buf,3);
+ set_reg16(client, 0xc4, h->params.ts_pid_pcr);
/* Send SI tables */
- i2c_master_send(client,localPAT,sizeof(PAT));
- i2c_master_send(client,localPMT,sizeof(PMT));
+ i2c_master_send(client, localPAT, sizeof(PAT));
+ i2c_master_send(client, localPMT, size);
/* mute then unmute audio. This removes buzzing artefacts */
- buf[0] = 0xa4;
- buf[1] = 1;
- i2c_master_send(client, buf, 2);
- buf[1] = 0;
- i2c_master_send(client, buf, 2);
+ set_reg8(client, 0xa4, 1);
+ set_reg8(client, 0xa4, 0);
/* start it going */
saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
@@ -689,45 +780,6 @@ static int saa6752hs_init(struct i2c_client* client)
return 0;
}
-static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- struct saa6752hs_state *h;
-
-
- if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL)))
- return -ENOMEM;
- h->client = client_template;
- h->params = param_defaults;
- h->client.adapter = adap;
- h->client.addr = addr;
-
- /* Assume 625 input lines */
- h->standard = 0;
-
- i2c_set_clientdata(&h->client, h);
- i2c_attach_client(&h->client);
-
- v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
- return 0;
-}
-
-static int saa6752hs_probe(struct i2c_adapter *adap)
-{
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, saa6752hs_attach);
- return 0;
-}
-
-static int saa6752hs_detach(struct i2c_client *client)
-{
- struct saa6752hs_state *h;
-
- h = i2c_get_clientdata(client);
- i2c_detach_client(client);
- kfree(h);
- return 0;
-}
-
static int
saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
@@ -738,14 +790,13 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
int i;
switch (cmd) {
+ case VIDIOC_INT_INIT:
+ /* apply settings and start encoder */
+ saa6752hs_init(client, *(u32 *)arg);
+ break;
case VIDIOC_S_EXT_CTRLS:
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
- if (ctrls->count == 0) {
- /* apply settings and start encoder */
- saa6752hs_init(client);
- break;
- }
/* fall through */
case VIDIOC_TRY_EXT_CTRLS:
case VIDIOC_G_EXT_CTRLS:
@@ -753,7 +804,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
return -EINVAL;
params = h->params;
for (i = 0; i < ctrls->count; i++) {
- if ((err = handle_ctrl(&params, ctrls->controls + i, cmd))) {
+ err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, cmd);
+ if (err) {
ctrls->error_idx = i;
return err;
}
@@ -761,9 +813,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
h->params = params;
break;
case VIDIOC_QUERYCTRL:
- return saa6752hs_qctrl(&h->params, arg);
+ return saa6752hs_qctrl(h, arg);
case VIDIOC_QUERYMENU:
- return saa6752hs_qmenu(&h->params, arg);
+ return saa6752hs_qmenu(h, arg);
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
@@ -786,6 +838,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
case VIDIOC_S_STD:
h->standard = *((v4l2_std_id *) arg);
break;
+
+ case VIDIOC_G_CHIP_IDENT:
+ return v4l2_chip_ident_i2c_client(client,
+ arg, h->chip, h->revision);
+
default:
/* nothing */
break;
@@ -794,36 +851,59 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
return err;
}
-/* ----------------------------------------------------------------------- */
+static int saa6752hs_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+ u8 addr = 0x13;
+ u8 data[12];
-static struct i2c_driver driver = {
- .driver = {
- .name = "saa6752hs",
- },
- .id = I2C_DRIVERID_SAA6752HS,
- .attach_adapter = saa6752hs_probe,
- .detach_client = saa6752hs_detach,
- .command = saa6752hs_command,
-};
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+ if (h == NULL)
+ return -ENOMEM;
-static struct i2c_client client_template =
-{
- .name = "saa6752hs",
- .driver = &driver,
-};
+ i2c_master_send(client, &addr, 1);
+ i2c_master_recv(client, data, sizeof(data));
+ h->chip = V4L2_IDENT_SAA6752HS;
+ h->revision = (data[8] << 8) | data[9];
+ h->has_ac3 = 0;
+ if (h->revision == 0x0206) {
+ h->chip = V4L2_IDENT_SAA6752HS_AC3;
+ h->has_ac3 = 1;
+ v4l_info(client, "support AC-3\n");
+ }
+ h->params = param_defaults;
+ h->standard = 0; /* Assume 625 input lines */
-static int __init saa6752hs_init_module(void)
-{
- return i2c_add_driver(&driver);
+ i2c_set_clientdata(client, h);
+ return 0;
}
-static void __exit saa6752hs_cleanup_module(void)
+static int saa6752hs_remove(struct i2c_client *client)
{
- i2c_del_driver(&driver);
+ kfree(i2c_get_clientdata(client));
+ return 0;
}
-module_init(saa6752hs_init_module);
-module_exit(saa6752hs_cleanup_module);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static const struct i2c_device_id saa6752hs_id[] = {
+ { "saa6752hs", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
+
+#endif
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "saa6752hs",
+ .driverid = I2C_DRIVERID_SAA6752HS,
+ .command = saa6752hs_command,
+ .probe = saa6752hs_probe,
+ .remove = saa6752hs_remove,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ .id_table = saa6752hs_id,
+#endif
+};
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c
index e02c3c1b1..ce8bcc967 100644
--- a/linux/drivers/media/video/saa7134/saa7134-core.c
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c
@@ -264,7 +264,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
{
__le32 *cpu;
- dma_addr_t dma_addr;
+ dma_addr_t dma_addr = 0;
cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
if (NULL == cpu)
@@ -408,32 +408,6 @@ void saa7134_buffer_timeout(unsigned long data)
spin_unlock_irqrestore(&dev->slock,flags);
}
-/* resends a current buffer in queue after resume */
-
-static int saa7134_buffer_requeue(struct saa7134_dev *dev,
- struct saa7134_dmaqueue *q)
-{
- struct saa7134_buf *buf, *next;
-
- assert_spin_locked(&dev->slock);
-
- buf = q->curr;
- next = buf;
- dprintk("buffer_requeue\n");
-
- if (!buf)
- return 0;
-
- dprintk("buffer_requeue : resending active buffers \n");
-
- if (!list_empty(&q->queue))
- next = list_entry(q->queue.next, struct saa7134_buf,
- vb.queue);
- buf->activate(dev, buf, next);
-
- return 0;
-}
-
/* ------------------------------------------------------------------ */
int saa7134_set_dmabits(struct saa7134_dev *dev)
@@ -491,9 +465,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
/* TS capture -- dma 5 */
if (dev->ts_q.curr) {
ctrl |= SAA7134_MAIN_CTRL_TE5;
- irq |= SAA7134_IRQ1_INTE_RA2_3 |
- SAA7134_IRQ1_INTE_RA2_2 |
- SAA7134_IRQ1_INTE_RA2_1 |
+ irq |= SAA7134_IRQ1_INTE_RA2_1 |
SAA7134_IRQ1_INTE_RA2_0;
}
@@ -1203,6 +1175,32 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
+
+/* resends a current buffer in queue after resume */
+static int saa7134_buffer_requeue(struct saa7134_dev *dev,
+ struct saa7134_dmaqueue *q)
+{
+ struct saa7134_buf *buf, *next;
+
+ assert_spin_locked(&dev->slock);
+
+ buf = q->curr;
+ next = buf;
+ dprintk("buffer_requeue\n");
+
+ if (!buf)
+ return 0;
+
+ dprintk("buffer_requeue : resending active buffers \n");
+
+ if (!list_empty(&q->queue))
+ next = list_entry(q->queue.next, struct saa7134_buf,
+ vb.queue);
+ buf->activate(dev, buf, next);
+
+ return 0;
+}
+
static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
{
diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c
index a454968f7..9ebe166cc 100644
--- a/linux/drivers/media/video/saa7134/saa7134-empress.c
+++ b/linux/drivers/media/video/saa7134/saa7134-empress.c
@@ -29,6 +29,7 @@
#include <media/saa6752hs.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
/* ------------------------------------------------------------------ */
@@ -63,10 +64,19 @@ static void ts_reset_encoder(struct saa7134_dev* dev)
static int ts_init_encoder(struct saa7134_dev* dev)
{
- struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 };
+ u32 leading_null_bytes = 0;
+ /* If more cards start to need this, then this
+ should probably be added to the card definitions. */
+ switch (dev->board) {
+ case SAA7134_BOARD_BEHOLD_M6:
+ case SAA7134_BOARD_BEHOLD_M63:
+ case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+ leading_null_bytes = 1;
+ break;
+ }
ts_reset_encoder(dev);
- saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls);
+ saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes);
dev->empress_started = 1;
return 0;
}
@@ -293,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv,
return videobuf_streamoff(&dev->empress_tsq);
}
-static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
- unsigned int cmd, void *arg)
-{
- if (dev->mpeg_i2c_client == NULL)
- return -EINVAL;
- return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
- cmd, arg);
-}
-
static int empress_s_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *ctrls)
{
@@ -403,6 +404,39 @@ static int empress_querymenu(struct file *file, void *priv,
return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c);
}
+static int empress_g_chip_ident(struct file *file, void *fh,
+ struct v4l2_chip_ident *chip)
+{
+ struct saa7134_dev *dev = file->private_data;
+
+ chip->ident = V4L2_IDENT_NONE;
+ chip->revision = 0;
+ if (dev->mpeg_i2c_client == NULL)
+ return -EINVAL;
+ if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER &&
+ chip->match_chip == I2C_DRIVERID_SAA6752HS)
+ return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+ if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR &&
+ chip->match_chip == dev->mpeg_i2c_client->addr)
+ return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+ return -EINVAL;
+}
+
+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 file_operations ts_fops =
{
.owner = THIS_MODULE,
@@ -431,11 +465,13 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
.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_g_chip_ident = empress_g_chip_ident,
+ .vidioc_s_std = empress_s_std,
+ .vidioc_g_std = empress_g_std,
};
/* ----------------------------------------------------------- */
diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c
index bdec276e0..2ca03df8c 100644
--- a/linux/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c
@@ -432,6 +432,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev,
i2c_clients_command(&dev->i2c_adap, cmd, arg);
}
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+ unsigned int cmd, void *arg)
+{
+ if (dev->mpeg_i2c_client == NULL)
+ return -EINVAL;
+ return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
+ cmd, arg);
+}
+EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752);
+
int saa7134_i2c_register(struct saa7134_dev *dev)
{
dev->i2c_adap = saa7134_adap_template;
diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c
index eae72fd60..ef55a59f0 100644
--- a/linux/drivers/media/video/saa7134/saa7134-ts.c
+++ b/linux/drivers/media/video/saa7134/saa7134-ts.c
@@ -66,11 +66,29 @@ static int buffer_activate(struct saa7134_dev *dev,
saa7134_set_dmabits(dev);
mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT);
+
+ if (dev->ts_state == SAA7134_TS_BUFF_DONE) {
+ /* Clear TS cache */
+ dev->buff_cnt = 0;
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x03);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x01);
+
+ /* TS clock non-inverted */
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+
+ /* Start TS stream */
+ saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+ saa_writeb(SAA7134_TS_PARALLEL, 0xEC);
+ dev->ts_state = SAA7134_TS_STARTED;
+ }
+
return 0;
}
static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
+ enum v4l2_field field)
{
struct saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
@@ -110,16 +128,22 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
goto oops;
}
- /* dma: setup channel 5 (= TS) */
- control = SAA7134_RS_CONTROL_BURST_16 |
- SAA7134_RS_CONTROL_ME |
- (buf->pt->dma >> 12);
-
- saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff));
- saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff));
- saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
- saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE);
- saa_writel(SAA7134_RS_CONTROL(5),control);
+ dev->buff_cnt++;
+
+ if (dev->buff_cnt == dev->ts.nr_bufs) {
+ dev->ts_state = SAA7134_TS_BUFF_DONE;
+ /* dma: setup channel 5 (= TS) */
+ control = SAA7134_RS_CONTROL_BURST_16 |
+ SAA7134_RS_CONTROL_ME |
+ (buf->pt->dma >> 12);
+
+ saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff);
+ saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff);
+ /* TSNOPIT=0, TSCOLAP=0 */
+ saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00);
+ saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+ saa_writel(SAA7134_RS_CONTROL(5), control);
+ }
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
@@ -140,6 +164,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
if (0 == *count)
*count = dev->ts.nr_bufs;
*count = saa7134_buffer_count(*size,*count);
+ dev->buff_cnt = 0;
+ dev->ts_state = SAA7134_TS_STOPPED;
return 0;
}
@@ -154,7 +180,13 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+ struct saa7134_dev *dev = q->priv_data;
+ if (dev->ts_state == SAA7134_TS_STARTED) {
+ /* Stop TS transport */
+ saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+ dev->ts_state = SAA7134_TS_STOPPED;
+ }
saa7134_dma_free(q,buf);
}
@@ -182,7 +214,7 @@ int saa7134_ts_init_hw(struct saa7134_dev *dev)
/* deactivate TS softreset */
saa_writeb(SAA7134_TS_SERIAL1, 0x00);
/* TSSOP high active, TSVAL high active, TSLOCK ignored */
- saa_writeb(SAA7134_TS_PARALLEL, 0xec);
+ saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c
index 547c0401a..241b60e3f 100644
--- a/linux/drivers/media/video/saa7134/saa7134-video.c
+++ b/linux/drivers/media/video/saa7134/saa7134-video.c
@@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
if (card_in(dev, dev->ctl_input).tv)
saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+ /* Set the correct norm for the saa6752hs. This function
+ does nothing if there is no saa6752hs. */
+ saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id);
}
static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1803,18 +1806,25 @@ static int saa7134_querycap(struct file *file, void *priv,
return 0;
}
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
{
- struct saa7134_fh *fh = priv;
- struct saa7134_dev *dev = fh->dev;
unsigned long flags;
unsigned int i;
v4l2_std_id fixup;
int err;
- err = v4l2_prio_check(&dev->prio, &fh->prio);
- if (0 != err)
- return err;
+ /* When called from the empress code fh == NULL.
+ That needs to be fixed somehow, but for now this is
+ good enough. */
+ if (fh) {
+ err = v4l2_prio_check(&dev->prio, &fh->prio);
+ if (0 != err)
+ return err;
+ } else if (res_locked(dev, RESOURCE_OVERLAY)) {
+ /* Don't change the std from the mpeg device
+ if overlay is active. */
+ return -EBUSY;
+ }
for (i = 0; i < TVNORMS; i++)
if (*id == tvnorms[i].id)
@@ -1847,7 +1857,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
*id = tvnorms[i].id;
mutex_lock(&dev->lock);
- if (res_check(fh, RESOURCE_OVERLAY)) {
+ if (fh && res_check(fh, RESOURCE_OVERLAY)) {
spin_lock_irqsave(&dev->slock, flags);
stop_preview(dev, fh);
spin_unlock_irqrestore(&dev->slock, flags);
@@ -1864,6 +1874,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
mutex_unlock(&dev->lock);
return 0;
}
+EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+
+static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct saa7134_fh *fh = priv;
+
+ return saa7134_s_std_internal(fh->dev, fh, id);
+}
+
+static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct saa7134_fh *fh = priv;
+ struct saa7134_dev *dev = fh->dev;
+
+ *id = dev->tvnorm->id;
+ return 0;
+}
static int saa7134_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cap)
@@ -2404,6 +2431,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_qbuf = saa7134_qbuf,
.vidioc_dqbuf = saa7134_dqbuf,
.vidioc_s_std = saa7134_s_std,
+ .vidioc_g_std = saa7134_g_std,
.vidioc_enum_input = saa7134_enum_input,
.vidioc_g_input = saa7134_g_input,
.vidioc_s_input = saa7134_s_input,
diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h
index e3ad9d9e7..50319493d 100644
--- a/linux/drivers/media/video/saa7134/saa7134.h
+++ b/linux/drivers/media/video/saa7134/saa7134.h
@@ -467,6 +467,12 @@ struct saa7134_mpeg_ops {
void (*signal_change)(struct saa7134_dev *dev);
};
+enum saa7134_ts_status {
+ SAA7134_TS_STOPPED,
+ SAA7134_TS_BUFF_DONE,
+ SAA7134_TS_STARTED,
+};
+
/* global device status */
struct saa7134_dev {
struct list_head devlist;
@@ -560,6 +566,8 @@ struct saa7134_dev {
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
+ enum saa7134_ts_status ts_state;
+ unsigned int buff_cnt;
struct saa7134_mpeg_ops *mops;
struct i2c_client *mpeg_i2c_client;
@@ -659,6 +667,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev);
int saa7134_i2c_unregister(struct saa7134_dev *dev);
void saa7134_i2c_call_clients(struct saa7134_dev *dev,
unsigned int cmd, void *arg);
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+ unsigned int cmd, void *arg);
/* ----------------------------------------------------------- */
@@ -671,6 +681,7 @@ 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);
int saa7134_videoport_init(struct saa7134_dev *dev);
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);