AVerMedia Cardbus Plus E501R

From LinuxTVWiki
Jump to navigation Jump to search

Итак, стал я недавно обладателем сего чудного девайса =)
Ноутбук Benq Joybook 2100-r32. Debian unstable. Ядро 2.6.17.

Быстрый старт

Добавить опцию загрузки модуля saa7134:

options saa7134 card=46 tuner=12

В этом случае девайс определиться как AverMedia Cardbus E500.

Если Вы используете alsa, то не забудьте загрузить модуль saa7134-alsa, если oss - saa7134-oss.

Для того, чтобы поиметь звук в таких программах как tvtime нужно использовать SOX-redirect:

sox -c 2 -s -w -r 32000 -t ossdsp /dev/dsp2 -t ossdsp -w -r 32000 /dev/dsp

Без лишних телодвижений можно получить звук в mplayer'е, например вот так (для alsa):

mplayer -vo xv -ao alsa -tv driver=v4l2:device=/dev/video0:width=720:height=576:normid=1:chanlist=russia:\
immediatemode=0:alsa:adevice=hw.1,0:audiorate=32000:channels=<list_of_channels> tv://

Тестировал сей девайс, на версии ядра 2.6.16.34, работает все замечательно:

options saa7134 card=46 tuner=12 alsa=1
options tda9887 secam=d
install saa7134 /sbin/modprobe tda9887; /sbin/modprobe --ignore-install saa7134; /sbin/modprobe saa7134-alsa && /usr/sbin/alsactl restore >/dev/null 2>&1 || :
remove saa7134-alsa { /usr/sbin/alsactl store >/dev/null 2>&1 || : ; }; /sbin/modprobe -r --ignore-remove saa7134-alsa

все что перечислено ниже можно пропустить.


Делаем все как надо ;)

Редактируем драйвер ядра ;) В saa7134.h добавляем определение новой карточки:

#define SAA7134_BOARD_AVERMEDIA_CARDBUS_PLUS 85

Далее редактируем saa7134-card.c, добавляем определение устройства в структуру saa7134_boards:

        [SAA7134_BOARD_AVERMEDIA_CARDBUS_PLUS] = {
                /* hayova@gmail.com */
                .name           = "AVerMedia Cardbus Plus",
                .audio_clock    = 0x187de7,
                .tuner_type     = TUNER_ALPS_TSBE5_PAL,
                .radio_type     = TUNER_TEA5767,
                .tuner_addr     = 0x61,
                .radio_addr     = 0x60,
                .tda9887_conf   = TDA9887_PRESENT,
                .gpiomask       = 0x0C400003,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 1,
                        .amux = TV,
                        .tv   = 1,
                        .gpio = 0x0C400001,
                },{
                        .name = name_comp1,
                        .vmux = 3,
                        .amux = LINE1,
                        .gpio = 0x0C400002,
                },{
                        .name = name_svideo,
                        .vmux = 6,
                        .amux = LINE1,
                        .gpio = 0x0C400002,
                }},
                .radio = {
                        .name = name_radio,
                        .amux = LINE2,
                        .gpio = 0x04400001,
                },

В том же файле вносим изменения в структуру saa7134_pci_tbl:

		/* AVerMedia CardBus Plus */
		.vendor       = PCI_VENDOR_ID_PHILIPS,
		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
		.subdevice    = 0xb7e9,
		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_PLUS,
	},{

И добавляем инициализацию устройства в функцию saa7134_board_init1:

	case SAA7134_BOARD_AVERMEDIA_CARDBUS_PLUS:
		/* power-up tuner chip */
		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0C440003, 0x0C440003);
		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0C400000, 0x0C400000);
		dev->has_remote = SAA7134_REMOTE_GPIO;
		msleep(1);
		break;

В файле saa7134-input.c вносим изменения в функцию saa7134_input_init1:

	case SAA7134_BOARD_AVERMEDIA_CARDBUS_PLUS:
		ir_codes     = ir_codes_gotview7135;
		mask_keycode = 0x0007C8;
		mask_keydown = 0x000010;
		polling      = 50; // ms
		break;

Далее к saa7134-tvaudio.c применяем следующий патч (решает проблему со звуком в SECAM):

--- linux-2.6.18-rc1-mm1-build/drivers/media/video/saa7134/saa7134-tvaudio.c.old	2006-05-13 23:29:35.000000000 +0400
+++ linux-2.6.18-rc1-mm1-build/drivers/media/video/saa7134/saa7134-tvaudio.c	2006-07-12 04:22:01.000000000 +0400
@@ -50,6 +50,14 @@
 module_param(audio_clock_tweak, int, 0644);
 MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])");
 
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+
 #define dprintk(fmt, arg...)	if (audio_debug) \
 	printk(KERN_DEBUG "%s/audio: " fmt, dev->name , ## arg)
 #define d2printk(fmt, arg...)	if (audio_debug > 1) \
@@ -93,61 +101,61 @@
 static struct saa7134_tvaudio tvaudio[] = {
 	{
 		.name          = "PAL-B/G FM-stereo",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_BG,
 		.mode          = TVAUDIO_FM_BG_STEREO,
 		.carr1         = 5500,
 		.carr2         = 5742,
 	},{
 		.name          = "PAL-D/K1 FM-stereo",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_DK,
 		.carr1         = 6500,
 		.carr2         = 6258,
 		.mode          = TVAUDIO_FM_BG_STEREO,
 	},{
 		.name          = "PAL-D/K2 FM-stereo",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_DK,
 		.carr1         = 6500,
 		.carr2         = 6742,
 		.mode          = TVAUDIO_FM_BG_STEREO,
 	},{
 		.name          = "PAL-D/K3 FM-stereo",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_DK,
 		.carr1         = 6500,
 		.carr2         = 5742,
 		.mode          = TVAUDIO_FM_BG_STEREO,
 	},{
 		.name          = "PAL-B/G NICAM",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_BG,
 		.carr1         = 5500,
 		.carr2         = 5850,
 		.mode          = TVAUDIO_NICAM_FM,
 	},{
 		.name          = "PAL-I NICAM",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_I,
 		.carr1         = 6000,
 		.carr2         = 6552,
 		.mode          = TVAUDIO_NICAM_FM,
 	},{
 		.name          = "PAL-D/K NICAM",
-		.std           = V4L2_STD_PAL,
+		.std           = V4L2_STD_PAL_DK,
 		.carr1         = 6500,
 		.carr2         = 5850,
 		.mode          = TVAUDIO_NICAM_FM,
 	},{
 		.name          = "SECAM-L NICAM",
-		.std           = V4L2_STD_SECAM,
+		.std           = V4L2_STD_SECAM_L,
 		.carr1         = 6500,
 		.carr2         = 5850,
 		.mode          = TVAUDIO_NICAM_AM,
 	},{
 		.name          = "SECAM-L MONO",
-		.std           = V4L2_STD_SECAM,
+		.std           = V4L2_STD_SECAM_L,
 		.carr1         = 6500,
 		.carr2         = -1,
 		.mode          = TVAUDIO_AM_MONO,
 	},{
 		.name          = "SECAM-D/K",
-		.std           = V4L2_STD_SECAM,
+		.std           = V4L2_STD_SECAM_DK,
 		.carr1         = 6500,
 		.carr2         = -1,
 		.mode          = TVAUDIO_FM_MONO,
@@ -514,6 +522,119 @@
 	return 0;
 }
 
+/* get more precise norm info from insmod option */
+static int saa7134_fixup_std(struct saa7134_dev *dev)
+{
+	struct saa7134_tvnorm *t = dev->tvnorm;
+	if ((t->id & V4L2_STD_PAL) == V4L2_STD_PAL) {
+		switch (pal[0]) {
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+			dprintk ("insmod fixup: PAL => PAL-BG\n");
+			t->id = V4L2_STD_PAL_BG;
+			break;
+		case 'i':
+		case 'I':
+			dprintk ("insmod fixup: PAL => PAL-I\n");
+			t->id = V4L2_STD_PAL_I;
+			break;
+		case 'd':
+		case 'D':
+		case 'k':
+		case 'K':
+			dprintk ("insmod fixup: PAL => PAL-DK\n");
+			t->id = V4L2_STD_PAL_DK;
+			break;
+		case 'M':
+		case 'm':
+			dprintk ("insmod fixup: PAL => PAL-M\n");
+			t->id = V4L2_STD_PAL_M;
+			break;
+		case 'N':
+		case 'n':
+			if (pal[1] == 'c' || pal[1] == 'C') {
+				dprintk("insmod fixup: PAL => PAL-Nc\n");
+				t->id = V4L2_STD_PAL_Nc;
+			} else {
+				dprintk ("insmod fixup: PAL => PAL-N\n");
+				t->id = V4L2_STD_PAL_N;
+			}
+			break;
+		case '-':
+			/* default parameter, do nothing */
+			break;
+		default:
+			dprintk ("pal= argument not recognised\n");
+			break;
+		}
+	}
+	if ((t->id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
+		switch (secam[0]) {
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+		case 'h':
+		case 'H':
+			dprintk("insmod fixup: SECAM => SECAM-BGH\n");
+			t->id = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+			break;
+		case 'd':
+		case 'D':
+		case 'k':
+		case 'K':
+			dprintk ("insmod fixup: SECAM => SECAM-DK\n");
+			t->id = V4L2_STD_SECAM_DK;
+			break;
+		case 'l':
+		case 'L':
+			if ((secam[1]=='C')||(secam[1]=='c')) {
+				dprintk ("insmod fixup: SECAM => SECAM-L'\n");
+				t->id = V4L2_STD_SECAM_LC;
+			} else {
+				dprintk ("insmod fixup: SECAM => SECAM-L\n");
+				t->id = V4L2_STD_SECAM_L;
+			}
+			break;
+		case '-':
+			/* default parameter, do nothing */
+			break;
+		default:
+			dprintk ("secam= argument not recognised\n");
+			break;
+		}
+	}
+
+	if ((t->id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+		switch (ntsc[0]) {
+		case 'm':
+		case 'M':
+			dprintk("insmod fixup: NTSC => NTSC-M\n");
+			t->id = V4L2_STD_NTSC_M;
+			break;
+		case 'j':
+		case 'J':
+			dprintk("insmod fixup: NTSC => NTSC_M_JP\n");
+			t->id = V4L2_STD_NTSC_M_JP;
+			break;
+		case 'k':
+		case 'K':
+			dprintk("insmod fixup: NTSC => NTSC_M_KR\n");
+			t->id = V4L2_STD_NTSC_M_KR;
+			break;
+		case '-':
+			/* default parameter, do nothing */
+			break;
+		default:
+			dprintk("ntsc= argument not recognised\n");
+			break;
+		}
+	}
+	return 0;
+}
+
 static int tvaudio_thread(void *data)
 {
 	struct saa7134_dev *dev = data;
@@ -605,6 +726,7 @@
 		saa7134_tvaudio_setmute(dev);
 
 		/* find the exact tv audio norm */
+		saa7134_fixup_std(dev);
 		for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
 			if (dev->tvnorm->id != UNSET &&
 				!(dev->tvnorm->id & tvaudio[i].std))

Потом в файле tuner-core.c вносим изменения в функцию tuner_attach:

	if (!no_autodetect) {
		switch (addr) {
		case 0x42:
		case 0x43:
		case 0x4a:
		case 0x4b:
			/* If chip is not tda8290, don't register.
			   since it can be tda9887*/
			if (tda8290_probe(&t->i2c) == 0) {
				tuner_dbg("chip at addr %x is a tda8290\n", addr);
			} else {
				/* Default is being tda9887 */
				t->type = TUNER_TDA9887;
				t->mode_mask = T_ANALOG_TV;
				t->mode = T_STANDBY;
				goto register_client;
			}
			break;
		case 0x60:
			//if (tea5767_autodetection(&t->i2c) != EINVAL) {
				t->type = TUNER_TEA5767;
				t->mode_mask = T_RADIO;
				t->mode = T_STANDBY;
				t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
				default_mode_mask &= ~T_RADIO;

				goto register_client;
			//}
			break;
		
		case 0x61:
			t->type = TUNER_ALPS_TSBE5_PAL;
			t->mode_mask = T_ANALOG_TV;
			t->mode = T_STANDBY;

			goto register_client;
			
			break;
		}
	}

Проблемы

1. все также не работает радио и пульт :(

И еще, данные, полученные при установленной опции i2c_scan=1 модуля saa7134:

saa7134[0]: i2c scan: found device @ 0x80  [???] -- возможно IR (???)
saa7134[0]: i2c scan: found device @ 0x84  [???] -- некая разновидность TDA9887 (???)
saa7134[0]: i2c scan: found device @ 0xa0  [eeprom]
saa7134[0]: i2c scan: found device @ 0xc0  [tuner (analog)]  -- тюнер TEA5767
saa7134[0]: i2c scan: found device @ 0xc2  [???]  -- тюнер ALPS TSEZ1

Кроме того, я отписался на список рассылки v4l, там же можно найти больше логов, если кого-нибудь заинтересует.

Пожалуйста поправляйте/добавляйте.


--Hayova 13:09, 18 June 2006 (CEST)