summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7134
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2005-12-06 17:31:30 -0500
committerLen Brown <len.brown@intel.com>2005-12-06 17:31:30 -0500
commit3d5271f9883cba7b54762bc4fe027d4172f06db7 (patch)
treeab8a881a14478598a0c8bda0d26c62cdccfffd6d /drivers/media/video/saa7134
parent378b2556f4e09fa6f87ff0cb5c4395ff28257d02 (diff)
parent9115a6c787596e687df03010d97fccc5e0762506 (diff)
Pull release into acpica branch
Diffstat (limited to 'drivers/media/video/saa7134')
-rw-r--r--drivers/media/video/saa7134/Kconfig69
-rw-r--r--drivers/media/video/saa7134/Makefile21
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c187
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c1029
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c619
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c198
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c370
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c6
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c28
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c335
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c549
-rw-r--r--drivers/media/video/saa7134/saa7134-reg.h27
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c29
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c27
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c185
-rw-r--r--drivers/media/video/saa7134/saa7134.h70
16 files changed, 3134 insertions, 615 deletions
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
new file mode 100644
index 00000000000..c512c4411b3
--- /dev/null
+++ b/drivers/media/video/saa7134/Kconfig
@@ -0,0 +1,69 @@
+config VIDEO_SAA7134
+ tristate "Philips SAA7134 support"
+ depends on VIDEO_DEV && PCI && I2C && SOUND && SND
+ select VIDEO_BUF
+ select VIDEO_IR
+ select VIDEO_TUNER
+ select CRC32
+ select SND_PCM_OSS
+ ---help---
+ This is a video4linux driver for Philips SAA713x based
+ TV cards.
+
+ To compile this driver as a module, choose M here: the
+ module will be called saa7134.
+
+config VIDEO_SAA7134_DVB
+ tristate "DVB/ATSC Support for saa7134 based TV cards"
+ depends on VIDEO_SAA7134 && DVB_CORE
+ select VIDEO_BUF_DVB
+ ---help---
+ This adds support for DVB cards based on the
+ Philips saa7134 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called saa7134-dvb.
+
+ You must also select one or more DVB demodulators.
+ If you are unsure which you need, choose all of them.
+
+config VIDEO_SAA7134_DVB_ALL_FRONTENDS
+ bool "Build all supported frontends for saa7134 based TV cards"
+ default y
+ depends on VIDEO_SAA7134_DVB
+ select DVB_MT352
+ select DVB_TDA1004X
+ select DVB_NXT200X
+ ---help---
+ This builds saa7134-dvb with all currently supported frontend
+ demodulators. If you wish to tweak your configuration, and
+ only include support for the hardware that you need, choose N here.
+
+ If you are unsure, choose Y.
+
+config VIDEO_SAA7134_DVB_MT352
+ bool "Zarlink MT352 DVB-T Support"
+ default y
+ depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
+ select DVB_MT352
+ ---help---
+ This adds DVB-T support for cards based on the
+ Philips saa7134 chip and the MT352 demodulator.
+
+config VIDEO_SAA7134_DVB_TDA1004X
+ bool "Phillips TDA10045H/TDA10046H DVB-T Support"
+ default y
+ depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
+ select DVB_TDA1004X
+ ---help---
+ This adds DVB-T support for cards based on the
+ Philips saa7134 chip and the TDA10045H/TDA10046H demodulator.
+
+config VIDEO_SAA7134_DVB_NXT200X
+ bool "NXT2002/NXT2004 ATSC Support"
+ default y
+ depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS
+ select DVB_NXT200X
+ ---help---
+ This adds ATSC 8VSB and QAM64/256 support for cards based on the
+ Philips saa7134 chip and the NXT2002/NXT2004 demodulator.
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index b778ffd94e6..134f83a9621 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -1,17 +1,20 @@
saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \
- saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \
- saa7134-vbi.o saa7134-video.o saa7134-input.o
+ saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \
+ saa7134-video.o saa7134-input.o
-obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o saa6752hs.o
+obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \
+ saa6752hs.o saa7134-alsa.o \
+ saa7134-oss.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
-ifneq ($(CONFIG_DVB_MT352),n)
- EXTRA_CFLAGS += -DHAVE_MT352=1
-endif
-ifneq ($(CONFIG_DVB_TDA1004X),n)
- EXTRA_CFLAGS += -DHAVE_TDA1004X=1
-endif
+
+extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
+extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
+extra-cflags-$(CONFIG_DVB_TDA1004X) += -DHAVE_TDA1004X=1
+extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 382911c6ef2..cdd1ed9c806 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/crc32.h>
-#include <media/id.h>
#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
@@ -57,6 +56,7 @@ struct saa6752hs_state {
struct i2c_client client;
struct v4l2_mpeg_compression params;
enum saa6752hs_videoformat video_format;
+ v4l2_std_id standard;
};
enum saa6752hs_command {
@@ -74,58 +74,58 @@ enum saa6752hs_command {
/* ---------------------------------------------------------------------- */
static u8 PAT[] = {
- 0xc2, // i2c register
- 0x00, // table number for encoder
+ 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)
+ 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, /* PSI pointer to start of table */
- 0x00, // tid(0)
- 0xb0, 0x0d, // section_syntax_indicator(1), section_length(13)
+ 0x00, /* tid(0) */
+ 0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
- 0x00, 0x01, // transport_stream_id(1)
+ 0x00, 0x01, /* transport_stream_id(1) */
- 0xc1, // version_number(0), current_next_indicator(1)
+ 0xc1, /* version_number(0), current_next_indicator(1) */
- 0x00, 0x00, // section_number(0), last_section_number(0)
+ 0x00, 0x00, /* section_number(0), last_section_number(0) */
- 0x00, 0x01, // program_number(1)
+ 0x00, 0x01, /* program_number(1) */
- 0xe0, 0x00, // PMT PID
+ 0xe0, 0x00, /* PMT PID */
- 0x00, 0x00, 0x00, 0x00 // CRC32
+ 0x00, 0x00, 0x00, 0x00 /* CRC32 */
};
static u8 PMT[] = {
- 0xc2, // i2c register
- 0x01, // table number for encoder
+ 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)
+ 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
+ 0x00, /* PSI pointer to start of table */
- 0x02, // tid(2)
- 0xb0, 0x17, // section_syntax_indicator(1), section_length(23)
+ 0x02, /* tid(2) */
+ 0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
- 0x00, 0x01, // program_number(1)
+ 0x00, 0x01, /* program_number(1) */
- 0xc1, // version_number(0), current_next_indicator(1)
+ 0xc1, /* version_number(0), current_next_indicator(1) */
- 0x00, 0x00, // section_number(0), last_section_number(0)
+ 0x00, 0x00, /* section_number(0), last_section_number(0) */
- 0xe0, 0x00, // PCR_PID
+ 0xe0, 0x00, /* PCR_PID */
- 0xf0, 0x00, // program_info_length(0)
+ 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
+ 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
+ 0x00, 0x00, 0x00, 0x00 /* CRC32 */
};
static struct v4l2_mpeg_compression param_defaults =
@@ -166,33 +166,33 @@ static int saa6752hs_chip_command(struct i2c_client* client,
unsigned long timeout;
int status = 0;
- // execute the command
+ /* execute the command */
switch(command) {
- case SAA6752HS_COMMAND_RESET:
- buf[0] = 0x00;
+ case SAA6752HS_COMMAND_RESET:
+ buf[0] = 0x00;
break;
case SAA6752HS_COMMAND_STOP:
- buf[0] = 0x03;
+ buf[0] = 0x03;
break;
case SAA6752HS_COMMAND_START:
- buf[0] = 0x02;
+ buf[0] = 0x02;
break;
case SAA6752HS_COMMAND_PAUSE:
- buf[0] = 0x04;
+ buf[0] = 0x04;
break;
case SAA6752HS_COMMAND_RECONFIGURE:
buf[0] = 0x05;
break;
- case SAA6752HS_COMMAND_SLEEP:
- buf[0] = 0x06;
+ case SAA6752HS_COMMAND_SLEEP:
+ buf[0] = 0x06;
break;
- case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
+ case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
buf[0] = 0x07;
break;
@@ -200,13 +200,13 @@ static int saa6752hs_chip_command(struct i2c_client* client,
return -EINVAL;
}
- // set it and wait for it to be so
+ /* set it and wait for it to be so */
i2c_master_send(client, buf, 1);
timeout = jiffies + HZ * 3;
for (;;) {
- // get the current status
+ /* get the current status */
buf[0] = 0x10;
- i2c_master_send(client, buf, 1);
+ i2c_master_send(client, buf, 1);
i2c_master_recv(client, buf, 1);
if (!(buf[0] & 0x20))
@@ -216,61 +216,58 @@ static int saa6752hs_chip_command(struct i2c_client* client,
break;
}
- // wait a bit
msleep(10);
}
- // delay a bit to let encoder settle
+ /* delay a bit to let encoder settle */
msleep(50);
- // done
- return status;
+ return status;
}
static int saa6752hs_set_bitrate(struct i2c_client* client,
struct v4l2_mpeg_compression* params)
{
- u8 buf[3];
+ u8 buf[3];
- // set the bitrate mode
+ /* set the bitrate mode */
buf[0] = 0x71;
buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1;
i2c_master_send(client, buf, 2);
- // set the video bitrate
+ /* set the video bitrate */
if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) {
- // set the target bitrate
+ /* set the target bitrate */
buf[0] = 0x80;
buf[1] = params->vi_bitrate.target >> 8;
- buf[2] = params->vi_bitrate.target & 0xff;
+ buf[2] = params->vi_bitrate.target & 0xff;
i2c_master_send(client, buf, 3);
- // set the max bitrate
+ /* set the max bitrate */
buf[0] = 0x81;
buf[1] = params->vi_bitrate.max >> 8;
- buf[2] = params->vi_bitrate.max & 0xff;
+ buf[2] = params->vi_bitrate.max & 0xff;
i2c_master_send(client, buf, 3);
} else {
- // set the target bitrate (no max bitrate for CBR)
- buf[0] = 0x81;
+ /* set the target bitrate (no max bitrate for CBR) */
+ buf[0] = 0x81;
buf[1] = params->vi_bitrate.target >> 8;
- buf[2] = params->vi_bitrate.target & 0xff;
+ buf[2] = params->vi_bitrate.target & 0xff;
i2c_master_send(client, buf, 3);
}
- // set the audio bitrate
- buf[0] = 0x94;
+ /* set the audio bitrate */
+ buf[0] = 0x94;
buf[1] = (256 == params->au_bitrate.target) ? 0 : 1;
i2c_master_send(client, buf, 2);
- // set the total bitrate
+ /* set the total bitrate */
buf[0] = 0xb1;
- buf[1] = params->st_bitrate.target >> 8;
- buf[2] = params->st_bitrate.target & 0xff;
+ buf[1] = params->st_bitrate.target >> 8;
+ buf[2] = params->st_bitrate.target & 0xff;
i2c_master_send(client, buf, 3);
- // return success
return 0;
}
@@ -376,36 +373,43 @@ 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
+ /* 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 bitrate
- saa6752hs_set_bitrate(client, &h->params);
+ /* 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 bitrate */
+ saa6752hs_set_bitrate(client, &h->params);
- // Set GOP structure {3, 13}
+ /* Set GOP structure {3, 13} */
buf[0] = 0x72;
buf[1] = 0x03;
buf[2] = 0x0D;
i2c_master_send(client,buf,3);
- // Set minimum Q-scale {4}
+ /* Set minimum Q-scale {4} */
buf[0] = 0x82;
buf[1] = 0x04;
i2c_master_send(client,buf,2);
- // Set maximum Q-scale {12}
+ /* Set maximum Q-scale {12} */
buf[0] = 0x83;
buf[1] = 0x0C;
i2c_master_send(client,buf,2);
- // Set Output Protocol
+ /* Set Output Protocol */
buf[0] = 0xD0;
buf[1] = 0x81;
i2c_master_send(client,buf,2);
- // Set video output stream format {TS}
+ /* Set video output stream format {TS} */
buf[0] = 0xB0;
buf[1] = 0x05;
i2c_master_send(client,buf,2);
@@ -421,9 +425,9 @@ static int saa6752hs_init(struct i2c_client* client)
localPAT[sizeof(PAT) - 1] = crc & 0xFF;
/* compute PMT */
- memcpy(localPMT, PMT, sizeof(PMT));
- localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
- localPMT[4] = h->params.ts_pid_pmt & 0xff;
+ memcpy(localPMT, PMT, sizeof(PMT));
+ 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);
@@ -436,39 +440,39 @@ static int saa6752hs_init(struct i2c_client* client)
localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
localPMT[sizeof(PMT) - 1] = crc & 0xFF;
- // Set Audio PID
+ /* 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 Video PID
+ /* 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 PCR PID
+ /* 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);
- // Send SI tables
+ /* Send SI tables */
i2c_master_send(client,localPAT,sizeof(PAT));
i2c_master_send(client,localPMT,sizeof(PMT));
- // mute then unmute audio. This removes buzzing artefacts
+ /* mute then unmute audio. This removes buzzing artefacts */
buf[0] = 0xa4;
buf[1] = 1;
i2c_master_send(client, buf, 2);
- buf[1] = 0;
+ buf[1] = 0;
i2c_master_send(client, buf, 2);
- // start it going
+ /* start it going */
saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
- // readout current state
+ /* readout current state */
buf[0] = 0xE1;
buf[1] = 0xA7;
buf[2] = 0xFE;
@@ -477,7 +481,7 @@ static int saa6752hs_init(struct i2c_client* client)
i2c_master_send(client, buf, 5);
i2c_master_recv(client, buf2, 4);
- // change aspect ratio
+ /* change aspect ratio */
buf[0] = 0xE0;
buf[1] = 0xA7;
buf[2] = 0xFE;
@@ -498,7 +502,6 @@ static int saa6752hs_init(struct i2c_client* client)
buf[8] = buf2[3];
i2c_master_send(client, buf, 9);
- // return success
return 0;
}
@@ -506,16 +509,19 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct saa6752hs_state *h;
- printk("saa6752hs: chip found @ 0x%x\n", addr<<1);
+ printk("saa6752hs: chip found @ 0x%x\n", addr<<1);
- if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL)))
- return -ENOMEM;
+ if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL)))
+ return -ENOMEM;
memset(h,0,sizeof(*h));
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);
return 0;
@@ -545,7 +551,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
struct v4l2_mpeg_compression *params = arg;
int err = 0;
- switch (cmd) {
+ switch (cmd) {
case VIDIOC_S_MPEGCOMP:
if (NULL == params) {
/* apply settings and start encoder */
@@ -559,7 +565,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
case VIDIOC_G_FMT:
{
- struct v4l2_format *f = arg;
+ struct v4l2_format *f = arg;
if (h->video_format == SAA6752HS_VF_UNKNOWN)
h->video_format = SAA6752HS_VF_D1;
@@ -576,6 +582,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
saa6752hs_set_subsampling(client, f);
break;
}
+ case VIDIOC_S_STD:
+ h->standard = *((v4l2_std_id *) arg);
+ break;
default:
/* nothing */
break;
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
new file mode 100644
index 00000000000..263c6e2e3e8
--- /dev/null
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -0,0 +1,1029 @@
+/*
+ * SAA713x ALSA support for V4L
+ *
+ *
+ * Caveats:
+ * - Volume doesn't work (it's always at max)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <linux/interrupt.h>
+
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
+static unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
+
+/*
+ * Configuration macros
+ */
+
+/* defaults */
+#define MIXER_ADDR_TVTUNER 0
+#define MIXER_ADDR_LINE1 1
+#define MIXER_ADDR_LINE2 2
+#define MIXER_ADDR_LAST 2
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
+
+#define dprintk(fmt, arg...) if (debug) \
+ printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg)
+
+/*
+ * Main chip structure
+ */
+typedef struct snd_card_saa7134 {
+ snd_card_t *card;
+ spinlock_t mixer_lock;
+ int mixer_volume[MIXER_ADDR_LAST+1][2];
+ int capture_source[MIXER_ADDR_LAST+1][2];
+ struct pci_dev *pci;
+ struct saa7134_dev *dev;
+
+ unsigned long iobase;
+ int irq;
+
+ spinlock_t lock;
+} snd_card_saa7134_t;
+
+
+
+/*
+ * PCM structure
+ */
+
+typedef struct snd_card_saa7134_pcm {
+ struct saa7134_dev *dev;
+
+ spinlock_t lock;
+
+ snd_pcm_substream_t *substream;
+} snd_card_saa7134_pcm_t;
+
+static snd_card_t *snd_saa7134_cards[SNDRV_CARDS];
+
+
+/*
+ * saa7134 DMA audio stop
+ *
+ * Called when the capture device is released or the buffer overflows
+ *
+ * - Copied verbatim from saa7134-oss's dsp_dma_stop.
+ *
+ */
+
+static void saa7134_dma_stop(struct saa7134_dev *dev)
+{
+ dev->dmasound.dma_blk = -1;
+ dev->dmasound.dma_running = 0;
+ saa7134_set_dmabits(dev);
+}
+
+/*
+ * saa7134 DMA audio start
+ *
+ * Called when preparing the capture device for use
+ *
+ * - Copied verbatim from saa7134-oss's dsp_dma_start.
+ *
+ */
+
+static void saa7134_dma_start(struct saa7134_dev *dev)
+{
+ dev->dmasound.dma_blk = 0;
+ dev->dmasound.dma_running = 1;
+ saa7134_set_dmabits(dev);
+}
+
+/*
+ * saa7134 audio DMA IRQ handler
+ *
+ * Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt
+ * Handles shifting between the 2 buffers, manages the read counters,
+ * and notifies ALSA when periods elapse
+ *
+ * - Mostly copied from saa7134-oss's saa7134_irq_oss_done.
+ *
+ */
+
+static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
+ unsigned long status)
+{
+ int next_blk, reg = 0;
+
+ spin_lock(&dev->slock);
+ if (UNSET == dev->dmasound.dma_blk) {
+ dprintk("irq: recording stopped\n");
+ goto done;
+ }
+ if (0 != (status & 0x0f000000))
+ dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
+ if (0 == (status & 0x10000000)) {
+ /* odd */
+ if (0 == (dev->dmasound.dma_blk & 0x01))
+ reg = SAA7134_RS_BA1(6);
+ } else {
+ /* even */
+ if (1 == (dev->dmasound.dma_blk & 0x01))
+ reg = SAA7134_RS_BA2(6);
+ }
+ if (0 == reg) {
+ dprintk("irq: field oops [%s]\n",
+ (status & 0x10000000) ? "even" : "odd");
+ goto done;
+ }
+
+ if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
+ 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_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+ return;
+ }
+
+ /* next block addr */
+ next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
+ saa_writel(reg,next_blk * dev->dmasound.blksize);
+ if (debug > 2)
+ dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
+ (status & 0x10000000) ? "even" : "odd ", next_blk,
+ next_blk * dev->dmasound.blksize, dev->dmasound.blocks, dev->dmasound.blksize, dev->dmasound.read_count);
+
+ /* update status & wake waiting readers */
+ dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
+ dev->dmasound.read_count += dev->dmasound.blksize;
+
+ dev->dmasound.recording_on = reg;
+
+ if (dev->dmasound.read_count >= snd_pcm_lib_period_bytes(dev->dmasound.substream)) {
+ spin_unlock(&dev->slock);
+ snd_pcm_period_elapsed(dev->dmasound.substream);
+ spin_lock(&dev->slock);
+ }
+
+ done:
+ spin_unlock(&dev->slock);
+
+}
+
+/*
+ * IRQ request handler
+ *
+ * Runs along with saa7134's IRQ handler, discards anything that isn't
+ * DMA sound
+ *
+ */
+
+static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct saa7134_dmasound *dmasound = dev_id;
+ struct saa7134_dev *dev = dmasound->priv_data;
+
+ unsigned long report, status;
+ int loop, handled = 0;
+
+ for (loop = 0; loop < 10; loop++) {
+ report = saa_readl(SAA7134_IRQ_REPORT);
+ status = saa_readl(SAA7134_IRQ_STATUS);
+
+ if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
+ handled = 1;
+ saa_writel(SAA7134_IRQ_REPORT,report);
+ saa7134_irq_alsa_done(dev, status);
+ } else {
+ goto out;
+ }
+ }
+
+ if (loop == 10) {
+ dprintk("error! looping IRQ!");
+ }
+
+out:
+ return IRQ_RETVAL(handled);
+}
+
+/*
+ * ALSA capture trigger
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called whenever a capture is started or stopped. Must be defined,
+ * but there's nothing we want to do here
+ *
+ */
+
+static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream,
+ int cmd)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+ struct saa7134_dev *dev=pcm->dev;
+ int err = 0;
+
+ spin_lock(&dev->slock);
+ if (cmd == SNDRV_PCM_TRIGGER_START) {
+ /* start dma */
+ saa7134_dma_start(dev);
+ } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+ /* stop dma */
+ saa7134_dma_stop(dev);
+ } else {
+ err = -EINVAL;
+ }
+ spin_unlock(&dev->slock);
+
+ return err;
+}
+
+/*
+ * DMA buffer initialization
+ *
+ * Uses V4L functions to initialize the DMA. Shouldn't be necessary in
+ * ALSA, but I was unable to use ALSA's own DMA, and had to force the
+ * usage of V4L's
+ *
+ * - Copied verbatim from saa7134-oss.
+ *
+ */
+
+static int dsp_buffer_init(struct saa7134_dev *dev)
+{
+ int err;
+
+ 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);
+ if (0 != err)
+ return err;
+ return 0;
+}
+
+/*
+ * DMA buffer release
+ *
+ * Called after closing the device, during snd_card_saa7134_capture_close
+ *
+ */
+
+static int dsp_buffer_free(struct saa7134_dev *dev)
+{
+ if (!dev->dmasound.blksize)
+ BUG();
+
+ videobuf_dma_free(&dev->dmasound.dma);
+
+ dev->dmasound.blocks = 0;
+ dev->dmasound.blksize = 0;
+ dev->dmasound.bufsize = 0;
+
+ return 0;
+}
+
+
+/*
+ * ALSA PCM preparation
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called right after the capture device is opened, this function configures
+ * the buffer using the previously defined functions, allocates the memory,
+ * sets up the hardware registers, and then starts the DMA. When this function
+ * returns, the audio should be flowing.
+ *
+ */
+
+static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int bswap, sign;
+ u32 fmt, control;
+ snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+ struct saa7134_dev *dev;
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+
+ pcm->dev->dmasound.substream = substream;
+
+ dev = saa7134->dev;
+
+ if (snd_pcm_format_width(runtime->format) == 8)
+ fmt = 0x00;
+ else
+ fmt = 0x01;
+
+ if (snd_pcm_format_signed(runtime->format))
+ sign = 1;
+ else
+ sign = 0;
+
+ if (snd_pcm_format_big_endian(runtime->format))
+ bswap = 1;
+ else
+ bswap = 0;
+
+ switch (dev->pci->device) {
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ if (1 == runtime->channels)
+ fmt |= (1 << 3);
+ if (2 == runtime->channels)
+ fmt |= (3 << 3);
+ if (sign)
+ fmt |= 0x04;
+
+ fmt |= (MIXER_ADDR_TVTUNER == dev->dmasound.input) ? 0xc0 : 0x80;
+ saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff));
+ saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >> 8);
+ saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16);
+ saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ if (1 == runtime->channels)
+ fmt |= (1 << 4);
+ if (2 == runtime->channels)
+ fmt |= (2 << 4);
+ if (!sign)
+ fmt |= 0x04;
+ saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1);
+ saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
+ break;
+ }
+
+ dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n",
+ runtime->format, runtime->channels, fmt,
+ bswap ? 'b' : '-');
+ /* dma: setup channel 6 (= AUDIO) */
+ control = SAA7134_RS_CONTROL_BURST_16 |
+ SAA7134_RS_CONTROL_ME |
+ (dev->dmasound.pt.dma >> 12);
+ if (bswap)
+ control |= SAA7134_RS_CONTROL_BSWAP;
+
+ saa_writel(SAA7134_RS_BA1(6),0);
+ saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
+ saa_writel(SAA7134_RS_PITCH(6),0);
+ saa_writel(SAA7134_RS_CONTROL(6),control);
+
+ dev->dmasound.rate = runtime->rate;
+
+ return 0;
+
+}
+
+/*
+ * ALSA pointer fetching
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called whenever a period elapses, it must return the current hardware
+ * position of the buffer.
+ * Also resets the read counter used to prevent overruns
+ *
+ */
+
+static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+ struct saa7134_dev *dev=pcm->dev;
+
+ if (dev->dmasound.read_count) {
+ dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream);
+ dev->dmasound.read_offset += snd_pcm_lib_period_bytes(substream);
+ if (dev->dmasound.read_offset == dev->dmasound.bufsize)
+ dev->dmasound.read_offset = 0;
+ }
+
+ return bytes_to_frames(runtime, dev->dmasound.read_offset);
+}
+
+/*
+ * ALSA hardware capabilities definition
+ */
+
+static snd_pcm_hardware_t snd_card_saa7134_capture =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S16_BE | \
+ SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_U8 | \
+ SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_U16_BE,
+ .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
+ .rate_min = 32000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (256*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (256*1024),
+ .periods_min = 2,
+ .periods_max = 1024,
+};
+
+static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime)
+{
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+
+ kfree(pcm);
+}
+
+
+/*
+ * ALSA hardware params
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called on initialization, right before the PCM preparation
+ *
+ */
+
+static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+ struct saa7134_dev *dev;
+ unsigned int period_size, periods;
+ int err;
+
+ period_size = params_period_bytes(hw_params);
+ periods = params_periods(hw_params);
+
+ snd_assert(period_size >= 0x100 && period_size <= 0x10000,
+ return -EINVAL);
+ snd_assert(periods >= 2, return -EINVAL);
+ snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL);
+
+ dev = saa7134->dev;
+
+ if (dev->dmasound.blocks == periods &&
+ dev->dmasound.blksize == period_size)
+ return 0;
+
+ /* release the old buffer */
+ if (substream->runtime->dma_area) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ substream->runtime->dma_area = NULL;
+ }
+ dev->dmasound.blocks = periods;
+ dev->dmasound.blksize = period_size;
+ dev->dmasound.bufsize = period_size * periods;
+
+ err = dsp_buffer_init(dev);
+ if (0 != err) {
+ dev->dmasound.blocks = 0;
+ dev->dmasound.blksize = 0;
+ dev->dmasound.bufsize = 0;
+ return err;
+ }
+
+ if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) {
+ dsp_buffer_free(dev);
+ return err;
+ }
+ if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ 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))) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ return err;
+ }
+
+ /* I should be able to use runtime->dma_addr in the control
+ 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.vmalloc;
+
+ return 1;
+
+}
+
+/*
+ * ALSA hardware release
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called after closing the device, but before snd_card_saa7134_capture_close
+ * It stops the DMA audio and releases the buffers.
+ *
+ */
+
+static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream)
+{
+ snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+ struct saa7134_dev *dev;
+
+ dev = saa7134->dev;
+
+ if (substream->runtime->dma_area) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ substream->runtime->dma_area = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * ALSA capture finish
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called after closing the device.
+ *
+ */
+
+static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream)
+{
+ return 0;
+}
+
+/*
+ * ALSA capture start
+ *
+ * - One of the ALSA capture callbacks.
+ *
+ * Called when opening the device. It creates and populates the PCM
+ * structure
+ *
+ */
+
+static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_card_saa7134_pcm_t *pcm;
+ snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+ struct saa7134_dev *dev = saa7134->dev;
+ int err;
+
+ down(&dev->dmasound.lock);
+
+ dev->dmasound.read_count = 0;
+ dev->dmasound.read_offset = 0;
+
+ up(&dev->dmasound.lock);
+
+ pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+ if (pcm == NULL)
+ return -ENOMEM;
+
+ pcm->dev=saa7134->dev;
+
+ spin_lock_init(&pcm->lock);
+
+ pcm->substream = substream;
+ runtime->private_data = pcm;
+ runtime->private_free = snd_card_saa7134_runtime_free;
+ runtime->hw = snd_card_saa7134_capture;
+
+ if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ return err;
+
+ return 0;
+}
+
+/*
+ * ALSA capture callbacks definition
+ */
+
+static snd_pcm_ops_t snd_card_saa7134_capture_ops = {
+ .open = snd_card_saa7134_capture_open,
+ .close = snd_card_saa7134_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_card_saa7134_hw_params,
+ .hw_free = snd_card_saa7134_hw_free,
+ .prepare = snd_card_saa7134_capture_prepare,
+ .trigger = snd_card_saa7134_capture_trigger,
+ .pointer = snd_card_saa7134_capture_pointer,
+};
+
+/*
+ * ALSA PCM setup
+ *
+ * Called when initializing the board. Sets up the name and hooks up
+ * the callbacks
+ *
+ */
+
+static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device)
+{
+ snd_pcm_t *pcm;
+ int err;
+
+ if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0)
+ return err;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops);
+ pcm->private_data = saa7134;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, "SAA7134 PCM");
+ return 0;
+}
+
+#define SAA713x_VOLUME(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+ .info = snd_saa7134_volume_info, \
+ .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \
+ .private_value = addr }
+
+static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 20;
+ return 0;
+}
+
+static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+ int addr = kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0];
+ ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1];
+ return 0;
+}
+
+static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+ int change, addr = kcontrol->private_value;
+ int left, right;
+
+ left = ucontrol->value.integer.value[0];
+ if (left < 0)
+ left = 0;
+ if (left > 20)
+ left = 20;
+ right = ucontrol->value.integer.value[1];
+ if (right < 0)
+ right = 0;
+ if (right > 20)
+ right = 20;
+ spin_lock_irq(&chip->mixer_lock);
+ change = chip->mixer_volume[addr][0] != left ||
+ chip->mixer_volume[addr][1] != right;
+ chip->mixer_volume[addr][0] = left;
+ chip->mixer_volume[addr][1] = right;
+ spin_unlock_irq(&chip->mixer_lock);
+ return change;
+}
+
+#define SAA713x_CAPSRC(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+ .info = snd_saa7134_capsrc_info, \
+ .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \
+ .private_value = addr }
+
+static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+ int addr = kcontrol->private_value;
+
+ spin_lock_irq(&chip->mixer_lock);
+ ucontrol->value.integer.value[0] = chip->capture_source[addr][0];
+ ucontrol->value.integer.value[1] = chip->capture_source[addr][1];
+ spin_unlock_irq(&chip->mixer_lock);
+
+ return 0;
+}
+
+static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+ int change, addr = kcontrol->private_value;
+ int left, right;
+ u32 anabar, xbarin;
+ int analog_io, rate;
+ struct saa7134_dev *dev;
+
+ dev = chip->dev;
+
+ left = ucontrol->value.integer.value[0] & 1;
+ right = ucontrol->value.integer.value[1] & 1;
+ spin_lock_irq(&chip->mixer_lock);
+
+ change = chip->capture_source[addr][0] != left ||
+ chip->capture_source[addr][1] != right;
+ chip->capture_source[addr][0] = left;
+ chip->capture_source[addr][1] = right;
+ dev->dmasound.input=addr;
+ spin_unlock_irq(&chip->mixer_lock);
+
+
+ if (change) {
+ switch (dev->pci->device) {
+
+ case PCI_DEVICE_ID_PHILIPS_SAA7134:
+ switch (addr) {
+ case MIXER_ADDR_TVTUNER:
+ saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
+ saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00);
+ break;
+ case MIXER_ADDR_LINE1:
+ case MIXER_ADDR_LINE2:
+ analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08;
+ rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03;
+ saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io);
+ saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80);
+ saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate);
+ break;
+ }
+
+ break;
+ case PCI_DEVICE_ID_PHILIPS_SAA7133:
+ case PCI_DEVICE_ID_PHILIPS_SAA7135:
+ xbarin = 0x03; // adc
+ anabar = 0;
+ switch (addr) {
+ case MIXER_ADDR_TVTUNER:
+ xbarin = 0; // Demodulator
+ anabar = 2; // DACs
+ break;
+ case MIXER_ADDR_LINE1:
+ anabar = 0; // aux1, aux1
+ break;
+ case MIXER_ADDR_LINE2:
+ anabar = 9; // aux2, aux2
+ break;
+ }
+
+ /* output xbar always main channel */
+ saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10);
+
+ if (left || right) { // We've got data, turn the input on
+ saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin);
+ saa_writel(SAA7133_ANALOG_IO_SELECT, anabar);
+ } else {
+ saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0);
+ saa_writel(SAA7133_ANALOG_IO_SELECT, 0);
+ }
+ break;
+ }
+ }
+
+ return change;
+}
+
+static snd_kcontrol_new_t snd_saa7134_controls[] = {
+SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER),
+SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER),
+SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1),
+SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1),
+SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2),
+SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2),
+};
+
+/*
+ * ALSA mixer setup
+ *
+ * Called when initializing the board. Sets up the name and hooks up
+ * the callbacks
+ *
+ */
+
+static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
+{
+ snd_card_t *card = chip->card;
+ unsigned int idx;
+ int err;
+
+ snd_assert(chip != NULL, return -EINVAL);
+ strcpy(card->mixername, "SAA7134 Mixer");
+
+ for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) {
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_controls[idx], chip))) < 0)
+ return err;
+ }
+ return 0;
+}
+
+static void snd_saa7134_free(snd_card_t * card)
+{
+ snd_card_saa7134_t *chip = card->private_data;
+
+ if (chip->dev->dmasound.priv_data == NULL)
+ return;
+
+ if (chip->irq >= 0) {
+ synchronize_irq(chip->irq);
+ free_irq(chip->irq, &chip->dev->dmasound);
+ }
+
+ chip->dev->dmasound.priv_data = NULL;
+
+}
+
+/*
+ * ALSA initialization
+ *
+ * Called by the init routine, once for each saa7134 device present,
+ * it creates the basic structures and registers the ALSA devices
+ *
+ */
+
+static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
+{
+
+ snd_card_t *card;
+ snd_card_saa7134_t *chip;
+ int err;
+
+
+ if (devnum >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[devnum])
+ return -ENODEV;
+
+ card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t));
+
+ if (card == NULL)
+ return -ENOMEM;
+
+ strcpy(card->driver, "SAA7134");
+
+ /* Card "creation" */
+
+ card->private_free = snd_saa7134_free;
+ chip = (snd_card_saa7134_t *) card->private_data;
+
+ spin_lock_init(&chip->lock);
+ spin_lock_init(&chip->mixer_lock);
+
+ chip->dev = dev;
+
+ chip->card = card;
+
+ chip->pci = dev->pci;
+ chip->iobase = pci_resource_start(dev->pci, 0);
+
+
+ err = request_irq(dev->pci->irq, saa7134_alsa_irq,
+ SA_SHIRQ | SA_INTERRUPT, dev->name,
+ (void*) &dev->dmasound);
+
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n",
+ dev->name, dev->pci->irq);
+ goto __nodev;
+ }
+
+ chip->irq = dev->pci->irq;
+
+ init_MUTEX(&dev->dmasound.lock);
+
+ if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
+ goto __nodev;
+
+ 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");
+ sprintf(card->longname, "%s at 0x%lx irq %d",
+ chip->dev->name, chip->iobase, chip->irq);
+
+ printk(KERN_INFO "%s/alsa: %s registered as card %d\n",dev->name,card->longname,index[devnum]);
+
+ if ((err = snd_card_register(card)) == 0) {
+ snd_saa7134_cards[devnum] = card;
+ return 0;
+ }
+
+__nodev:
+ snd_card_free(card);
+ return err;
+}
+
+
+static int alsa_device_init(struct saa7134_dev *dev)
+{
+ dev->dmasound.priv_data = dev;
+ alsa_card_saa7134_create(dev,dev->nr);
+ return 1;
+}
+
+static int alsa_device_exit(struct saa7134_dev *dev)
+{
+
+ snd_card_free(snd_saa7134_cards[dev->nr]);
+ snd_saa7134_cards[dev->nr] = NULL;
+ return 1;
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+
+static int saa7134_alsa_init(void)
+{
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
+
+ printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
+
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
+ if (dev->dmasound.priv_data == NULL) {
+ alsa_device_init(dev);
+ } else {
+ printk(KERN_ERR "saa7134 ALSA: DMA sound is being handled by OSS. ignoring %s\n",dev->name);
+ return -EBUSY;
+ }
+ }
+
+ dmasound_init = alsa_device_init;
+ dmasound_exit = alsa_device_exit;
+
+ if (dev == NULL)
+ printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n");
+
+ return 0;
+}
+
+/*
+ * Module destructor
+ */
+
+static void saa7134_alsa_exit(void)
+{
+ int idx;
+
+ for (idx = 0; idx < SNDRV_CARDS; idx++) {
+ snd_card_free(snd_saa7134_cards[idx]);
+ }
+
+ printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
+
+ return;
+}
+
+module_init(saa7134_alsa_init);
+module_exit(saa7134_alsa_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ricardo Cerqueira");
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index acc7a4335e2..75abc20b0cc 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -191,10 +191,14 @@ struct saa7134_board saa7134_boards[] = {
.amux = TV,
.tv = 1,
},{
- .name = name_comp1,
+ .name = name_comp1, /* Composite signal on S-Video input */
.vmux = 0,
.amux = LINE2,
},{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ },{
.name = name_svideo,
.vmux = 8,
.amux = LINE2,
@@ -2109,8 +2113,449 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x01,
},
},
-};
+ [SAA7134_BOARD_BEHOLD_409FM] = {
+ /* <http://tuner.beholder.ru>, Sergey <skiv@orel.ru> */
+ .name = "Beholder BeholdTV 409 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_GOTVIEW_7135] = {
+ /* Mike Baikov <mike@baikov.com> */
+ /* Andrey Cvetcov <ays14@yandex.ru> */
+ .name = "GoTView 7135 PCI",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x00200003,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x00200003,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .gpio = 0x00200003,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ .gpio = 0x00200003,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ .gpio = 0x00200003,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x00200003,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ .gpio = 0x00200003,
+ },
+ },
+ [SAA7134_BOARD_PHILIPS_EUROPA] = {
+ .name = "Philips EUROPA V3 reference design",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TD1316,
+ .radio_type = UNSET,
+ .tuner_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_VIDEOMATE_DVBT_300] = {
+ .name = "Compro Videomate DVB-T300",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TD1316,
+ .radio_type = UNSET,
+ .tuner_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_VIDEOMATE_DVBT_200] = {
+ .name = "Compro Videomate DVB-T200",
+ .tuner_type = TUNER_ABSENT,
+ .audio_clock = 0x00187de7,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ },
+ [SAA7134_BOARD_RTD_VFG7350] = {
+ .name = "RTD Embedded Technologies VFG7350",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = "Composite 0",
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = "Composite 1",
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = "Composite 2",
+ .vmux = 2,
+ .amux = LINE1,
+ },{
+ .name = "Composite 3",
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = "S-Video 0",
+ .vmux = 8,
+ .amux = LINE1,
+ },{
+ .name = "S-Video 1",
+ .vmux = 9,
+ .amux = LINE2,
+ }},
+ .mpeg = SAA7134_MPEG_EMPRESS,
+ .video_out = CCIR656,
+ .vid_port_opts = ( SET_T_CODE_POLARITY_NON_INVERTED |
+ SET_CLOCK_NOT_DELAYED |
+ SET_CLOCK_INVERTED |
+ SET_VSYNC_OFF ),
+ },
+ [SAA7134_BOARD_RTD_VFG7330] = {
+ .name = "RTD Embedded Technologies VFG7330",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = "Composite 0",
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = "Composite 1",
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = "Composite 2",
+ .vmux = 2,
+ .amux = LINE1,
+ },{
+ .name = "Composite 3",
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = "S-Video 0",
+ .vmux = 8,
+ .amux = LINE1,
+ },{
+ .name = "S-Video 1",
+ .vmux = 9,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = {
+ .name = "LifeView FlyTV Platinum Mini2",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
+ /* Michael Krufky <mkrufky@m1k.net>
+ * Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
+ * AFAIK, there is no analog demod, thus,
+ * no support for analog television.
+ */
+ .name = "AVerMedia AVerTVHD MCE A180",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_MONSTERTV_MOBILE] = {
+ .name = "SKNet MonsterTV Mobile",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE1,
+ }},
+ },
+ [SAA7134_BOARD_PINNACLE_PCTV_110i] = {
+ .name = "Pinnacle PCTV 110i (saa7133)",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x080200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 4,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ },
+ },
+ [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = {
+ .name = "ASUSTeK P7131 Dual",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 1 << 21,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_SEDNA_PC_TV_CARDBUS] = {
+ /* Paul Tom Zalac <pzalac@gmail.com> */
+ /* Pavel Mihaylov <bin@bash.info> */
+ .name = "Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)",
+ /* Sedna/MuchTV (OEM) Cardbus TV Tuner */
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0xe880c0,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV] = {
+ /* "Cyril Lacoux (Yack)" <clacoux@ifeelgood.org> */
+ .name = "ASUS Digimatrix TV",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .tda9887_conf = TDA9887_PRESENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ },
+ [SAA7134_BOARD_PHILIPS_TIGER] = {
+ .name = "Philips Tiger reference design",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ },
+ [SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = {
+ .name = "MSI TV@Anywhere plus",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 0,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ },
+ },
+};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -2145,19 +2590,19 @@ struct pci_device_id saa7134_pci_tbl[] = {
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
- .subvendor = 0x153B,
+ .subvendor = 0x153b,
.subdevice = 0x1142,
.driver_data = SAA7134_BOARD_CINERGY400,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
- .subvendor = 0x153B,
+ .subvendor = 0x153b,
.subdevice = 0x1143,
.driver_data = SAA7134_BOARD_CINERGY600,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
- .subvendor = 0x153B,
+ .subvendor = 0x153b,
.subdevice = 0x1158,
.driver_data = SAA7134_BOARD_CINERGY600_MK3,
},{
@@ -2193,6 +2638,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x14c0,
+ .subdevice = 0x1212, /* minipci, LR1212 */
+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI2,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x4e42,
+ .subdevice = 0x0212, /* OEM minipci, LR212 */
+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168, /* Animation Technologies (LifeView) */
.subdevice = 0x0214, /* Standard PCI, LR214WF */
.driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
@@ -2369,7 +2826,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
- .subvendor = 0x153B,
+ .subvendor = 0x153b,
.subdevice = 0x1152,
.driver_data = SAA7134_BOARD_CINERGY200,
},{
@@ -2434,13 +2891,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x1421,
.subdevice = 0x0350, /* PCI version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
-
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1421,
.subdevice = 0x0370, /* cardbus version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1421,
+ .subdevice = 0x1370, /* cardbus version */
+ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
},{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */
.vendor = PCI_VENDOR_ID_PHILIPS,
@@ -2459,9 +2921,87 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x1043,
.subdevice = 0x0210, /* mini pci PAL/SECAM version */
- .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX,
+ .driver_data = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */
+ .subdevice = 0x4091,
+ .driver_data = SAA7134_BOARD_BEHOLD_409FM,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5456, /* GoTView */
+ .subdevice = 0x7135,
+ .driver_data = SAA7134_BOARD_GOTVIEW_7135,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = PCI_VENDOR_ID_PHILIPS,
+ .subdevice = 0x2004,
+ .driver_data = SAA7134_BOARD_PHILIPS_EUROPA,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x185b,
+ .subdevice = 0xc900,
+ .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x185b,
+ .subdevice = 0xc901,
+ .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1435,
+ .subdevice = 0x7350,
+ .driver_data = SAA7134_BOARD_RTD_VFG7350,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1435,
+ .subdevice = 0x7330,
+ .driver_data = SAA7134_BOARD_RTD_VFG7330,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461,
+ .subdevice = 0x1044,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1131,
+ .subdevice = 0x4ee9,
+ .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x11bd,
+ .subdevice = 0x002e,
+ .driver_data = SAA7134_BOARD_PINNACLE_PCTV_110i,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1043,
+ .subdevice = 0x4862,
+ .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = PCI_VENDOR_ID_PHILIPS,
+ .subdevice = 0x2018,
+ .driver_data = SAA7134_BOARD_PHILIPS_TIGER,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1462,
+ .subdevice = 0x6231,
+ .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -2530,9 +3070,10 @@ int saa7134_board_init1(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_FLYVIDEO2000:
case SAA7134_BOARD_FLYVIDEO3000:
- dev->has_remote = 1;
+ dev->has_remote = SAA7134_REMOTE_GPIO;
board_flyvideo(dev);
break;
+ case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
case SAA7134_BOARD_FLYTVPLATINUM_FM:
case SAA7134_BOARD_CINERGY400:
case SAA7134_BOARD_CINERGY600:
@@ -2550,10 +3091,16 @@ int saa7134_board_init1(struct saa7134_dev *dev)
/* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200:
case SAA7134_BOARD_MANLI_MTV001:
case SAA7134_BOARD_MANLI_MTV002:
+ case SAA7134_BOARD_BEHOLD_409FM:
case SAA7134_BOARD_AVACSSMARTTV:
- dev->has_remote = 1;
+ case SAA7134_BOARD_GOTVIEW_7135:
+ case SAA7134_BOARD_KWORLD_TERMINATOR:
+ case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
+ dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_MD5044:
printk("%s: seems there are two different versions of the MD5044\n"
@@ -2565,11 +3112,14 @@ int saa7134_board_init1(struct saa7134_dev *dev)
/* power-up tuner chip */
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
- msleep(1);
+ case SAA7134_BOARD_MONSTERTV_MOBILE:
+ /* power-up tuner chip */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
break;
case SAA7134_BOARD_FLYDVBTDUO:
case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
- /* turn the fan on Hac: static for the time being */
+ /* turn the fan on */
saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
break;
@@ -2579,6 +3129,22 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
msleep(1);
break;
+ case SAA7134_BOARD_RTD_VFG7350:
+
+ /*
+ * Make sure Production Test Register at offset 0x1D1 is cleared
+ * to take chip out of test mode. Clearing bit 4 (TST_EN_AOUT)
+ * prevents pin 105 from remaining low; keeping pin 105 low
+ * continually resets the SAA6752 chip.
+ */
+
+ saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
+ break;
+ /* i2c remotes */
+ case SAA7134_BOARD_PINNACLE_PCTV_110i:
+ case SAA7134_BOARD_UPMOST_PURPLE_TV:
+ dev->has_remote = SAA7134_REMOTE_I2C;
+ break;
}
return 0;
}
@@ -2613,7 +3179,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup);
}
break;
-case SAA7134_BOARD_MD7134:
+ case SAA7134_BOARD_MD7134:
{
struct tuner_setup tun_setup;
u8 subaddr;
@@ -2680,6 +3246,33 @@ case SAA7134_BOARD_MD7134:
saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
}
break;
+ case SAA7134_BOARD_PHILIPS_EUROPA:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ /* The Philips EUROPA based hybrid boards have the tuner connected through
+ * the channel decoder. We have to make it transparent to find it
+ */
+ {
+ struct tuner_setup tun_setup;
+ u8 data[] = { 0x07, 0x02};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+ tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+ tun_setup.type = dev->tuner_type;
+ tun_setup.addr = dev->tuner_addr;
+
+ saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
+ }
+ break;
+ case SAA7134_BOARD_PHILIPS_TIGER:
+ case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+ /* this is a hybrid board, initialize to analog mode */
+ {
+ u8 data[] = { 0x3c, 0x33, 0x68};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+ }
+ break;
}
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index e5e36f3c625..1a093bf176f 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -53,9 +53,13 @@ static unsigned int gpio_tracking = 0;
module_param(gpio_tracking, int, 0644);
MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
+static unsigned int alsa = 0;
+module_param(alsa, int, 0644);
+MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
+
static unsigned int oss = 0;
-module_param(oss, int, 0444);
-MODULE_PARM_DESC(oss,"register oss devices (default: no)");
+module_param(oss, int, 0644);
+MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
static unsigned int latency = UNSET;
module_param(latency, int, 0444);
@@ -64,24 +68,18 @@ MODULE_PARM_DESC(latency,"pci latency timer");
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 };
-static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
module_param_array(video_nr, int, NULL, 0444);
module_param_array(vbi_nr, int, NULL, 0444);
module_param_array(radio_nr, int, NULL, 0444);
-module_param_array(dsp_nr, int, NULL, 0444);
-module_param_array(mixer_nr, int, NULL, 0444);
module_param_array(tuner, int, NULL, 0444);
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "video device number");
MODULE_PARM_DESC(vbi_nr, "vbi device number");
MODULE_PARM_DESC(radio_nr, "radio device number");
-MODULE_PARM_DESC(dsp_nr, "oss dsp device number");
-MODULE_PARM_DESC(mixer_nr, "oss mixer device number");
MODULE_PARM_DESC(tuner, "tuner type");
MODULE_PARM_DESC(card, "card type");
@@ -90,6 +88,9 @@ LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
static unsigned int saa7134_devcount;
+int (*dmasound_init)(struct saa7134_dev *dev);
+int (*dmasound_exit)(struct saa7134_dev *dev);
+
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
@@ -186,10 +187,11 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
/* ----------------------------------------------------------- */
/* delayed request_module */
-#ifdef CONFIG_MODULES
-
+#if defined(CONFIG_MODULES) && defined(MODULE)
static int need_empress;
static int need_dvb;
+static int need_alsa;
+static int need_oss;
static int pending_call(struct notifier_block *self, unsigned long state,
void *module)
@@ -197,10 +199,14 @@ static int pending_call(struct notifier_block *self, unsigned long state,
if (module != THIS_MODULE || state != MODULE_STATE_LIVE)
return NOTIFY_DONE;
- if (need_empress)
- request_module("saa7134-empress");
- if (need_dvb)
- request_module("saa7134-dvb");
+ if (need_empress)
+ request_module("saa7134-empress");
+ if (need_dvb)
+ request_module("saa7134-dvb");
+ if (need_alsa)
+ request_module("saa7134-alsa");
+ if (need_oss)
+ request_module("saa7134-oss");
return NOTIFY_DONE;
}
@@ -211,10 +217,11 @@ static struct notifier_block pending_notifier = {
static void request_module_depend(char *name, int *flag)
{
+ int err;
switch (THIS_MODULE->state) {
case MODULE_STATE_COMING:
if (!pending_registered) {
- register_module_notifier(&pending_notifier);
+ err = register_module_notifier(&pending_notifier);
pending_registered = 1;
}
*flag = 1;
@@ -229,9 +236,7 @@ static void request_module_depend(char *name, int *flag)
}
#else
-
#define request_module_depend(name,flag)
-
#endif /* CONFIG_MODULES */
/* ------------------------------------------------------------------ */
@@ -275,8 +280,8 @@ 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;
+ __le32 *cpu;
+ dma_addr_t dma_addr;
cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
if (NULL == cpu)
@@ -436,7 +441,7 @@ 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->video_q.curr->vb.field;
}
/* video capture -- dma 1+2 (planar modes) */
@@ -465,7 +470,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
}
/* audio capture -- dma 3 */
- if (dev->oss.dma_running) {
+ if (dev->dmasound.dma_running) {
ctrl |= SAA7134_MAIN_CTRL_TE6;
irq |= SAA7134_IRQ1_INTE_RA3_1 |
SAA7134_IRQ1_INTE_RA3_0;
@@ -570,6 +575,19 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
dev->name);
goto out;
}
+
+ /* If dmasound support is active and we get a sound report, exit
+ and let the saa7134-alsa/oss module deal with it */
+
+ if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
+ (dev->dmasound.priv_data != NULL) )
+ {
+ if (irq_debug > 1)
+ printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n",
+ dev->name);
+ goto out;
+ }
+
handled = 1;
saa_writel(SAA7134_IRQ_REPORT,report);
if (irq_debug)
@@ -591,13 +609,11 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
card_has_mpeg(dev))
saa7134_irq_ts_done(dev,status);
- if ((report & SAA7134_IRQ_REPORT_DONE_RA3))
- saa7134_irq_oss_done(dev,status);
-
if ((report & (SAA7134_IRQ_REPORT_GPIO16 |
SAA7134_IRQ_REPORT_GPIO18)) &&
dev->remote)
saa7134_input_irq(dev);
+
}
if (10 == loop) {
@@ -636,7 +652,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, 0);
- init_MUTEX(&dev->lock);
+ init_MUTEX(&dev->lock);
spin_lock_init(&dev->slock);
saa7134_track_gpio(dev,"pre-init");
@@ -646,14 +662,6 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
saa7134_ts_init1(dev);
saa7134_input_init1(dev);
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- saa7134_oss_init1(dev);
- break;
- }
-
/* RAM FIFO config */
saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
saa_writel(SAA7134_THRESHOULD,0x02020202);
@@ -668,6 +676,13 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
SAA7134_MAIN_CTRL_ESFE |
SAA7134_MAIN_CTRL_EBDAC);
+ /*
+ * Initialize OSS _after_ enabling audio clock PLL and audio processing.
+ * OSS initialization writes to registers via the audio DSP; these
+ * writes will fail unless the audio clock has been started. At worst,
+ * audio will not work.
+ */
+
/* enable peripheral devices */
saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
@@ -687,7 +702,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
saa7134_tvaudio_init2(dev);
/* enable IRQ's */
- irq2_mask =
+ irq2_mask =
SAA7134_IRQ2_INTE_DEC3 |
SAA7134_IRQ2_INTE_DEC2 |
SAA7134_IRQ2_INTE_DEC1 |
@@ -695,7 +710,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
SAA7134_IRQ2_INTE_PE |
SAA7134_IRQ2_INTE_AR;
- if (dev->has_remote)
+ if (dev->has_remote == SAA7134_REMOTE_GPIO)
irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 |
SAA7134_IRQ2_INTE_GPIO18A |
SAA7134_IRQ2_INTE_GPIO16 );
@@ -711,13 +726,6 @@ static int saa7134_hwfini(struct saa7134_dev *dev)
{
dprintk("hwfini\n");
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- saa7134_oss_fini(dev);
- break;
- }
if (card_has_mpeg(dev))
saa7134_ts_fini(dev);
saa7134_input_fini(dev);
@@ -872,8 +880,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* print pci info */
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
- pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
- printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
+ pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
+ printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
"latency: %d, mmio: 0x%lx\n", dev->name,
pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
dev->pci_lat,pci_resource_start(pci_dev,0));
@@ -897,7 +905,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
if (UNSET != tuner[dev->nr])
dev->tuner_type = tuner[dev->nr];
- printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+ printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
dev->name,pci_dev->subsystem_vendor,
pci_dev->subsystem_device,saa7134_boards[dev->board].name,
dev->board, card[dev->nr] == dev->board ?
@@ -947,14 +955,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
request_module("tuner");
if (dev->tda9887_conf)
request_module("tda9887");
- if (card_is_empress(dev)) {
+ if (card_is_empress(dev)) {
request_module("saa6752hs");
request_module_depend("saa7134-empress",&need_empress);
}
- if (card_is_dvb(dev))
+ if (card_is_dvb(dev))
request_module_depend("saa7134-dvb",&need_dvb);
+
+ if (alsa)
+ request_module_depend("saa7134-alsa",&need_alsa);
+
+ if (oss)
+ request_module_depend("saa7134-oss",&need_oss);
+
v4l2_prio_init(&dev->prio);
/* register v4l devices */
@@ -987,32 +1002,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->name,dev->radio_dev->minor & 0x1f);
}
- /* register oss devices */
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (oss) {
- err = dev->oss.minor_dsp =
- register_sound_dsp(&saa7134_dsp_fops,
- dsp_nr[dev->nr]);
- if (err < 0) {
- goto fail4;
- }
- printk(KERN_INFO "%s: registered device dsp%d\n",
- dev->name,dev->oss.minor_dsp >> 4);
-
- err = dev->oss.minor_mixer =
- register_sound_mixer(&saa7134_mixer_fops,
- mixer_nr[dev->nr]);
- if (err < 0)
- goto fail5;
- printk(KERN_INFO "%s: registered device mixer%d\n",
- dev->name,dev->oss.minor_mixer >> 4);
- }
- break;
- }
-
/* everything worked */
pci_set_drvdata(pci_dev,dev);
saa7134_devcount++;
@@ -1027,17 +1016,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* check for signal */
saa7134_irq_video_intl(dev);
- return 0;
- fail5:
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (oss)
- unregister_sound_dsp(dev->oss.minor_dsp);
- break;
+ if (dmasound_init && !dev->dmasound.priv_data) {
+ dmasound_init(dev);
}
+
+ return 0;
+
fail4:
saa7134_unregister_video(dev);
saa7134_i2c_unregister(dev);
@@ -1055,10 +1040,15 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
{
- struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+ struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
struct list_head *item;
struct saa7134_mpeg_ops *mops;
+ /* Release DMA sound modules if present */
+ if (dmasound_exit && dev->dmasound.priv_data) {
+ dmasound_exit(dev);
+ }
+
/* debugging ... */
if (irq_debug) {
u32 report = saa_readl(SAA7134_IRQ_REPORT);
@@ -1088,19 +1078,18 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa7134_devcount--;
saa7134_i2c_unregister(dev);
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (oss) {
- unregister_sound_mixer(dev->oss.minor_mixer);
- unregister_sound_dsp(dev->oss.minor_dsp);
- }
- break;
- }
saa7134_unregister_video(dev);
- /* release ressources */
+
+ /* the DMA sound modules should be unloaded before reaching
+ this, but just in case they are still present... */
+ if (dev->dmasound.priv_data != NULL) {
+ free_irq(pci_dev->irq, &dev->dmasound);
+ dev->dmasound.priv_data = NULL;
+ }
+
+
+ /* release resources */
free_irq(pci_dev->irq, dev);
iounmap(dev->lmmio);
release_mem_region(pci_resource_start(pci_dev,0),
@@ -1149,10 +1138,10 @@ EXPORT_SYMBOL(saa7134_ts_unregister);
/* ----------------------------------------------------------- */
static struct pci_driver saa7134_pci_driver = {
- .name = "saa7134",
- .id_table = saa7134_pci_tbl,
- .probe = saa7134_initdev,
- .remove = __devexit_p(saa7134_finidev),
+ .name = "saa7134",
+ .id_table = saa7134_pci_tbl,
+ .probe = saa7134_initdev,
+ .remove = __devexit_p(saa7134_finidev),
};
static int saa7134_init(void)
@@ -1171,10 +1160,10 @@ static int saa7134_init(void)
static void saa7134_fini(void)
{
-#ifdef CONFIG_MODULES
+#if defined(CONFIG_MODULES) && defined(MODULE)
if (pending_registered)
unregister_module_notifier(&pending_notifier);
-#endif
+#endif /* CONFIG_MODULES */
pci_unregister_driver(&saa7134_pci_driver);
}
@@ -1188,6 +1177,15 @@ EXPORT_SYMBOL(saa7134_i2c_call_clients);
EXPORT_SYMBOL(saa7134_devlist);
EXPORT_SYMBOL(saa7134_boards);
+/* ----------------- for the DMA sound modules --------------- */
+
+EXPORT_SYMBOL(dmasound_init);
+EXPORT_SYMBOL(dmasound_exit);
+EXPORT_SYMBOL(saa7134_pgtable_free);
+EXPORT_SYMBOL(saa7134_pgtable_build);
+EXPORT_SYMBOL(saa7134_pgtable_alloc);
+EXPORT_SYMBOL(saa7134_set_dmabits);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 639ae51a052..e016480c346 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -29,7 +29,6 @@
#include <linux/kthread.h>
#include <linux/suspend.h>
-
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -40,6 +39,10 @@
#ifdef HAVE_TDA1004X
# include "tda1004x.h"
#endif
+#ifdef HAVE_NXT200X
+# include "nxt200x.h"
+# include "dvb-pll.h"
+#endif
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
@@ -151,25 +154,12 @@ static struct mt352_config pinnacle_300i = {
/* ------------------------------------------------------------------ */
#ifdef HAVE_TDA1004X
-static int philips_tu1216_pll_init(struct dvb_frontend *fe)
-{
- struct saa7134_dev *dev = fe->dvb->priv;
- static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
- struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
-
- /* setup PLL configuration */
- if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
- return -EIO;
- msleep(1);
- return 0;
-}
-
-static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct saa7134_dev *dev = fe->dvb->priv;
u8 tuner_buf[4];
- struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
+ struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len =
sizeof(tuner_buf) };
int tuner_frequency = 0;
u8 band, cp, filter;
@@ -242,11 +232,36 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
+ msleep(1);
+ return 0;
+}
+static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
+ struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
+
+ /* setup PLL configuration */
+ if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
+ return -EIO;
msleep(1);
+
return 0;
}
+/* ------------------------------------------------------------------ */
+
+static int philips_tu1216_pll_60_init(struct dvb_frontend *fe)
+{
+ return philips_tda6651_pll_init(0x60, fe);
+}
+
+static int philips_tu1216_pll_60_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ return philips_tda6651_pll_set(0x60, fe, params);
+}
+
static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
const struct firmware **fw, char *name)
{
@@ -254,22 +269,108 @@ static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
return request_firmware(fw, name, &dev->pci->dev);
}
-static struct tda1004x_config philips_tu1216_config = {
+static struct tda1004x_config philips_tu1216_60_config = {
+
+ .demod_address = 0x8,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_4M,
+ .agc_config = TDA10046_AGC_DEFAULT,
+ .if_freq = TDA10046_FREQ_3617,
+ .pll_init = philips_tu1216_pll_60_init,
+ .pll_set = philips_tu1216_pll_60_set,
+ .pll_sleep = NULL,
+ .request_firmware = philips_tu1216_request_firmware,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int philips_tu1216_pll_61_init(struct dvb_frontend *fe)
+{
+ return philips_tda6651_pll_init(0x61, fe);
+}
+
+static int philips_tu1216_pll_61_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ return philips_tda6651_pll_set(0x61, fe, params);
+}
+
+static struct tda1004x_config philips_tu1216_61_config = {
.demod_address = 0x8,
.invert = 1,
- .invert_oclk = 1,
+ .invert_oclk = 0,
.xtal_freq = TDA10046_XTAL_4M,
.agc_config = TDA10046_AGC_DEFAULT,
.if_freq = TDA10046_FREQ_3617,
- .pll_init = philips_tu1216_pll_init,
- .pll_set = philips_tu1216_pll_set,
+ .pll_init = philips_tu1216_pll_61_init,
+ .pll_set = philips_tu1216_pll_61_set,
.pll_sleep = NULL,
.request_firmware = philips_tu1216_request_firmware,
};
/* ------------------------------------------------------------------ */
+static int philips_europa_pll_init(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
+ struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+ /* setup PLL configuration */
+ if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
+ return -EIO;
+ msleep(1);
+
+ /* switch the board to dvb mode */
+ init_msg.addr = 0x43;
+ init_msg.len = 0x02;
+ msg[0] = 0x00;
+ msg[1] = 0x40;
+ if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+
+static int philips_td1316_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ return philips_tda6651_pll_set(0x61, fe, params);
+}
+
+static void philips_europa_analog(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ /* this message actually turns the tuner back to analog mode */
+ static u8 msg[] = { 0x0b, 0xdc, 0x86, 0xa4 };
+ struct i2c_msg analog_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+ i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
+ msleep(1);
+
+ /* switch the board to analog mode */
+ analog_msg.addr = 0x43;
+ analog_msg.len = 0x02;
+ msg[0] = 0x00;
+ msg[1] = 0x14;
+ i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
+}
+
+static struct tda1004x_config philips_europa_config = {
+
+ .demod_address = 0x8,
+ .invert = 0,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_4M,
+ .agc_config = TDA10046_AGC_IFO_AUTO_POS,
+ .if_freq = TDA10046_FREQ_052,
+ .pll_init = philips_europa_pll_init,
+ .pll_set = philips_td1316_pll_set,
+ .pll_sleep = philips_europa_analog,
+ .request_firmware = NULL,
+};
+
+/* ------------------------------------------------------------------ */
static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
{
@@ -382,7 +483,6 @@ static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
return 0;
}
-#ifdef HAVE_TDA1004X
static struct tda1004x_config medion_cardbus = {
.demod_address = 0x08,
.invert = 1,
@@ -395,7 +495,6 @@ static struct tda1004x_config medion_cardbus = {
.pll_sleep = philips_fmd1216_analog,
.request_firmware = NULL,
};
-#endif
/* ------------------------------------------------------------------ */
@@ -452,7 +551,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
u8 tuner_buf[14];
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,
- .len = sizeof(tuner_buf) };
+ .len = sizeof(tuner_buf) };
int i, tuner_freq, if_freq;
u32 N;
switch (params->u.ofdm.bandwidth) {
@@ -511,7 +610,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe)
struct saa7134_dev *dev = fe->dvb->priv;
static u8 tda827x_sleep[] = { 0x30, 0xd0};
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep,
- .len = sizeof(tda827x_sleep) };
+ .len = sizeof(tda827x_sleep) };
i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
}
@@ -527,6 +626,202 @@ static struct tda1004x_config tda827x_lifeview_config = {
.pll_sleep = philips_tda827x_pll_sleep,
.request_firmware = NULL,
};
+
+/* ------------------------------------------------------------------ */
+
+struct tda827xa_data {
+ u32 lomax;
+ u8 svco;
+ u8 spd;
+ u8 scr;
+ u8 sbs;
+ u8 gc3;
+};
+
+static struct tda827xa_data tda827xa_dvbt[] = {
+ { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
+ { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
+ { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
+ { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
+ { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
+ { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+ { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+ { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+ { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
+ { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
+ { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
+ { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
+ { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
+ { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
+ { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
+ { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
+ { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
+ { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
+ { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
+ { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+ { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+ { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+ { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+ { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
+ { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
+ { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
+ { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}};
+
+
+static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ u8 tuner_buf[14];
+ unsigned char reg2[2];
+
+ struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = tuner_buf};
+ int i, tuner_freq, if_freq;
+ u32 N;
+
+ switch (params->u.ofdm.bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ if_freq = 4000000;
+ break;
+ case BANDWIDTH_7_MHZ:
+ if_freq = 4500000;
+ break;
+ default: /* 8 MHz or Auto */
+ if_freq = 5000000;
+ break;
+ }
+ tuner_freq = params->frequency + if_freq;
+
+ i = 0;
+ while (tda827xa_dvbt[i].lomax < tuner_freq) {
+ if(tda827xa_dvbt[i + 1].lomax == 0)
+ break;
+ i++;
+ }
+
+ N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
+ tuner_buf[0] = 0; // subaddress
+ tuner_buf[1] = N >> 8;
+ tuner_buf[2] = N & 0xff;
+ tuner_buf[3] = 0;
+ tuner_buf[4] = 0x16;
+ tuner_buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
+ tda827xa_dvbt[i].sbs;
+ tuner_buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
+ tuner_buf[7] = 0x0c;
+ tuner_buf[8] = 0x06;
+ tuner_buf[9] = 0x24;
+ tuner_buf[10] = 0xff;
+ tuner_buf[11] = 0x60;
+ tuner_buf[12] = 0x00;
+ tuner_buf[13] = 0x39; // lpsel
+ msg.len = 14;
+ if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+
+ msg.buf= reg2;
+ msg.len = 2;
+ reg2[0] = 0x60;
+ reg2[1] = 0x3c;
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+ reg2[0] = 0xa0;
+ reg2[1] = 0x40;
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+ msleep(2);
+ /* correct CP value */
+ reg2[0] = 0x30;
+ reg2[1] = 0x10 + tda827xa_dvbt[i].scr;
+ msg.len = 2;
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+ msleep(550);
+ reg2[0] = 0x50;
+ reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+ return 0;
+
+}
+
+static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 tda827xa_sleep[] = { 0x30, 0x90};
+ struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep,
+ .len = sizeof(tda827xa_sleep) };
+ i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
+
+}
+
+/* ------------------------------------------------------------------ */
+
+static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ int ret;
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 tda8290_close[] = { 0x21, 0xc0};
+ static u8 tda8290_open[] = { 0x21, 0x80};
+ struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
+ /* close tda8290 i2c bridge */
+ tda8290_msg.buf = tda8290_close;
+ ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
+ if (ret != 1)
+ return -EIO;
+ msleep(20);
+ ret = philips_tda827xa_pll_set(0x61, fe, params);
+ if (ret != 0)
+ return ret;
+ /* open tda8290 i2c bridge */
+ tda8290_msg.buf = tda8290_open;
+ i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
+ return ret;
+};
+
+static int philips_tiger_dvb_mode(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 data[] = { 0x3c, 0x33, 0x6a};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+ if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static void philips_tiger_analog_mode(struct dvb_frontend *fe)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ static u8 data[] = { 0x3c, 0x33, 0x68};
+ struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+
+ i2c_transfer(&dev->i2c_adap, &msg, 1);
+ philips_tda827xa_pll_sleep( 0x61, fe);
+}
+
+static struct tda1004x_config philips_tiger_config = {
+ .demod_address = 0x08,
+ .invert = 1,
+ .invert_oclk = 0,
+ .xtal_freq = TDA10046_XTAL_16M,
+ .agc_config = TDA10046_AGC_TDA827X,
+ .if_freq = TDA10046_FREQ_045,
+ .pll_init = philips_tiger_dvb_mode,
+ .pll_set = philips_tiger_pll_set,
+ .pll_sleep = philips_tiger_analog_mode,
+ .request_firmware = NULL,
+};
+
+#endif
+
+/* ------------------------------------------------------------------ */
+
+#ifdef HAVE_NXT200X
+static struct nxt200x_config avertvhda180 = {
+ .demod_address = 0x0a,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_tdhu2,
+};
#endif
/* ------------------------------------------------------------------ */
@@ -558,7 +853,7 @@ static int dvb_init(struct saa7134_dev *dev)
&dev->i2c_adap);
break;
case SAA7134_BOARD_PHILIPS_TOUGH:
- dev->dvb.frontend = tda10046_attach(&philips_tu1216_config,
+ dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config,
&dev->i2c_adap);
break;
case SAA7134_BOARD_FLYDVBTDUO:
@@ -569,6 +864,31 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap);
break;
+ case SAA7134_BOARD_PHILIPS_EUROPA:
+ dev->dvb.frontend = tda10046_attach(&philips_europa_config,
+ &dev->i2c_adap);
+ break;
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ dev->dvb.frontend = tda10046_attach(&philips_europa_config,
+ &dev->i2c_adap);
+ break;
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config,
+ &dev->i2c_adap);
+ break;
+ case SAA7134_BOARD_PHILIPS_TIGER:
+ dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
+ &dev->i2c_adap);
+ break;
+ case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+ dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
+ &dev->i2c_adap);
+ break;
+#endif
+#ifdef HAVE_NXT200X
+ case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
+ dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap);
+ break;
#endif
default:
printk("%s: Huh? unknown DVB card?\n",dev->name);
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 77b627eb648..e9ec69efb4c 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -55,7 +55,7 @@ static void ts_reset_encoder(struct saa7134_dev* dev)
saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
msleep(10);
- saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+ saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
msleep(100);
dev->empress_started = 0;
}
@@ -65,7 +65,7 @@ static int ts_init_encoder(struct saa7134_dev* dev)
ts_reset_encoder(dev);
saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL);
dev->empress_started = 1;
- return 0;
+ return 0;
}
/* ------------------------------------------------------------------ */
@@ -169,7 +169,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "saa7134");
+ 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));
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 711aa8e85fa..7575043f087 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -239,7 +239,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
unsigned char data;
int addr,rc,i,byte;
- status = i2c_get_status(dev);
+ status = i2c_get_status(dev);
if (!i2c_is_idle(status))
if (!i2c_reset(dev))
return -EIO;
@@ -296,7 +296,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
rc = -EIO;
if (!i2c_is_busy_wait(dev))
goto err;
- status = i2c_get_status(dev);
+ status = i2c_get_status(dev);
if (i2c_is_error(status))
goto err;
/* ensure that the bus is idle for at least one bit slot */
@@ -335,6 +335,20 @@ static int attach_inform(struct i2c_client *client)
d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
client->driver->name, client->addr, client->name);
+ /* Am I an i2c remote control? */
+
+ switch (client->addr) {
+ case 0x7a:
+ case 0x47:
+ {
+ struct IR_i2c *ir = i2c_get_clientdata(client);
+ d1printk("%s i2c IR detected (%s).\n",
+ client->driver->name,ir->phys);
+ saa7134_set_i2c_ir(dev,ir);
+ break;
+ }
+ }
+
if (!client->driver->command)
return 0;
@@ -348,12 +362,12 @@ static int attach_inform(struct i2c_client *client)
client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup);
}
- }
+ }
if (tuner != UNSET) {
- tun_setup.type = tuner;
- tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
+ tun_setup.type = tuner;
+ tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) {
@@ -361,11 +375,11 @@ static int attach_inform(struct i2c_client *client)
client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup);
}
- }
+ }
client->driver->command(client, TDA9887_SET_CONFIG, &conf);
- return 0;
+ return 0;
}
static struct i2c_algorithm saa7134_algo = {
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 1f456c4d76f..ab75ca5ac35 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -39,6 +39,8 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
#define dprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
+#define i2cdprintk(fmt, arg...) if (ir_debug) \
+ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
/* ---------------------------------------------------------------------- */
@@ -114,24 +116,24 @@ static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
/* Alfons Geser <a.geser@cox.net>
* updates from Job D. R. Borges <jobdrb@ig.com.br> */
static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
- [ 18 ] = KEY_POWER,
- [ 1 ] = KEY_TV, // DVR
- [ 21 ] = KEY_DVD, // DVD
- [ 23 ] = KEY_AUDIO, // music
- // DVR mode / DVD mode / music mode
-
- [ 27 ] = KEY_MUTE, // mute
- [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek
- [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek
- [ 22 ] = KEY_ZOOM, // full screen
- [ 28 ] = KEY_VIDEO, // video source / eject / delall
- [ 29 ] = KEY_RESTART, // playback / angle / del
- [ 47 ] = KEY_SEARCH, // scan / menu / playlist
- [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo
-
- [ 49 ] = KEY_HELP, // help
- [ 50 ] = KEY_MODE, // num/memo
- [ 51 ] = KEY_ESC, // cancel
+ [ 18 ] = KEY_POWER,
+ [ 1 ] = KEY_TV, // DVR
+ [ 21 ] = KEY_DVD, // DVD
+ [ 23 ] = KEY_AUDIO, // music
+ // DVR mode / DVD mode / music mode
+
+ [ 27 ] = KEY_MUTE, // mute
+ [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek
+ [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek
+ [ 22 ] = KEY_ZOOM, // full screen
+ [ 28 ] = KEY_VIDEO, // video source / eject / delall
+ [ 29 ] = KEY_RESTART, // playback / angle / del
+ [ 47 ] = KEY_SEARCH, // scan / menu / playlist
+ [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo
+
+ [ 49 ] = KEY_HELP, // help
+ [ 50 ] = KEY_MODE, // num/memo
+ [ 51 ] = KEY_ESC, // cancel
[ 12 ] = KEY_UP, // up
[ 16 ] = KEY_DOWN, // down
@@ -148,24 +150,24 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = {
[ 45 ] = KEY_PLAY, // play
[ 46 ] = KEY_SHUFFLE, // snapshot / shuffle
- [ 0 ] = KEY_KP0,
- [ 5 ] = KEY_KP1,
- [ 6 ] = KEY_KP2,
- [ 7 ] = KEY_KP3,
- [ 9 ] = KEY_KP4,
- [ 10 ] = KEY_KP5,
- [ 11 ] = KEY_KP6,
- [ 13 ] = KEY_KP7,
- [ 14 ] = KEY_KP8,
- [ 15 ] = KEY_KP9,
-
- [ 42 ] = KEY_VOLUMEUP,
- [ 17 ] = KEY_VOLUMEDOWN,
- [ 24 ] = KEY_CHANNELUP, // CH.tracking up
- [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down
-
- [ 19 ] = KEY_KPENTER, // enter
- [ 33 ] = KEY_KPDOT, // . (decimal dot)
+ [ 0 ] = KEY_KP0,
+ [ 5 ] = KEY_KP1,
+ [ 6 ] = KEY_KP2,
+ [ 7 ] = KEY_KP3,
+ [ 9 ] = KEY_KP4,
+ [ 10 ] = KEY_KP5,
+ [ 11 ] = KEY_KP6,
+ [ 13 ] = KEY_KP7,
+ [ 14 ] = KEY_KP8,
+ [ 15 ] = KEY_KP9,
+
+ [ 42 ] = KEY_VOLUMEUP,
+ [ 17 ] = KEY_VOLUMEDOWN,
+ [ 24 ] = KEY_CHANNELUP, // CH.tracking up
+ [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down
+
+ [ 19 ] = KEY_KPENTER, // enter
+ [ 33 ] = KEY_KPDOT, // . (decimal dot)
};
static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = {
@@ -401,7 +403,125 @@ static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
// 0x1d unused ?
};
-/* ---------------------------------------------------------------------- */
+
+
+/* Mike Baikov <mike@baikov.com> */
+static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = {
+
+ [ 33 ] = KEY_POWER,
+ [ 105] = KEY_TV,
+ [ 51 ] = KEY_KP0,
+ [ 81 ] = KEY_KP1,
+ [ 49 ] = KEY_KP2,
+ [ 113] = KEY_KP3,
+ [ 59 ] = KEY_KP4,
+ [ 88 ] = KEY_KP5,
+ [ 65 ] = KEY_KP6,
+ [ 72 ] = KEY_KP7,
+ [ 48 ] = KEY_KP8,
+ [ 83 ] = KEY_KP9,
+ [ 115] = KEY_AGAIN, /* LOOP */
+ [ 10 ] = KEY_AUDIO,
+ [ 97 ] = KEY_PRINT, /* PREVIEW */
+ [ 122] = KEY_VIDEO,
+ [ 32 ] = KEY_CHANNELUP,
+ [ 64 ] = KEY_CHANNELDOWN,
+ [ 24 ] = KEY_VOLUMEDOWN,
+ [ 80 ] = KEY_VOLUMEUP,
+ [ 16 ] = KEY_MUTE,
+ [ 74 ] = KEY_SEARCH,
+ [ 123] = KEY_SHUFFLE, /* SNAPSHOT */
+ [ 34 ] = KEY_RECORD,
+ [ 98 ] = KEY_STOP,
+ [ 120] = KEY_PLAY,
+ [ 57 ] = KEY_REWIND,
+ [ 89 ] = KEY_PAUSE,
+ [ 25 ] = KEY_FORWARD,
+ [ 9 ] = KEY_ZOOM,
+
+ [ 82 ] = KEY_F21, /* LIVE TIMESHIFT */
+ [ 26 ] = KEY_F22, /* MIN TIMESHIFT */
+ [ 58 ] = KEY_F23, /* TIMESHIFT */
+ [ 112] = KEY_F24, /* NORMAL TIMESHIFT */
+};
+
+static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
+ [ 0x3 ] = KEY_POWER,
+ [ 0x6f ] = KEY_MUTE,
+ [ 0x10 ] = KEY_BACKSPACE, /* Recall */
+
+ [ 0x11 ] = KEY_KP0,
+ [ 0x4 ] = KEY_KP1,
+ [ 0x5 ] = KEY_KP2,
+ [ 0x6 ] = KEY_KP3,
+ [ 0x8 ] = KEY_KP4,
+ [ 0x9 ] = KEY_KP5,
+ [ 0xa ] = KEY_KP6,
+ [ 0xc ] = KEY_KP7,
+ [ 0xd ] = KEY_KP8,
+ [ 0xe ] = KEY_KP9,
+ [ 0x12 ] = KEY_KPDOT, /* 100+ */
+
+ [ 0x7 ] = KEY_VOLUMEUP,
+ [ 0xb ] = KEY_VOLUMEDOWN,
+ [ 0x1a ] = KEY_KPPLUS,
+ [ 0x18 ] = KEY_KPMINUS,
+ [ 0x15 ] = KEY_UP,
+ [ 0x1d ] = KEY_DOWN,
+ [ 0xf ] = KEY_CHANNELUP,
+ [ 0x13 ] = KEY_CHANNELDOWN,
+ [ 0x48 ] = KEY_ZOOM,
+
+ [ 0x1b ] = KEY_VIDEO, /* Video source */
+ [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */
+ [ 0x19 ] = KEY_SEARCH, /* Auto Scan */
+
+ [ 0x4b ] = KEY_RECORD,
+ [ 0x46 ] = KEY_PLAY,
+ [ 0x45 ] = KEY_PAUSE, /* Pause */
+ [ 0x44 ] = KEY_STOP,
+ [ 0x40 ] = KEY_FORWARD, /* Forward ? */
+ [ 0x42 ] = KEY_REWIND, /* Backward ? */
+
+};
+
+/* Mapping for the 28 key remote control as seen at
+ http://www.sednacomputer.com/photo/cardbus-tv.jpg
+ Pavel Mihaylov <bin@bash.info> */
+static IR_KEYTAB_TYPE pctv_sedna_codes[IR_KEYTAB_SIZE] = {
+ [ 0 ] = KEY_KP0,
+ [ 1 ] = KEY_KP1,
+ [ 2 ] = KEY_KP2,
+ [ 3 ] = KEY_KP3,
+ [ 4 ] = KEY_KP4,
+ [ 5 ] = KEY_KP5,
+ [ 6 ] = KEY_KP6,
+ [ 7 ] = KEY_KP7,
+ [ 8 ] = KEY_KP8,
+ [ 9 ] = KEY_KP9,
+
+ [ 0x0a ] = KEY_AGAIN, /* Recall */
+ [ 0x0b ] = KEY_CHANNELUP,
+ [ 0x0c ] = KEY_VOLUMEUP,
+ [ 0x0d ] = KEY_MODE, /* Stereo */
+ [ 0x0e ] = KEY_STOP,
+ [ 0x0f ] = KEY_PREVIOUSSONG,
+ [ 0x10 ] = KEY_ZOOM,
+ [ 0x11 ] = KEY_TUNER, /* Source */
+ [ 0x12 ] = KEY_POWER,
+ [ 0x13 ] = KEY_MUTE,
+ [ 0x15 ] = KEY_CHANNELDOWN,
+ [ 0x18 ] = KEY_VOLUMEDOWN,
+ [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */
+ [ 0x1a ] = KEY_NEXTSONG,
+ [ 0x1b ] = KEY_TEXT, /* Time Shift */
+ [ 0x1c ] = KEY_RADIO, /* FM Radio */
+ [ 0x1d ] = KEY_RECORD,
+ [ 0x1e ] = KEY_PAUSE,
+};
+
+
+/* -------------------- GPIO generic keycode builder -------------------- */
static int build_key(struct saa7134_dev *dev)
{
@@ -413,32 +533,55 @@ static int build_key(struct saa7134_dev *dev)
saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
- if (ir->polling) {
- if (ir->last_gpio == gpio)
- return 0;
- ir->last_gpio = gpio;
- }
+ if (ir->polling) {
+ if (ir->last_gpio == gpio)
+ return 0;
+ ir->last_gpio = gpio;
+ }
- data = ir_extract_bits(gpio, ir->mask_keycode);
+ data = ir_extract_bits(gpio, ir->mask_keycode);
dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
gpio, ir->mask_keycode, data);
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
- ir_input_keydown(&ir->dev,&ir->ir,data,data);
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
} else {
- ir_input_nokey(&ir->dev,&ir->ir);
+ ir_input_nokey(ir->dev, &ir->ir);
}
return 0;
}
-/* ---------------------------------------------------------------------- */
+/* --------------------- Chip specific I2C key builders ----------------- */
+
+static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char b;
+
+ /* poll IR chip */
+ if (1 != i2c_master_recv(&ir->c,&b,1)) {
+ i2cdprintk("read error\n");
+ return -EIO;
+ }
+
+ /* no button press */
+ if (b==0)
+ return 0;
+
+ /* repeating */
+ if (b & 0x80)
+ return 1;
+
+ *ir_key = b;
+ *ir_raw = b;
+ return 1;
+}
void saa7134_input_irq(struct saa7134_dev *dev)
{
- struct saa7134_ir *ir = dev->remote;
+ struct saa7134_ir *ir = dev->remote;
- if (!ir->polling)
+ if (!ir->polling)
build_key(dev);
}
@@ -456,6 +599,7 @@ static void saa7134_input_timer(unsigned long data)
int saa7134_input_init1(struct saa7134_dev *dev)
{
struct saa7134_ir *ir;
+ struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = NULL;
u32 mask_keycode = 0;
u32 mask_keydown = 0;
@@ -463,7 +607,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
int polling = 0;
int ir_type = IR_TYPE_OTHER;
- if (!dev->has_remote)
+ if (dev->has_remote != SAA7134_REMOTE_GPIO)
return -ENODEV;
if (disable_ir)
return -ENODEV;
@@ -472,7 +616,8 @@ int saa7134_input_init1(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_FLYVIDEO2000:
case SAA7134_BOARD_FLYVIDEO3000:
- case SAA7134_BOARD_FLYTVPLATINUM_FM:
+ case SAA7134_BOARD_FLYTVPLATINUM_FM:
+ case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
ir_codes = flyvideo_codes;
mask_keycode = 0xEC00000;
mask_keydown = 0x0040000;
@@ -513,14 +658,33 @@ int saa7134_input_init1(struct saa7134_dev *dev)
saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
break;
+ case SAA7134_BOARD_KWORLD_TERMINATOR:
+ ir_codes = avacssmart_codes;
+ mask_keycode = 0x00001f;
+ mask_keyup = 0x000060;
+ polling = 50; // ms
+ break;
case SAA7134_BOARD_MANLI_MTV001:
case SAA7134_BOARD_MANLI_MTV002:
+ case SAA7134_BOARD_BEHOLD_409FM:
ir_codes = manli_codes;
mask_keycode = 0x001f00;
mask_keyup = 0x004000;
- mask_keydown = 0x002000;
polling = 50; // ms
break;
+ case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
+ ir_codes = pctv_sedna_codes;
+ mask_keycode = 0x001f00;
+ mask_keyup = 0x004000;
+ polling = 50; // ms
+ break;
+ case SAA7134_BOARD_GOTVIEW_7135:
+ ir_codes = gotview7135_codes;
+ mask_keycode = 0x0003EC;
+ mask_keyup = 0x008000;
+ mask_keydown = 0x000010;
+ polling = 50; // ms
+ break;
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
ir_codes = videomate_tv_pvr_codes;
@@ -528,6 +692,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
mask_keyup = 0x400000;
polling = 50; // ms
break;
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ ir_codes = videomate_tv_pvr_codes;
+ mask_keycode = 0x003F00;
+ mask_keyup = 0x040000;
+ break;
}
if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n",
@@ -535,16 +705,21 @@ int saa7134_input_init1(struct saa7134_dev *dev)
return -ENODEV;
}
- ir = kmalloc(sizeof(*ir),GFP_KERNEL);
- if (NULL == ir)
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ir || !input_dev) {
+ kfree(ir);
+ input_free_device(input_dev);
return -ENOMEM;
- memset(ir,0,sizeof(*ir));
+ }
+
+ ir->dev = input_dev;
/* init hardware-specific stuff */
ir->mask_keycode = mask_keycode;
ir->mask_keydown = mask_keydown;
ir->mask_keyup = mask_keyup;
- ir->polling = polling;
+ ir->polling = polling;
/* init input device */
snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
@@ -552,19 +727,19 @@ int saa7134_input_init1(struct saa7134_dev *dev)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(dev->pci));
- ir_input_init(&ir->dev, &ir->ir, ir_type, ir_codes);
- ir->dev.name = ir->name;
- ir->dev.phys = ir->phys;
- ir->dev.id.bustype = BUS_PCI;
- ir->dev.id.version = 1;
+ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+ input_dev->name = ir->name;
+ input_dev->phys = ir->phys;
+ input_dev->id.bustype = BUS_PCI;
+ input_dev->id.version = 1;
if (dev->pci->subsystem_vendor) {
- ir->dev.id.vendor = dev->pci->subsystem_vendor;
- ir->dev.id.product = dev->pci->subsystem_device;
+ input_dev->id.vendor = dev->pci->subsystem_vendor;
+ input_dev->id.product = dev->pci->subsystem_device;
} else {
- ir->dev.id.vendor = dev->pci->vendor;
- ir->dev.id.product = dev->pci->device;
+ input_dev->id.vendor = dev->pci->vendor;
+ input_dev->id.product = dev->pci->device;
}
- ir->dev.dev = &dev->pci->dev;
+ input_dev->cdev.dev = &dev->pci->dev;
/* all done */
dev->remote = ir;
@@ -576,8 +751,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
add_timer(&ir->timer);
}
- input_register_device(&dev->remote->dev);
- printk("%s: registered input device for IR\n",dev->name);
+ input_register_device(ir->dev);
return 0;
}
@@ -586,13 +760,38 @@ void saa7134_input_fini(struct saa7134_dev *dev)
if (NULL == dev->remote)
return;
- input_unregister_device(&dev->remote->dev);
if (dev->remote->polling)
del_timer_sync(&dev->remote->timer);
+ input_unregister_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
}
+void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
+{
+ if (disable_ir) {
+ dprintk("Found supported i2c remote, but IR has been disabled\n");
+ ir->get_key=NULL;
+ return;
+ }
+
+ switch (dev->board) {
+ case SAA7134_BOARD_PINNACLE_PCTV_110i:
+ snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
+ ir->get_key = get_key_pinnacle;
+ ir->ir_codes = ir_codes_pinnacle;
+ break;
+ case SAA7134_BOARD_UPMOST_PURPLE_TV:
+ snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
+ ir->get_key = get_key_purpletv;
+ ir->ir_codes = ir_codes_purpletv;
+ break;
+ default:
+ dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
+ break;
+ }
+
+}
/* ----------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index c20630c82f1..5a579194e45 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -4,6 +4,8 @@
* oss dsp interface
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * 2005 conversion to standalone module:
+ * Ricardo Cerqueira <v4l@cerqueira.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +27,9 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
+#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/sound.h>
#include <linux/soundcard.h>
#include "saa7134-reg.h"
@@ -33,17 +37,26 @@
/* ------------------------------------------------------------------ */
-static unsigned int oss_debug = 0;
-module_param(oss_debug, int, 0644);
-MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]");
+static unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [oss]");
-static unsigned int oss_rate = 0;
-module_param(oss_rate, int, 0444);
-MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)");
+static unsigned int rate = 0;
+module_param(rate, int, 0444);
+MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)");
-#define dprintk(fmt, arg...) if (oss_debug) \
+static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s).");
+module_param_array(dsp_nr, int, NULL, 0444);
+
+static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s).");
+module_param_array(mixer_nr, int, NULL, 0444);
+
+#define dprintk(fmt, arg...) if (debug) \
printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg)
+
/* ------------------------------------------------------------------ */
static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
@@ -58,12 +71,12 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
if ((blksize * blocks) > 1024*1024)
blocks = 1024*1024 / blksize;
- dev->oss.blocks = blocks;
- dev->oss.blksize = blksize;
- dev->oss.bufsize = blksize * blocks;
+ dev->dmasound.blocks = blocks;
+ dev->dmasound.blksize = blksize;
+ dev->dmasound.bufsize = blksize * blocks;
dprintk("buffer config: %d blocks / %d bytes, %d kB total\n",
- blocks,blksize,blksize * blocks / 1024);
+ blocks,blksize,blksize * blocks / 1024);
return 0;
}
@@ -71,11 +84,11 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
{
int err;
- if (!dev->oss.bufsize)
+ if (!dev->dmasound.bufsize)
BUG();
- videobuf_dma_init(&dev->oss.dma);
- err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
- (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
+ videobuf_dma_init(&dev->dmasound.dma);
+ err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
+ (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
if (0 != err)
return err;
return 0;
@@ -83,26 +96,26 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
static int dsp_buffer_free(struct saa7134_dev *dev)
{
- if (!dev->oss.blksize)
+ if (!dev->dmasound.blksize)
BUG();
- videobuf_dma_free(&dev->oss.dma);
- dev->oss.blocks = 0;
- dev->oss.blksize = 0;
- dev->oss.bufsize = 0;
+ videobuf_dma_free(&dev->dmasound.dma);
+ dev->dmasound.blocks = 0;
+ dev->dmasound.blksize = 0;
+ dev->dmasound.bufsize = 0;
return 0;
}
static void dsp_dma_start(struct saa7134_dev *dev)
{
- dev->oss.dma_blk = 0;
- dev->oss.dma_running = 1;
+ dev->dmasound.dma_blk = 0;
+ dev->dmasound.dma_running = 1;
saa7134_set_dmabits(dev);
}
static void dsp_dma_stop(struct saa7134_dev *dev)
{
- dev->oss.dma_blk = -1;
- dev->oss.dma_running = 0;
+ dev->dmasound.dma_blk = -1;
+ dev->dmasound.dma_running = 0;
saa7134_set_dmabits(dev);
}
@@ -113,18 +126,18 @@ static int dsp_rec_start(struct saa7134_dev *dev)
unsigned long flags;
/* prepare buffer */
- if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma)))
+ if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma)))
return err;
- if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt)))
+ if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt)))
goto fail1;
- if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt,
- dev->oss.dma.sglist,
- dev->oss.dma.sglen,
+ if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
+ dev->dmasound.dma.sglist,
+ dev->dmasound.dma.sglen,
0)))
goto fail2;
/* sample format */
- switch (dev->oss.afmt) {
+ switch (dev->dmasound.afmt) {
case AFMT_U8:
case AFMT_S8: fmt = 0x00; break;
case AFMT_U16_LE:
@@ -136,14 +149,14 @@ static int dsp_rec_start(struct saa7134_dev *dev)
goto fail2;
}
- switch (dev->oss.afmt) {
+ switch (dev->dmasound.afmt) {
case AFMT_S8:
case AFMT_S16_LE:
case AFMT_S16_BE: sign = 1; break;
default: sign = 0; break;
}
- switch (dev->oss.afmt) {
+ switch (dev->dmasound.afmt) {
case AFMT_U16_BE:
case AFMT_S16_BE: bswap = 1; break;
default: bswap = 0; break;
@@ -151,58 +164,58 @@ static int dsp_rec_start(struct saa7134_dev *dev)
switch (dev->pci->device) {
case PCI_DEVICE_ID_PHILIPS_SAA7134:
- if (1 == dev->oss.channels)
+ if (1 == dev->dmasound.channels)
fmt |= (1 << 3);
- if (2 == dev->oss.channels)
+ if (2 == dev->dmasound.channels)
fmt |= (3 << 3);
if (sign)
fmt |= 0x04;
- fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
+ fmt |= (TV == dev->dmasound.input) ? 0xc0 : 0x80;
- saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff));
- saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8);
- saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16);
+ saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff));
+ saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >> 8);
+ saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16);
saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
break;
case PCI_DEVICE_ID_PHILIPS_SAA7133:
case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (1 == dev->oss.channels)
+ if (1 == dev->dmasound.channels)
fmt |= (1 << 4);
- if (2 == dev->oss.channels)
+ if (2 == dev->dmasound.channels)
fmt |= (2 << 4);
if (!sign)
fmt |= 0x04;
- saa_writel(0x588 >> 2, dev->oss.blksize -4);
- saa_writel(0x58c >> 2, 0x543210 | (fmt << 24));
+ saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -4);
+ saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
break;
}
dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n",
- dev->oss.afmt, dev->oss.channels, fmt,
+ dev->dmasound.afmt, dev->dmasound.channels, fmt,
bswap ? 'b' : '-');
/* dma: setup channel 6 (= AUDIO) */
control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
- (dev->oss.pt.dma >> 12);
+ (dev->dmasound.pt.dma >> 12);
if (bswap)
control |= SAA7134_RS_CONTROL_BSWAP;
saa_writel(SAA7134_RS_BA1(6),0);
- saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize);
+ saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
saa_writel(SAA7134_RS_PITCH(6),0);
saa_writel(SAA7134_RS_CONTROL(6),control);
/* start dma */
- dev->oss.recording_on = 1;
+ dev->dmasound.recording_on = 1;
spin_lock_irqsave(&dev->slock,flags);
dsp_dma_start(dev);
spin_unlock_irqrestore(&dev->slock,flags);
return 0;
fail2:
- saa7134_pgtable_free(dev->pci,&dev->oss.pt);
+ saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
fail1:
- videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma);
+ videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
return err;
}
@@ -210,17 +223,17 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
{
unsigned long flags;
- dprintk("rec_stop dma_blk=%d\n",dev->oss.dma_blk);
+ dprintk("rec_stop dma_blk=%d\n",dev->dmasound.dma_blk);
/* stop dma */
- dev->oss.recording_on = 0;
+ dev->dmasound.recording_on = 0;
spin_lock_irqsave(&dev->slock,flags);
dsp_dma_stop(dev);
spin_unlock_irqrestore(&dev->slock,flags);
/* unlock buffer */
- saa7134_pgtable_free(dev->pci,&dev->oss.pt);
- videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma);
+ saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
return 0;
}
@@ -235,35 +248,35 @@ static int dsp_open(struct inode *inode, struct file *file)
list_for_each(list,&saa7134_devlist) {
h = list_entry(list, struct saa7134_dev, devlist);
- if (h->oss.minor_dsp == minor)
+ if (h->dmasound.minor_dsp == minor)
dev = h;
}
if (NULL == dev)
return -ENODEV;
- down(&dev->oss.lock);
+ down(&dev->dmasound.lock);
err = -EBUSY;
- if (dev->oss.users_dsp)
+ if (dev->dmasound.users_dsp)
goto fail1;
- dev->oss.users_dsp++;
+ dev->dmasound.users_dsp++;
file->private_data = dev;
- dev->oss.afmt = AFMT_U8;
- dev->oss.channels = 1;
- dev->oss.read_count = 0;
- dev->oss.read_offset = 0;
+ dev->dmasound.afmt = AFMT_U8;
+ dev->dmasound.channels = 1;
+ dev->dmasound.read_count = 0;
+ dev->dmasound.read_offset = 0;
dsp_buffer_conf(dev,PAGE_SIZE,64);
err = dsp_buffer_init(dev);
if (0 != err)
goto fail2;
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
return 0;
fail2:
- dev->oss.users_dsp--;
+ dev->dmasound.users_dsp--;
fail1:
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
return err;
}
@@ -271,13 +284,13 @@ static int dsp_release(struct inode *inode, struct file *file)
{
struct saa7134_dev *dev = file->private_data;
- down(&dev->oss.lock);
- if (dev->oss.recording_on)
+ down(&dev->dmasound.lock);
+ if (dev->dmasound.recording_on)
dsp_rec_stop(dev);
dsp_buffer_free(dev);
- dev->oss.users_dsp--;
+ dev->dmasound.users_dsp--;
file->private_data = NULL;
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
return 0;
}
@@ -290,12 +303,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer,
unsigned long flags;
int err,ret = 0;
- add_wait_queue(&dev->oss.wq, &wait);
- down(&dev->oss.lock);
+ add_wait_queue(&dev->dmasound.wq, &wait);
+ down(&dev->dmasound.lock);
while (count > 0) {
/* wait for data if needed */
- if (0 == dev->oss.read_count) {
- if (!dev->oss.recording_on) {
+ if (0 == dev->dmasound.read_count) {
+ if (!dev->dmasound.recording_on) {
err = dsp_rec_start(dev);
if (err < 0) {
if (0 == ret)
@@ -303,8 +316,8 @@ static ssize_t dsp_read(struct file *file, char __user *buffer,
break;
}
}
- if (dev->oss.recording_on &&
- !dev->oss.dma_running) {
+ if (dev->dmasound.recording_on &&
+ !dev->dmasound.dma_running) {
/* recover from overruns */
spin_lock_irqsave(&dev->slock,flags);
dsp_dma_start(dev);
@@ -315,12 +328,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer,
ret = -EAGAIN;
break;
}
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
set_current_state(TASK_INTERRUPTIBLE);
- if (0 == dev->oss.read_count)
+ if (0 == dev->dmasound.read_count)
schedule();
set_current_state(TASK_RUNNING);
- down(&dev->oss.lock);
+ down(&dev->dmasound.lock);
if (signal_pending(current)) {
if (0 == ret)
ret = -EINTR;
@@ -330,12 +343,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer,
/* copy data to userspace */
bytes = count;
- if (bytes > dev->oss.read_count)
- bytes = dev->oss.read_count;
- if (bytes > dev->oss.bufsize - dev->oss.read_offset)
- bytes = dev->oss.bufsize - dev->oss.read_offset;
+ if (bytes > dev->dmasound.read_count)
+ bytes = dev->dmasound.read_count;
+ if (bytes > dev->dmasound.bufsize - dev->dmasound.read_offset)
+ bytes = dev->dmasound.bufsize - dev->dmasound.read_offset;
if (copy_to_user(buffer + ret,
- dev->oss.dma.vmalloc + dev->oss.read_offset,
+ dev->dmasound.dma.vmalloc + dev->dmasound.read_offset,
bytes)) {
if (0 == ret)
ret = -EFAULT;
@@ -344,13 +357,13 @@ static ssize_t dsp_read(struct file *file, char __user *buffer,
ret += bytes;
count -= bytes;
- dev->oss.read_count -= bytes;
- dev->oss.read_offset += bytes;
- if (dev->oss.read_offset == dev->oss.bufsize)
- dev->oss.read_offset = 0;
+ dev->dmasound.read_count -= bytes;
+ dev->dmasound.read_offset += bytes;
+ if (dev->dmasound.read_offset == dev->dmasound.bufsize)
+ dev->dmasound.read_offset = 0;
}
- up(&dev->oss.lock);
- remove_wait_queue(&dev->oss.wq, &wait);
+ up(&dev->dmasound.lock);
+ remove_wait_queue(&dev->dmasound.wq, &wait);
return ret;
}
@@ -368,55 +381,55 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
int __user *p = argp;
int val = 0;
- if (oss_debug > 1)
+ if (debug > 1)
saa7134_print_ioctl(dev->name,cmd);
- switch (cmd) {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, p);
- case SNDCTL_DSP_GETCAPS:
+ switch (cmd) {
+ case OSS_GETVERSION:
+ return put_user(SOUND_VERSION, p);
+ case SNDCTL_DSP_GETCAPS:
return 0;
- case SNDCTL_DSP_SPEED:
+ case SNDCTL_DSP_SPEED:
if (get_user(val, p))
return -EFAULT;
/* fall through */
- case SOUND_PCM_READ_RATE:
- return put_user(dev->oss.rate, p);
+ case SOUND_PCM_READ_RATE:
+ return put_user(dev->dmasound.rate, p);
- case SNDCTL_DSP_STEREO:
+ case SNDCTL_DSP_STEREO:
if (get_user(val, p))
return -EFAULT;
- down(&dev->oss.lock);
- dev->oss.channels = val ? 2 : 1;
- if (dev->oss.recording_on) {
+ down(&dev->dmasound.lock);
+ dev->dmasound.channels = val ? 2 : 1;
+ if (dev->dmasound.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
- up(&dev->oss.lock);
- return put_user(dev->oss.channels-1, p);
+ up(&dev->dmasound.lock);
+ return put_user(dev->dmasound.channels-1, p);
- case SNDCTL_DSP_CHANNELS:
+ case SNDCTL_DSP_CHANNELS:
if (get_user(val, p))
return -EFAULT;
if (val != 1 && val != 2)
return -EINVAL;
- down(&dev->oss.lock);
- dev->oss.channels = val;
- if (dev->oss.recording_on) {
+ down(&dev->dmasound.lock);
+ dev->dmasound.channels = val;
+ if (dev->dmasound.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
/* fall through */
- case SOUND_PCM_READ_CHANNELS:
- return put_user(dev->oss.channels, p);
+ case SOUND_PCM_READ_CHANNELS:
+ return put_user(dev->dmasound.channels, p);
- case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+ case SNDCTL_DSP_GETFMTS: /* Returns a mask */
return put_user(AFMT_U8 | AFMT_S8 |
AFMT_U16_LE | AFMT_U16_BE |
AFMT_S16_LE | AFMT_S16_BE, p);
- case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */
+ case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */
if (get_user(val, p))
return -EFAULT;
switch (val) {
@@ -429,20 +442,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
case AFMT_U16_BE:
case AFMT_S16_LE:
case AFMT_S16_BE:
- down(&dev->oss.lock);
- dev->oss.afmt = val;
- if (dev->oss.recording_on) {
+ down(&dev->dmasound.lock);
+ dev->dmasound.afmt = val;
+ if (dev->dmasound.recording_on) {
dsp_rec_stop(dev);
dsp_rec_start(dev);
}
- up(&dev->oss.lock);
- return put_user(dev->oss.afmt, p);
+ up(&dev->dmasound.lock);
+ return put_user(dev->dmasound.afmt, p);
default:
return -EINVAL;
}
- case SOUND_PCM_READ_BITS:
- switch (dev->oss.afmt) {
+ case SOUND_PCM_READ_BITS:
+ switch (dev->dmasound.afmt) {
case AFMT_U8:
case AFMT_S8:
return put_user(8, p);
@@ -455,23 +468,23 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- return 0;
+ case SNDCTL_DSP_NONBLOCK:
+ file->f_flags |= O_NONBLOCK;
+ return 0;
- case SNDCTL_DSP_RESET:
- down(&dev->oss.lock);
- if (dev->oss.recording_on)
+ case SNDCTL_DSP_RESET:
+ down(&dev->dmasound.lock);
+ if (dev->dmasound.recording_on)
dsp_rec_stop(dev);
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
return 0;
- case SNDCTL_DSP_GETBLKSIZE:
- return put_user(dev->oss.blksize, p);
+ case SNDCTL_DSP_GETBLKSIZE:
+ return put_user(dev->dmasound.blksize, p);
- case SNDCTL_DSP_SETFRAGMENT:
+ case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, p))
return -EFAULT;
- if (dev->oss.recording_on)
+ if (dev->dmasound.recording_on)
return -EBUSY;
dsp_buffer_free(dev);
/* used to be arg >> 16 instead of val >> 16; fixed */
@@ -479,16 +492,16 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
dsp_buffer_init(dev);
return 0;
- case SNDCTL_DSP_SYNC:
+ case SNDCTL_DSP_SYNC:
/* NOP */
return 0;
case SNDCTL_DSP_GETISPACE:
{
audio_buf_info info;
- info.fragsize = dev->oss.blksize;
- info.fragstotal = dev->oss.blocks;
- info.bytes = dev->oss.read_count;
+ info.fragsize = dev->dmasound.blksize;
+ info.fragstotal = dev->dmasound.blocks;
+ info.bytes = dev->dmasound.read_count;
info.fragments = info.bytes / info.fragsize;
if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
@@ -504,13 +517,13 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait)
struct saa7134_dev *dev = file->private_data;
unsigned int mask = 0;
- poll_wait(file, &dev->oss.wq, wait);
+ poll_wait(file, &dev->dmasound.wq, wait);
- if (0 == dev->oss.read_count) {
- down(&dev->oss.lock);
- if (!dev->oss.recording_on)
+ if (0 == dev->dmasound.read_count) {
+ down(&dev->dmasound.lock);
+ if (!dev->dmasound.recording_on)
dsp_rec_start(dev);
- up(&dev->oss.lock);
+ up(&dev->dmasound.lock);
} else
mask |= (POLLIN | POLLRDNORM);
return mask;
@@ -534,7 +547,7 @@ mixer_recsrc_7134(struct saa7134_dev *dev)
{
int analog_io,rate;
- switch (dev->oss.input) {
+ switch (dev->dmasound.input) {
case TV:
saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00);
@@ -542,8 +555,8 @@ mixer_recsrc_7134(struct saa7134_dev *dev)
case LINE1:
case LINE2:
case LINE2_LEFT:
- analog_io = (LINE1 == dev->oss.input) ? 0x00 : 0x08;
- rate = (32000 == dev->oss.rate) ? 0x01 : 0x03;
+ analog_io = (LINE1 == dev->dmasound.input) ? 0x00 : 0x08;
+ rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03;
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io);
saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80);
saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate);
@@ -559,10 +572,10 @@ mixer_recsrc_7133(struct saa7134_dev *dev)
xbarin = 0x03; // adc
anabar = 0;
- switch (dev->oss.input) {
+ switch (dev->dmasound.input) {
case TV:
xbarin = 0; // Demodulator
- anabar = 2; // DACs
+ anabar = 2; // DACs
break;
case LINE1:
anabar = 0; // aux1, aux1
@@ -585,9 +598,9 @@ mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
{
static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" };
- dev->oss.count++;
- dev->oss.input = src;
- dprintk("mixer input = %s\n",iname[dev->oss.input]);
+ dev->dmasound.count++;
+ dev->dmasound.input = src;
+ dprintk("mixer input = %s\n",iname[dev->dmasound.input]);
switch (dev->pci->device) {
case PCI_DEVICE_ID_PHILIPS_SAA7134:
@@ -639,7 +652,7 @@ static int mixer_open(struct inode *inode, struct file *file)
list_for_each(list,&saa7134_devlist) {
h = list_entry(list, struct saa7134_dev, devlist);
- if (h->oss.minor_mixer == minor)
+ if (h->dmasound.minor_mixer == minor)
dev = h;
}
if (NULL == dev)
@@ -664,30 +677,30 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
void __user *argp = (void __user *) arg;
int __user *p = argp;
- if (oss_debug > 1)
+ if (debug > 1)
saa7134_print_ioctl(dev->name,cmd);
- switch (cmd) {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, p);
+ switch (cmd) {
+ case OSS_GETVERSION:
+ return put_user(SOUND_VERSION, p);
case SOUND_MIXER_INFO:
{
mixer_info info;
memset(&info,0,sizeof(info));
- strlcpy(info.id, "TV audio", sizeof(info.id));
- strlcpy(info.name, dev->name, sizeof(info.name));
- info.modify_counter = dev->oss.count;
- if (copy_to_user(argp, &info, sizeof(info)))
- return -EFAULT;
+ strlcpy(info.id, "TV audio", sizeof(info.id));
+ strlcpy(info.name, dev->name, sizeof(info.name));
+ info.modify_counter = dev->dmasound.count;
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
return 0;
}
case SOUND_OLD_MIXER_INFO:
{
_old_mixer_info info;
memset(&info,0,sizeof(info));
- strlcpy(info.id, "TV audio", sizeof(info.id));
- strlcpy(info.name, dev->name, sizeof(info.name));
- if (copy_to_user(argp, &info, sizeof(info)))
- return -EFAULT;
+ strlcpy(info.id, "TV audio", sizeof(info.id));
+ strlcpy(info.name, dev->name, sizeof(info.name));
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
return 0;
}
case MIXER_READ(SOUND_MIXER_CAPS):
@@ -697,26 +710,26 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
case MIXER_READ(SOUND_MIXER_RECMASK):
case MIXER_READ(SOUND_MIXER_DEVMASK):
val = SOUND_MASK_LINE1 | SOUND_MASK_LINE2;
- if (32000 == dev->oss.rate)
+ if (32000 == dev->dmasound.rate)
val |= SOUND_MASK_VIDEO;
return put_user(val, p);
case MIXER_WRITE(SOUND_MIXER_RECSRC):
if (get_user(val, p))
return -EFAULT;
- input = dev->oss.input;
- if (32000 == dev->oss.rate &&
- val & SOUND_MASK_VIDEO && dev->oss.input != TV)
+ input = dev->dmasound.input;
+ if (32000 == dev->dmasound.rate &&
+ val & SOUND_MASK_VIDEO && dev->dmasound.input != TV)
input = TV;
- if (val & SOUND_MASK_LINE1 && dev->oss.input != LINE1)
+ if (val & SOUND_MASK_LINE1 && dev->dmasound.input != LINE1)
input = LINE1;
- if (val & SOUND_MASK_LINE2 && dev->oss.input != LINE2)
+ if (val & SOUND_MASK_LINE2 && dev->dmasound.input != LINE2)
input = LINE2;
- if (input != dev->oss.input)
+ if (input != dev->dmasound.input)
mixer_recsrc(dev,input);
/* fall throuth */
case MIXER_READ(SOUND_MIXER_RECSRC):
- switch (dev->oss.input) {
+ switch (dev->dmasound.input) {
case TV: ret = SOUND_MASK_VIDEO; break;
case LINE1: ret = SOUND_MASK_LINE1; break;
case LINE2: ret = SOUND_MASK_LINE2; break;
@@ -726,7 +739,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
case MIXER_WRITE(SOUND_MIXER_VIDEO):
case MIXER_READ(SOUND_MIXER_VIDEO):
- if (32000 != dev->oss.rate)
+ if (32000 != dev->dmasound.rate)
return -EINVAL;
return put_user(100 | 100 << 8, p);
@@ -735,22 +748,22 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
val &= 0xff;
val = (val <= 50) ? 50 : 100;
- dev->oss.line1 = val;
- mixer_level(dev,LINE1,dev->oss.line1);
+ dev->dmasound.line1 = val;
+ mixer_level(dev,LINE1,dev->dmasound.line1);
/* fall throuth */
case MIXER_READ(SOUND_MIXER_LINE1):
- return put_user(dev->oss.line1 | dev->oss.line1 << 8, p);
+ return put_user(dev->dmasound.line1 | dev->dmasound.line1 << 8, p);
case MIXER_WRITE(SOUND_MIXER_LINE2):
if (get_user(val, p))
return -EFAULT;
val &= 0xff;
val = (val <= 50) ? 50 : 100;
- dev->oss.line2 = val;
- mixer_level(dev,LINE2,dev->oss.line2);
+ dev->dmasound.line2 = val;
+ mixer_level(dev,LINE2,dev->dmasound.line2);
/* fall throuth */
case MIXER_READ(SOUND_MIXER_LINE2):
- return put_user(dev->oss.line2 | dev->oss.line2 << 8, p);
+ return put_user(dev->dmasound.line2 | dev->dmasound.line2 << 8, p);
default:
return -EINVAL;
@@ -767,11 +780,44 @@ struct file_operations saa7134_mixer_fops = {
/* ------------------------------------------------------------------ */
+static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct saa7134_dmasound *dmasound = dev_id;
+ struct saa7134_dev *dev = dmasound->priv_data;
+ unsigned long report, status;
+ int loop, handled = 0;
+
+ for (loop = 0; loop < 10; loop++) {
+ report = saa_readl(SAA7134_IRQ_REPORT);
+ status = saa_readl(SAA7134_IRQ_STATUS);
+
+ if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
+ handled = 1;
+ saa_writel(SAA7134_IRQ_REPORT,report);
+ saa7134_irq_oss_done(dev, status);
+ } else {
+ goto out;
+ }
+ }
+
+ if (loop == 10) {
+ dprintk("error! looping IRQ!");
+ }
+out:
+ return IRQ_RETVAL(handled);
+}
+
int saa7134_oss_init1(struct saa7134_dev *dev)
{
+
+ if ((request_irq(dev->pci->irq, saa7134_oss_irq,
+ SA_SHIRQ | SA_INTERRUPT, dev->name,
+ (void*) &dev->dmasound)) < 0)
+ return -1;
+
/* general */
- init_MUTEX(&dev->oss.lock);
- init_waitqueue_head(&dev->oss.wq);
+ init_MUTEX(&dev->dmasound.lock);
+ init_waitqueue_head(&dev->dmasound.wq);
switch (dev->pci->device) {
case PCI_DEVICE_ID_PHILIPS_SAA7133:
@@ -783,17 +829,17 @@ int saa7134_oss_init1(struct saa7134_dev *dev)
}
/* dsp */
- dev->oss.rate = 32000;
- if (oss_rate)
- dev->oss.rate = oss_rate;
- dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000;
+ dev->dmasound.rate = 32000;
+ if (rate)
+ dev->dmasound.rate = rate;
+ dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000;
/* mixer */
- dev->oss.line1 = 50;
- dev->oss.line2 = 50;
- mixer_level(dev,LINE1,dev->oss.line1);
- mixer_level(dev,LINE2,dev->oss.line2);
- mixer_recsrc(dev, (dev->oss.rate == 32000) ? TV : LINE2);
+ dev->dmasound.line1 = 50;
+ dev->dmasound.line2 = 50;
+ mixer_level(dev,LINE1,dev->dmasound.line1);
+ mixer_level(dev,LINE2,dev->dmasound.line2);
+ mixer_recsrc(dev, (dev->dmasound.rate == 32000) ? TV : LINE2);
return 0;
}
@@ -809,7 +855,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
int next_blk, reg = 0;
spin_lock(&dev->slock);
- if (UNSET == dev->oss.dma_blk) {
+ if (UNSET == dev->dmasound.dma_blk) {
dprintk("irq: recording stopped\n");
goto done;
}
@@ -817,11 +863,11 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
if (0 == (status & 0x10000000)) {
/* odd */
- if (0 == (dev->oss.dma_blk & 0x01))
+ if (0 == (dev->dmasound.dma_blk & 0x01))
reg = SAA7134_RS_BA1(6);
} else {
/* even */
- if (1 == (dev->oss.dma_blk & 0x01))
+ if (1 == (dev->dmasound.dma_blk & 0x01))
reg = SAA7134_RS_BA2(6);
}
if (0 == reg) {
@@ -829,30 +875,137 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
(status & 0x10000000) ? "even" : "odd");
goto done;
}
- if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) {
- dprintk("irq: overrun [full=%d/%d]\n",dev->oss.read_count,
- dev->oss.bufsize);
+ if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
+ dprintk("irq: overrun [full=%d/%d]\n",dev->dmasound.read_count,
+ dev->dmasound.bufsize);
dsp_dma_stop(dev);
goto done;
}
/* next block addr */
- next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks;
- saa_writel(reg,next_blk * dev->oss.blksize);
- if (oss_debug > 2)
+ next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
+ saa_writel(reg,next_blk * dev->dmasound.blksize);
+ if (debug > 2)
dprintk("irq: ok, %s, next_blk=%d, addr=%x\n",
(status & 0x10000000) ? "even" : "odd ", next_blk,
- next_blk * dev->oss.blksize);
+ next_blk * dev->dmasound.blksize);
/* update status & wake waiting readers */
- dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks;
- dev->oss.read_count += dev->oss.blksize;
- wake_up(&dev->oss.wq);
+ dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
+ dev->dmasound.read_count += dev->dmasound.blksize;
+ wake_up(&dev->dmasound.wq);
done:
spin_unlock(&dev->slock);
}
+static int saa7134_dsp_create(struct saa7134_dev *dev)
+{
+ int err;
+
+ err = dev->dmasound.minor_dsp =
+ register_sound_dsp(&saa7134_dsp_fops,
+ dsp_nr[dev->nr]);
+ if (err < 0) {
+ goto fail;
+ }
+ printk(KERN_INFO "%s: registered device dsp%d\n",
+ dev->name,dev->dmasound.minor_dsp >> 4);
+
+ err = dev->dmasound.minor_mixer =
+ register_sound_mixer(&saa7134_mixer_fops,
+ mixer_nr[dev->nr]);
+ if (err < 0)
+ goto fail;
+ printk(KERN_INFO "%s: registered device mixer%d\n",
+ dev->name,dev->dmasound.minor_mixer >> 4);
+
+ return 0;
+
+fail:
+ unregister_sound_dsp(dev->dmasound.minor_dsp);
+ return 0;
+
+
+}
+
+static int oss_device_init(struct saa7134_dev *dev)
+{
+ dev->dmasound.priv_data = dev;
+ saa7134_oss_init1(dev);
+ saa7134_dsp_create(dev);
+ return 1;
+}
+
+static int oss_device_exit(struct saa7134_dev *dev)
+{
+
+ unregister_sound_mixer(dev->dmasound.minor_mixer);
+ unregister_sound_dsp(dev->dmasound.minor_dsp);
+
+ saa7134_oss_fini(dev);
+
+ if (dev->pci->irq > 0) {
+ synchronize_irq(dev->pci->irq);
+ free_irq(dev->pci->irq,&dev->dmasound);
+ }
+
+ dev->dmasound.priv_data = NULL;
+ return 1;
+}
+
+static int saa7134_oss_init(void)
+{
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
+
+ printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n");
+
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
+ if (dev->dmasound.priv_data == NULL) {
+ oss_device_init(dev);
+ } else {
+ printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name);
+ return -EBUSY;
+ }
+ }
+
+ if (dev == NULL)
+ printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n");
+
+ dmasound_init = oss_device_init;
+ dmasound_exit = oss_device_exit;
+
+ return 0;
+
+}
+
+static void saa7134_oss_exit(void)
+{
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
+
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
+
+ /* Device isn't registered by OSS, probably ALSA's */
+ if (!dev->dmasound.minor_dsp)
+ continue;
+
+ oss_device_exit(dev);
+ }
+
+ printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
+
+ return;
+}
+
+module_init(saa7134_oss_init);
+module_exit(saa7134_oss_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
index ae0c7a16539..ac6431ba4fc 100644
--- a/drivers/media/video/saa7134/saa7134-reg.h
+++ b/drivers/media/video/saa7134/saa7134-reg.h
@@ -27,7 +27,7 @@
/* DMA channels, n = 0 ... 6 */
#define SAA7134_RS_BA1(n) ((0x200 >> 2) + 4*n)
-#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n)
+#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n)
#define SAA7134_RS_PITCH(n) ((0x208 >> 2) + 4*n)
#define SAA7134_RS_CONTROL(n) ((0x20c >> 2) + 4*n)
#define SAA7134_RS_CONTROL_WSWAP (0x01 << 25)
@@ -43,16 +43,24 @@
#define SAA7134_FIFO_SIZE (0x2a0 >> 2)
#define SAA7134_THRESHOULD (0x2a4 >> 2)
+#define SAA7133_NUM_SAMPLES (0x588 >> 2)
+#define SAA7133_AUDIO_CHANNEL (0x58c >> 2)
+#define SAA7133_AUDIO_FORMAT (0x58f >> 2)
+#define SAA7133_DIGITAL_OUTPUT_SEL1 (0x46c >> 2)
+#define SAA7133_DIGITAL_OUTPUT_SEL2 (0x470 >> 2)
+#define SAA7133_DIGITAL_INPUT_XBAR1 (0x464 >> 2)
+#define SAA7133_ANALOG_IO_SELECT (0x594 >> 2)
+
/* main control */
#define SAA7134_MAIN_CTRL (0x2a8 >> 2)
-#define SAA7134_MAIN_CTRL_VPLLE (1 << 15)
-#define SAA7134_MAIN_CTRL_APLLE (1 << 14)
-#define SAA7134_MAIN_CTRL_EXOSC (1 << 13)
-#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12)
-#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11)
-#define SAA7134_MAIN_CTRL_ESFE (1 << 10)
-#define SAA7134_MAIN_CTRL_EBADC (1 << 9)
-#define SAA7134_MAIN_CTRL_EBDAC (1 << 8)
+#define SAA7134_MAIN_CTRL_VPLLE (1 << 15)
+#define SAA7134_MAIN_CTRL_APLLE (1 << 14)
+#define SAA7134_MAIN_CTRL_EXOSC (1 << 13)
+#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12)
+#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11)
+#define SAA7134_MAIN_CTRL_ESFE (1 << 10)
+#define SAA7134_MAIN_CTRL_EBADC (1 << 9)
+#define SAA7134_MAIN_CTRL_EBDAC (1 << 8)
#define SAA7134_MAIN_CTRL_TE6 (1 << 6)
#define SAA7134_MAIN_CTRL_TE5 (1 << 5)
#define SAA7134_MAIN_CTRL_TE4 (1 << 4)
@@ -348,6 +356,7 @@
/* test modes */
#define SAA7134_SPECIAL_MODE 0x1d0
+#define SAA7134_PRODUCTION_TEST_MODE 0x1d1
/* audio -- saa7133 + saa7135 only */
#define SAA7135_DSP_RWSTATE 0x580
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 463885601ab..470903e2f5e 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -46,17 +46,11 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
- u32 control;
dprintk("buffer_activate [%p]",buf);
buf->vb.state = STATE_ACTIVE;
buf->top_seen = 0;
- /* dma: setup channel 5 (= TS) */
- control = SAA7134_RS_CONTROL_BURST_16 |
- SAA7134_RS_CONTROL_ME |
- (buf->pt->dma >> 12);
-
if (NULL == next)
next = buf;
if (V4L2_FIELD_TOP == buf->vb.field) {
@@ -68,8 +62,6 @@ static int buffer_activate(struct saa7134_dev *dev,
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
}
- saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE);
- saa_writel(SAA7134_RS_CONTROL(5),control);
/* start DMA */
saa7134_set_dmabits(dev);
@@ -84,6 +76,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
unsigned int lines, llength, size;
+ u32 control;
int err;
dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
@@ -115,6 +108,18 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (err)
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);
+
buf->vb.state = STATE_PREPARED;
buf->activate = buffer_activate;
buf->vb.field = field;
@@ -164,11 +169,11 @@ EXPORT_SYMBOL_GPL(saa7134_ts_qops);
/* ----------------------------------------------------------- */
/* exported stuff */
-static unsigned int tsbufs = 4;
+static unsigned int tsbufs = 8;
module_param(tsbufs, int, 0444);
MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32");
-static unsigned int ts_nr_packets = 30;
+static unsigned int ts_nr_packets = 64;
module_param(ts_nr_packets, int, 0444);
MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
@@ -220,10 +225,10 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
if (dev->ts_q.curr) {
field = dev->ts_q.curr->vb.field;
if (field == V4L2_FIELD_TOP) {
- if ((status & 0x100000) != 0x100000)
+ if ((status & 0x100000) != 0x000000)
goto done;
} else {
- if ((status & 0x100000) != 0x000000)
+ if ((status & 0x100000) != 0x100000)
goto done;
}
saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE);
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index badf2f9e307..93268427750 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -207,6 +207,10 @@ static void tvaudio_setcarrier(struct saa7134_dev *dev,
saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary));
}
+#define SAA7134_MUTE_MASK 0xbb
+#define SAA7134_MUTE_ANALOG 0x04
+#define SAA7134_MUTE_I2S 0x40
+
static void mute_input_7134(struct saa7134_dev *dev)
{
unsigned int mute;
@@ -241,7 +245,11 @@ static void mute_input_7134(struct saa7134_dev *dev)
if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
/* 7134 mute */
- saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xbf : 0xbb);
+ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ?
+ SAA7134_MUTE_MASK |
+ SAA7134_MUTE_ANALOG |
+ SAA7134_MUTE_I2S :
+ SAA7134_MUTE_MASK);
/* switch internal audio mux */
switch (in->amux) {
@@ -342,8 +350,8 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
set_current_state(TASK_INTERRUPTIBLE);
schedule();
} else {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(timeout));
+ schedule_timeout_interruptible
+ (msecs_to_jiffies(timeout));
}
}
remove_wait_queue(&dev->thread.wq, &wait);
@@ -753,17 +761,17 @@ static int mute_input_7133(struct saa7134_dev *dev)
/* switch gpio-connected external audio mux */
- if (0 != card(dev).gpiomask) {
- mask = card(dev).gpiomask;
+ if (0 != card(dev).gpiomask) {
+ mask = card(dev).gpiomask;
if (card(dev).mute.name && dev->ctl_mute)
in = &card(dev).mute;
else
in = dev->input;
- saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask);
- saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio);
- saa7134_track_gpio(dev,in->name);
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio);
+ saa7134_track_gpio(dev,in->name);
}
return 0;
@@ -1016,9 +1024,12 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
return 0;
}
+EXPORT_SYMBOL(saa_dsp_writel);
+
/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
+
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 35e5e85f669..45c852df13e 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -30,6 +30,9 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+/* Include V4L1 specific functions. Should be removed soon */
+#include <linux/videodev.h>
+
/* ------------------------------------------------------------------ */
static unsigned int video_debug = 0;
@@ -48,6 +51,43 @@ MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");
printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x191 */
+
+/* Bit 0: VIP code T bit polarity */
+
+#define VP_T_CODE_P_NON_INVERTED 0x00
+#define VP_T_CODE_P_INVERTED 0x01
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x195 */
+
+/* Bit 2: Video output clock delay control */
+
+#define VP_CLK_CTRL2_NOT_DELAYED 0x00
+#define VP_CLK_CTRL2_DELAYED 0x04
+
+/* Bit 1: Video output clock invert control */
+
+#define VP_CLK_CTRL1_NON_INVERTED 0x00
+#define VP_CLK_CTRL1_INVERTED 0x02
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x196 */
+
+/* Bits 2 to 0: VSYNC pin video vertical sync type */
+
+#define VP_VS_TYPE_MASK 0x07
+
+#define VP_VS_TYPE_OFF 0x00
+#define VP_VS_TYPE_V123 0x01
+#define VP_VS_TYPE_V_ITU 0x02
+#define VP_VS_TYPE_VGATE_L 0x03
+#define VP_VS_TYPE_RESERVED1 0x04
+#define VP_VS_TYPE_RESERVED2 0x05
+#define VP_VS_TYPE_F_ITU 0x06
+#define VP_VS_TYPE_SC_FID 0x07
+
+/* ------------------------------------------------------------------ */
/* data structs for video */
static int video_out[][9] = {
@@ -273,12 +313,12 @@ static struct saa7134_tvnorm tvnorms[] = {
.h_start = 0,
.h_stop = 719,
- .video_v_start = 23,
- .video_v_stop = 262,
- .vbi_v_start_0 = 10,
- .vbi_v_stop_0 = 21,
- .vbi_v_start_1 = 273,
- .src_timing = 7,
+ .video_v_start = 23,
+ .video_v_stop = 262,
+ .vbi_v_start_0 = 10,
+ .vbi_v_stop_0 = 21,
+ .vbi_v_start_1 = 273,
+ .src_timing = 7,
.sync_control = 0x18,
.luma_control = 0x40,
@@ -622,7 +662,7 @@ static void set_size(struct saa7134_dev *dev, int task,
prescale = 1;
xscale = 1024 * dev->crop_current.width / prescale / width;
yscale = 512 * div * dev->crop_current.height / height;
- dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
+ dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
set_h_prescale(dev,task,prescale);
saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff);
saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8);
@@ -752,20 +792,20 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win)
maxh = dev->crop_current.height;
if (V4L2_FIELD_ANY == field) {
- field = (win->w.height > maxh/2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_TOP;
- }
- switch (field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- maxh = maxh / 2;
- break;
- case V4L2_FIELD_INTERLACED:
- break;
- default:
- return -EINVAL;
- }
+ field = (win->w.height > maxh/2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_TOP;
+ }
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ maxh = maxh / 2;
+ break;
+ case V4L2_FIELD_INTERLACED:
+ break;
+ default:
+ return -EINVAL;
+ }
win->field = field;
if (win->w.width > maxw)
@@ -1306,13 +1346,13 @@ video_poll(struct file *file, struct poll_table_struct *wait)
if (res_locked(fh->dev,RESOURCE_VIDEO)) {
up(&fh->cap.lock);
return POLLERR;
- }
- if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) {
- up(&fh->cap.lock);
- return POLLERR;
- }
- fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
- fh->cap.read_off = 0;
+ }
+ if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) {
+ up(&fh->cap.lock);
+ return POLLERR;
+ }
+ fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
+ fh->cap.read_off = 0;
}
up(&fh->cap.lock);
buf = fh->cap.read_buf;
@@ -1666,9 +1706,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
+ unsigned int tuner_type = dev->tuner_type;
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "saa7134");
+ 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));
@@ -1677,9 +1718,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_TUNER |
V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING;
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_TUNER;
+
+ if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET))
+ cap->capabilities &= ~V4L2_CAP_TUNER;
+
return 0;
}
@@ -1793,9 +1838,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
crop->c.height = b->top - crop->c.top + b->height;
if (crop->c.left < b->left)
- crop->c.top = b->left;
+ crop->c.left = b->left;
if (crop->c.left > b->left + b->width)
- crop->c.top = b->left + b->width;
+ crop->c.left = b->left + b->width;
if (crop->c.width > b->left - crop->c.left + b->width)
crop->c.width = b->left - crop->c.left + b->width;
@@ -1817,6 +1862,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
break;
if (NULL != card_in(dev,n).name) {
strcpy(t->name, "Television");
+ t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM |
V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 |
@@ -1892,26 +1938,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
}
case VIDIOC_S_AUDIO:
return 0;
- case VIDIOC_G_PARM:
- {
- struct v4l2_captureparm *parm = arg;
- memset(parm,0,sizeof(*parm));
- return 0;
- }
-
- case VIDIOC_G_PRIORITY:
- {
- enum v4l2_priority *p = arg;
-
- *p = v4l2_prio_max(&dev->prio);
- return 0;
- }
- case VIDIOC_S_PRIORITY:
- {
- enum v4l2_priority *prio = arg;
-
- return v4l2_prio_change(&dev->prio, &fh->prio, *prio);
- }
+ case VIDIOC_G_PARM:
+ {
+ struct v4l2_captureparm *parm = arg;
+ memset(parm,0,sizeof(*parm));
+ return 0;
+ }
+
+ case VIDIOC_G_PRIORITY:
+ {
+ enum v4l2_priority *p = arg;
+
+ *p = v4l2_prio_max(&dev->prio);
+ return 0;
+ }
+ case VIDIOC_S_PRIORITY:
+ {
+ enum v4l2_priority *prio = arg;
+
+ return v4l2_prio_change(&dev->prio, &fh->prio, *prio);
+ }
/* --- preview ioctls ---------------------------------------- */
case VIDIOC_ENUM_FMT:
@@ -2018,7 +2064,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_format *f = arg;
return saa7134_try_fmt(dev,fh,f);
}
-
+#ifdef HAVE_V4L1
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
@@ -2043,6 +2089,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
}
return 0;
}
+#endif
case VIDIOC_REQBUFS:
return videobuf_reqbufs(saa7134_queue(fh),arg);
@@ -2060,7 +2107,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
{
int res = saa7134_resource(fh);
- if (!res_get(dev,fh,res))
+ if (!res_get(dev,fh,res))
return -EBUSY;
return videobuf_streamon(saa7134_queue(fh));
}
@@ -2102,7 +2149,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
- strcpy(cap->driver, "saa7134");
+ 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));
@@ -2119,6 +2166,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
memset(t,0,sizeof(*t));
strcpy(t->name, "Radio");
+ t->type = V4L2_TUNER_RADIO;
saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
@@ -2233,7 +2281,7 @@ struct video_device saa7134_video_template =
{
.name = "saa7134-video",
.type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY|
- VID_TYPE_CLIPPING|VID_TYPE_SCALES,
+ VID_TYPE_CLIPPING|VID_TYPE_SCALES,
.hardware = 0,
.fops = &video_fops,
.minor = -1,
@@ -2280,7 +2328,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
dev->tda9887_conf |= TDA9887_AUTOMUTE;
dev->automute = 0;
- INIT_LIST_HEAD(&dev->video_q.queue);
+ INIT_LIST_HEAD(&dev->video_q.queue);
init_timer(&dev->video_q.timeout);
dev->video_q.timeout.function = saa7134_buffer_timeout;
dev->video_q.timeout.data = (unsigned long)(&dev->video_q);
@@ -2289,13 +2337,28 @@ int saa7134_video_init1(struct saa7134_dev *dev)
if (saa7134_boards[dev->board].video_out) {
/* enable video output */
int vo = saa7134_boards[dev->board].video_out;
+ int video_reg;
+ unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;
saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);
- saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_out[vo][1]);
+ video_reg = video_out[vo][1];
+ if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)
+ video_reg &= ~VP_T_CODE_P_INVERTED;
+ saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);
saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);
saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);
- saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_out[vo][5]);
- saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_out[vo][6]);
+ video_reg = video_out[vo][5];
+ if (vid_port_opts & SET_CLOCK_NOT_DELAYED)
+ video_reg &= ~VP_CLK_CTRL2_DELAYED;
+ if (vid_port_opts & SET_CLOCK_INVERTED)
+ video_reg |= VP_CLK_CTRL1_INVERTED;
+ saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg);
+ video_reg = video_out[vo][6];
+ if (vid_port_opts & SET_VSYNC_OFF) {
+ video_reg &= ~VP_VS_TYPE_MASK;
+ video_reg |= VP_VS_TYPE_OFF;
+ }
+ saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg);
saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);
saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);
}
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 3ea09142ec9..add49db1ad4 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -24,16 +24,18 @@
#include <linux/pci.h>
#include <linux/i2c.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
#include <linux/kdev_t.h>
#include <linux/input.h>
+#include <linux/notifier.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <media/tuner.h>
#include <media/audiochip.h>
-#include <media/id.h>
#include <media/ir-common.h>
+#include <media/ir-kbd-i2c.h>
#include <media/video-buf.h>
#include <media/video-buf-dvb.h>
@@ -45,6 +47,10 @@
#endif
#define UNSET (-1U)
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
/* ----------------------------------------------------------- */
/* enums */
@@ -187,10 +193,40 @@ struct saa7134_format {
#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
#define SAA7134_BOARD_KWORLD_TERMINATOR 65
#define SAA7134_BOARD_YUAN_TUN900 66
+#define SAA7134_BOARD_BEHOLD_409FM 67
+#define SAA7134_BOARD_GOTVIEW_7135 68
+#define SAA7134_BOARD_PHILIPS_EUROPA 69
+#define SAA7134_BOARD_VIDEOMATE_DVBT_300 70
+#define SAA7134_BOARD_VIDEOMATE_DVBT_200 71
+#define SAA7134_BOARD_RTD_VFG7350 72
+#define SAA7134_BOARD_RTD_VFG7330 73
+#define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74
+#define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75
+#define SAA7134_BOARD_MONSTERTV_MOBILE 76
+#define SAA7134_BOARD_PINNACLE_PCTV_110i 77
+#define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78
+#define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79
+#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
+#define SAA7134_BOARD_PHILIPS_TIGER 81
+#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
+/* ----------------------------------------------------------- */
+/* Since we support 2 remote types, lets tell them apart */
+
+#define SAA7134_REMOTE_GPIO 1
+#define SAA7134_REMOTE_I2C 2
+
+/* ----------------------------------------------------------- */
+/* Video Output Port Register Initialization Options */
+
+#define SET_T_CODE_POLARITY_NON_INVERTED (1 << 0)
+#define SET_CLOCK_NOT_DELAYED (1 << 1)
+#define SET_CLOCK_INVERTED (1 << 2)
+#define SET_VSYNC_OFF (1 << 3)
+
struct saa7134_input {
char *name;
unsigned int vmux;
@@ -226,6 +262,7 @@ struct saa7134_board {
/* peripheral I/O */
enum saa7134_video_out video_out;
enum saa7134_mpeg_type mpeg;
+ unsigned int vid_port_opts;
};
#define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name)
@@ -319,9 +356,9 @@ struct saa7134_fh {
struct saa7134_pgtable pt_vbi;
};
-/* oss dsp status */
-struct saa7134_oss {
- struct semaphore lock;
+/* dmasound dsp status */
+struct saa7134_dmasound {
+ struct semaphore lock;
int minor_mixer;
int minor_dsp;
unsigned int users_dsp;
@@ -347,20 +384,22 @@ struct saa7134_oss {
unsigned int dma_blk;
unsigned int read_offset;
unsigned int read_count;
+ void * priv_data;
+ snd_pcm_substream_t *substream;
};
/* IR input */
struct saa7134_ir {
- struct input_dev dev;
+ struct input_dev *dev;
struct ir_input_state ir;
char name[32];
char phys[32];
u32 mask_keycode;
u32 mask_keydown;
u32 mask_keyup;
- int polling;
- u32 last_gpio;
- struct timer_list timer;
+ int polling;
+ u32 last_gpio;
+ struct timer_list timer;
};
/* ts/mpeg status */
@@ -383,8 +422,8 @@ struct saa7134_mpeg_ops {
/* global device status */
struct saa7134_dev {
struct list_head devlist;
- struct semaphore lock;
- spinlock_t slock;
+ struct semaphore lock;
+ spinlock_t slock;
#ifdef VIDIOC_G_PRIORITY
struct v4l2_prio_state prio;
#endif
@@ -394,7 +433,7 @@ struct saa7134_dev {
struct video_device *video_dev;
struct video_device *radio_dev;
struct video_device *vbi_dev;
- struct saa7134_oss oss;
+ struct saa7134_dmasound dmasound;
/* infrared remote */
int has_remote;
@@ -421,7 +460,7 @@ struct saa7134_dev {
/* i2c i/o */
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
- unsigned char eedata[64];
+ unsigned char eedata[128];
/* video overlay */
struct v4l2_framebuffer ovbuf;
@@ -532,6 +571,10 @@ void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf);
int saa7134_set_dmabits(struct saa7134_dev *dev);
+extern int (*dmasound_init)(struct saa7134_dev *dev);
+extern int (*dmasound_exit)(struct saa7134_dev *dev);
+
+
/* ----------------------------------------------------------- */
/* saa7134-cards.c */
@@ -626,6 +669,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status);
int saa7134_input_init1(struct saa7134_dev *dev);
void saa7134_input_fini(struct saa7134_dev *dev);
void saa7134_input_irq(struct saa7134_dev *dev);
+void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
/*
* Local variables: