Hi, again This is the 2nd part of my patches for the MD7134 hybrid card. This part is the changes in the SAA7134 driver: - Introduce the hybrid version of this card - A patch in saa7134-core.c to remain compatibiliy to the analog version of the card - Modifications in saa7134-video.c to switch between analog and digital mode - Introduce the FMD1216ME hybrid tuner - Additional i2c client calls to support reinitialization of the tuner (the FMD needs this) and for the FM radio mode of the tda9887 You experienced guys out there: Please have a careful look especially at the client calls, I am new to this game. Have fun Hartmut Hackmann >-------------------- snip -----------------------< diff -uprNw video4linux.orig/ChangeLog video4linux/ChangeLog --- video4linux.orig/ChangeLog 2005-04-26 11:07:03.000000000 +0200 +++ video4linux/ChangeLog 2005-04-30 02:08:57.000000000 +0200 @@ -1,14 +1,79 @@ -2005-04-26 11:01 kraxel +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) - * README.patches: + * Makefile - - update README.patches + - added driver for TDA10046 -2005-04-04 00:14 kraxel + * tda1004x.c tda1004x.h - * README.patches: + - added config options and code for + + 16 MHZ crystal + + different IF frequencies + + different AGC controls + + boot the DSP from on board EEPROM - - Final commit: add README.patches + - be more relaxed with different firmware revisions + + - code cleanup, rely less on default settings + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * saa7134-cards.c saa7134.c saa7134-dvb-c + + - introduced / modified support for Medion MD7134 / Philips TOUGH reference design + + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * saa7134-core.c + + - distinguish DVB-T and analog only version of the MD7134 board + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * saa7134-oss.c + + - fixed DMA memory allocation and setup + + - fixed odd / even buffer assignment + +2005-04-29 Hartmut Hackmann (actually Gerd Knorr) + + * saa7134-ts.c + + - fixed odd / even buffer assignment + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * saa7134-tvaudio.c + + - fixed audio clock switching for oss sound streaming + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * saa7134-video.c + + - reinitialize (MD7134) hybrid tuner for analog TV + (if prior operation was DVB-T) + + - at exit, ensure that planar mode is off, otherwise + DVB-T will not work + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * tda9887.c audiochip.h + + - added i2c client call for FM radio with FMD1216 tuner + +2005-04-29 Hartmut Hackmann (hartmut.hackmann@xxxxxxxxxxx) + + * tuner-core.c tuner-simple.c tuner.h + + - added support for Philips FMD1216ME tuner + + - allow run time change of tuner type (for MD7134) + + - added i2c client call to reinitialize tuner 2005-03-10 11:07 kraxel diff -uprNw video4linux.orig/Makefile video4linux/Makefile --- video4linux.orig/Makefile 2005-02-21 15:07:00.000000000 +0100 +++ video4linux/Makefile 2005-03-21 00:30:22.000000000 +0100 @@ -40,7 +40,7 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda obj-$(CONFIG_VIDEO_TVAUDIO) += msp3400.o tvaudio.o tvmixer.o obj-$(CONFIG_VIDEO_CX88_DVB) += video-buf-dvb.o cx88-dvb.o cx22702.o dvb-pll.o or51132.o -obj-$(CONFIG_VIDEO_SAA7134_DVB) += video-buf-dvb.o saa7134-dvb.o mt352.o +obj-$(CONFIG_VIDEO_SAA7134_DVB) += video-buf-dvb.o saa7134-dvb.o mt352.o tda1004x.o # 2.6-only stuff ifeq ($(VERSION).$(PATCHLEVEL),2.6) diff -uprNw video4linux.orig/audiochip.h video4linux/audiochip.h --- video4linux.orig/audiochip.h 2004-10-13 13:07:00.000000000 +0200 +++ video4linux/audiochip.h 2005-04-27 00:58:48.000000000 +0200 @@ -31,5 +31,5 @@ /* misc stuff to pass around config info to i2c chips */ #define AUDC_CONFIG_PINNACLE _IOW('m',32,int) - +#define AUDC_CONFIG_PHILIPS_FMD _IO('m',33) #endif /* AUDIOCHIP_H */ diff -uprNw video4linux.orig/load_modules video4linux/load_modules --- video4linux.orig/load_modules 1970-01-01 01:00:00.000000000 +0100 +++ video4linux/load_modules 2005-04-27 01:12:12.000000000 +0200 @@ -0,0 +1,16 @@ +modprobe i2c-core +modprobe firmware_class +insmod ./video-buf.ko +modprobe dvb_core +modprobe videodev +insmod ./ir-common.ko +insmod ./v4l1-compat.ko +insmod ./v4l2-common.ko +insmod ./tuner.ko tuner +insmod ./tda9887.ko +insmod ./tda1004x.ko +insmod ./mt352.ko +insmod ./video-buf-dvb.ko +insmod ./saa7134.ko ts_nr_packets=128 oss=1 +insmod ./saa7134-dvb.ko + diff -uprNw video4linux.orig/rm_modules video4linux/rm_modules --- video4linux.orig/rm_modules 1970-01-01 01:00:00.000000000 +0100 +++ video4linux/rm_modules 2005-03-23 23:33:35.000000000 +0100 @@ -0,0 +1,4 @@ +rmmod saa7134_dvb tda1004x tda9887 mt352 +rmmod tuner saa7134 +rmmod v4l2_common v4l1_compat ir_common videodev video_buf_dvb +rmmod dvb_core video_buf diff -uprNw video4linux.orig/saa7134-cards.c video4linux/saa7134-cards.c --- video4linux.orig/saa7134-cards.c 2005-03-07 13:07:00.000000000 +0100 +++ video4linux/saa7134-cards.c 2005-04-30 01:19:21.000000000 +0200 @@ -474,9 +474,8 @@ struct saa7134_board saa7134_boards[] = }, [SAA7134_BOARD_MD7134] = { .name = "Medion 7134", - //.audio_clock = 0x00200000, .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, .tda9887_conf = TDA9887_PRESENT, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ @@ -1546,6 +1545,30 @@ struct saa7134_board saa7134_boards[] = // .gpio = 0x4000, }}, }, + [SAA7134_BOARD_PHILIPS_TOUGH] = { + .name = "Philips TOUGH DVB-T reference design", + .tuner_type = TUNER_ABSENT, + .audio_clock = 0x00187de7, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -1840,6 +1863,12 @@ struct pci_device_id saa7134_pci_tbl[] = .driver_data = SAA7134_BOARD_FLYDVBTDUO, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = PCI_VENDOR_ID_PHILIPS, + .subdevice = 0x2004, + .driver_data = SAA7134_BOARD_PHILIPS_TOUGH, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, diff -uprNw video4linux.orig/saa7134-core.c video4linux/saa7134-core.c --- video4linux.orig/saa7134-core.c 2005-02-22 11:07:00.000000000 +0100 +++ video4linux/saa7134-core.c 2005-04-25 22:10:09.000000000 +0200 @@ -722,7 +722,6 @@ static int saa7134_hwinit1(struct saa713 SAA7134_MAIN_CTRL_EVFE1 | SAA7134_MAIN_CTRL_EVFE2 | SAA7134_MAIN_CTRL_ESFE | - SAA7134_MAIN_CTRL_EBADC | SAA7134_MAIN_CTRL_EBDAC); /* enable peripheral devices */ @@ -990,6 +989,22 @@ static int __devinit saa7134_initdev(str msleep(100); saa7134_i2c_register(dev); + /* Hac: if a card has variants, let's patch the data structures now */ + if (dev->board == SAA7134_BOARD_MD7134) { + u8 buf; + int ret; + struct i2c_msg msg = { .addr=0x08, .flags=I2C_M_RD, .buf=&buf, .len = 1}; + ret = i2c_transfer(&dev->i2c_adap, &msg, 1); + if (ret == 1) { + printk(KERN_INFO "%s: Board MD7134 has DVB-T\n", dev->name); + } else { + printk(KERN_INFO "%s: Board MD7134 is analog only\n", dev->name); + dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3; + saa7134_boards[SAA7134_BOARD_MD7134].tuner_type = TUNER_PHILIPS_FM1216ME_MK3; + saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&dev->tuner_type); + } + } + /* initialize hardware #2 */ saa7134_board_init2(dev); saa7134_hwinit2(dev); diff -uprNw video4linux.orig/saa7134-dvb.c video4linux/saa7134-dvb.c --- video4linux.orig/saa7134-dvb.c 2005-02-18 14:07:01.000000000 +0100 +++ video4linux/saa7134-dvb.c 2005-04-23 23:38:10.000000000 +0200 @@ -3,6 +3,9 @@ * * (c) 2004 Gerd Knorr <kraxel@xxxxxxxxxxx> [SuSE Labs] * + * Extended 3 / 2005 by Hartmut Hackmann to support various + * cards with the tda10046 DVB-T channel decoder + * * 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; either version 2 of the License, or @@ -141,44 +144,231 @@ static struct mt352_config pinnacle_300i /* ------------------------------------------------------------------ */ -static int medion_cardbus_init(struct dvb_frontend* fe) +static int philips_tu1216_pll_init(struct dvb_frontend *fe) { - /* anything to do here ??? */ + 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 medion_cardbus_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct saa7134_dev *dev = fe->dvb->priv; - struct v4l2_frequency f; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len = + sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36166000; + if (tuner_frequency < 87000000) + return -EINVAL; + else if (tuner_frequency < 130000000) + cp = 3; + else if (tuner_frequency < 160000000) + cp = 5; + else if (tuner_frequency < 200000000) + cp = 6; + else if (tuner_frequency < 290000000) + cp = 3; + else if (tuner_frequency < 420000000) + cp = 5; + else if (tuner_frequency < 480000000) + cp = 6; + else if (tuner_frequency < 620000000) + cp = 3; + else if (tuner_frequency < 830000000) + cp = 5; + else if (tuner_frequency < 895000000) + cp = 7; + else + return -EINVAL; + + // determine band + if (params->frequency < 49000000) + return -EINVAL; + else if (params->frequency < 161000000) + band = 1; + else if (params->frequency < 444000000) + band = 2; + else if (params->frequency < 861000000) + band = 4; + else + return -EINVAL; + + // setup PLL filter + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + filter = 0; + break; - /* - * this instructs tuner.o to set the frequency, the call will - * end up in tuner_command(), VIDIOC_S_FREQUENCY switch. - * tda9887.o will see that as well. - */ - f.tuner = 0; - f.type = V4L2_TUNER_DIGITAL_TV; - f.frequency = params->frequency / 1000 * 16 / 1000; - saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); + case BANDWIDTH_7_MHZ: + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate divisor + // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000; + + // setup tuner buffer + tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); return 0; } -static int fe_request_firmware(struct dvb_frontend* fe, +static int philips_tu1216_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char* name) { struct saa7134_dev *dev = fe->dvb->priv; return request_firmware(fw, name, &dev->pci->dev); } -struct tda1004x_config medion_cardbus = { - .demod_address = 0x08, /* not sure this is correct */ - .invert = 0, +static struct tda1004x_config philips_tu1216_config = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 1, + .xtal_freq = TDA10046_XTAL_4M, + .agc_config = TDA10046_AGC_DEFAULT, + .if_freq = TDA10046_FREQ_DEFAULT, + .pll_init = philips_tu1216_pll_init, + .pll_set = philips_tu1216_pll_set, + .request_firmware = philips_tu1216_request_firmware, +}; + +/* ------------------------------------------------------------------ */ + + +static int philips_fmd1216_pll_init(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + // this message is to set up ATC and ALC + static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; + struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; + + if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + msleep(1); + + return 0; +} + +static int philips_fmd1216_pll_set(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 = 0x61,.flags = 0,.buf = tuner_buf,.len = + sizeof(tuner_buf) }; + int tuner_frequency = 0; + int divider = 0; + u8 band, mode, cp; + + // determine charge pump + tuner_frequency = params->frequency + 36130000; + if (tuner_frequency < 87000000) + return -EINVAL; + // low band + else if (tuner_frequency < 180000000) { + band = 1; + mode = 7; + cp = 0; + } else if (tuner_frequency < 195000000) { + band = 1; + mode = 6; + cp = 1; + // mid band + } else if (tuner_frequency < 366000000) { + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { + band = 10; + } else { + band = 2; + } + mode = 7; + cp = 0; + } else if (tuner_frequency < 478000000) { + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { + band = 10; + } else { + band = 2; + } + mode = 6; + cp = 1; + // high band + } else if (tuner_frequency < 662000000) { + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { + band = 12; + } else { + band = 4; + } + mode = 7; + cp = 0; + } else if (tuner_frequency < 840000000) { + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { + band = 12; + } else { + band = 4; + } + mode = 6; + cp = 1; + } else { + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { + band = 12; + } else { + band = 4; + } + mode = 7; + cp = 1; + + } + // calculate divisor + // ((36166000 + Finput) / 166666) rounded! + divider = (tuner_frequency + 83333) / 166667; + + // setup tuner buffer + tuner_buf[0] = (divider >> 8) & 0x7f; + tuner_buf[1] = divider & 0xff; + tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4; + tuner_buf[3] = 0x40 | band; + + if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + return 0; +} + + +static struct tda1004x_config medion_cardbus = { + .demod_address = 0x08, + .invert = 1, .invert_oclk = 0, - .pll_init = medion_cardbus_init, - .pll_set = medion_cardbus_pll_set, - .request_firmware = fe_request_firmware, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_IFO_AUTO_NEG, + .if_freq = TDA10046_FREQ_3613, + .pll_init = philips_fmd1216_pll_init, + .pll_set = philips_fmd1216_pll_set, + .request_firmware = NULL, }; /* ------------------------------------------------------------------ */ @@ -205,9 +395,10 @@ static int dvb_init(struct saa7134_dev * case SAA7134_BOARD_MD7134: dev->dvb.frontend = tda10046_attach(&medion_cardbus, &dev->i2c_adap); - if (NULL == dev->dvb.frontend) - printk("%s: Hmm, looks like this is the old MD7134 " - "version without DVB-T support\n",dev->name); + break; + case SAA7134_BOARD_PHILIPS_TOUGH: + dev->dvb.frontend = tda10046_attach(&philips_tu1216_config, + &dev->i2c_adap); break; default: printk("%s: Huh? unknown DVB card?\n",dev->name); @@ -227,8 +418,6 @@ static int dvb_fini(struct saa7134_dev * { static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE; - printk("%s: %s\n",dev->name,__FUNCTION__); - switch (dev->board) { case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: /* otherwise we don't detect the tuner on next insmod */ diff -uprNw video4linux.orig/saa7134-ts.c video4linux/saa7134-ts.c --- video4linux.orig/saa7134-ts.c 2005-02-03 11:27:01.000000000 +0100 +++ video4linux/saa7134-ts.c 2005-04-18 00:14:13.000000000 +0200 @@ -221,10 +221,10 @@ void saa7134_irq_ts_done(struct saa7134_ if (dev->ts_q.curr) { field = dev->ts_q.curr->vb.field; if (field == V4L2_FIELD_TOP) { - if ((status & 0x100000) != 0x000000) + if ((status & 0x100000) != 0x100000) goto done; } else { - if ((status & 0x100000) != 0x100000) + if ((status & 0x100000) != 0x000000) goto done; } saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE); diff -uprNw video4linux.orig/saa7134-video.c video4linux/saa7134-video.c --- video4linux.orig/saa7134-video.c 2005-02-15 17:07:00.000000000 +0100 +++ video4linux/saa7134-video.c 2005-04-28 00:51:11.000000000 +0200 @@ -1218,7 +1218,6 @@ static int video_open(struct inode *inod struct list_head *list; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int radio = 0; - list_for_each(list,&saa7134_devlist) { h = list_entry(list, struct saa7134_dev, devlist); if (h->video_dev && (h->video_dev->minor == minor)) @@ -1235,6 +1234,12 @@ static int video_open(struct inode *inod if (NULL == dev) return -ENODEV; + if (dev->board == SAA7134_BOARD_MD7134) { + /* initialize the tuner for analog mode, necessary for some hybrid tuners. + the tda9886 will be invisible in digital mode Hac: 04.05*/ + saa7134_i2c_call_clients(dev, TUNER_SET_ANALOG, NULL); + } + dprintk("open minor=%d radio=%d type=%s\n",minor,radio, v4l2_type_names[type]); @@ -1270,6 +1275,8 @@ static int video_open(struct inode *inod if (fh->radio) { /* switch to radio mode */ saa7134_tvaudio_setinput(dev,&card(dev).radio); + if(dev->board == SAA7134_BOARD_MD7134) + saa7134_i2c_call_clients(dev,AUDC_CONFIG_PHILIPS_FMD, NULL); saa7134_i2c_call_clients(dev,AUDC_SET_RADIO,NULL); } else { /* switch to video/vbi mode */ @@ -1377,6 +1384,12 @@ static int video_release(struct inode *i res_free(dev,fh,RESOURCE_VBI); } + /* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/ + saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0); + saa_andorb(SAA7134_OFMT_VIDEO_B, 0x1f, 0); + saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); + saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); + /* free stuff */ videobuf_mmap_free(&fh->cap); videobuf_mmap_free(&fh->vbi); diff -uprNw video4linux.orig/saa7134.h video4linux/saa7134.h --- video4linux.orig/saa7134.h 2005-03-07 13:07:00.000000000 +0100 +++ video4linux/saa7134.h 2005-03-24 02:09:32.000000000 +0100 @@ -197,6 +197,7 @@ struct saa7134_format { #define SAA7135_BOARD_ASUSTeK_TVFM7135 53 #define SAA7134_BOARD_FLYTVPLATINUM_FM 54 #define SAA7134_BOARD_FLYDVBTDUO 55 +#define SAA7134_BOARD_PHILIPS_TOUGH 56 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff -uprNw video4linux.orig/tda9887.c video4linux/tda9887.c --- video4linux.orig/tda9887.c 2005-02-04 13:07:00.000000000 +0100 +++ video4linux/tda9887.c 2005-04-28 00:11:34.000000000 +0200 @@ -61,6 +61,7 @@ struct tda9887 { unsigned int radio; unsigned int config; unsigned int pinnacle_id; + unsigned int philips_fmd_id; unsigned int using_v4l2; }; @@ -231,6 +232,13 @@ static struct tvnorm radio = { cRadioIF_38_90 ), }; +static struct tvnorm radio_philips_fmd = { + .name = "radio", + .b = ( cFmRadio | cQSS | cAutoMuteFmActive), + .c = ( cAudioGain6 | cDeemphasis50 | cDeemphasisOFF | 0x1f), + .e = ( cGating_36 | cTunerGainLow | cRadioIF_38_90 | cAudioIF_5_5 ), +}; + /* ---------------------------------------------------------------------- */ static void dump_read_message(unsigned char *buf) @@ -363,6 +371,9 @@ static int tda9887_set_tvnorm(struct tda int i; if (t->radio) { + if (t-> philips_fmd_id) + norm = &radio_philips_fmd; + else norm = &radio; } else { for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { @@ -559,6 +570,10 @@ static int tda9887_configure(struct tda9 if (UNSET != t->pinnacle_id) { tda9887_set_pinnacle(t,buf); } + if ((t->radio) && (t->philips_fmd_id)) { + buf[1] &= ~cOutputPort1Inactive; + buf[1] &= ~cOutputPort2Inactive; + } tda9887_set_config(t,buf); tda9887_set_insmod(t,buf); @@ -609,6 +624,7 @@ static int tda9887_attach(struct i2c_ada t->client = client_template; t->std = 0; t->pinnacle_id = UNSET; + t->philips_fmd_id = 0; i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -675,6 +691,9 @@ tda9887_command(struct i2c_client *clien tda9887_configure(t); break; } + case AUDC_CONFIG_PHILIPS_FMD: + t->philips_fmd_id = 1; + break; case TDA9887_SET_CONFIG: { int *i = arg; diff -uprNw video4linux.orig/tuner-core.c video4linux/tuner-core.c --- video4linux.orig/tuner-core.c 2005-02-15 17:07:00.000000000 +0100 +++ video4linux/tuner-core.c 2005-04-26 00:59:10.000000000 +0200 @@ -149,8 +149,8 @@ static void set_type(struct i2c_client * t->type = type; return; } - if (t->initialized) - /* run only once */ + if ((t->initialized) && (t->type == type)) + /* run only once except type change Hac 04/05*/ return; t->initialized = 1; @@ -289,7 +289,9 @@ tuner_command(struct i2c_client *client, break; } break; - + case TUNER_SET_ANALOG: + default_tuner_init2(client); + break; /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ diff -uprNw video4linux.orig/tuner-simple.c video4linux/tuner-simple.c --- video4linux.orig/tuner-simple.c 2005-03-08 10:07:01.000000000 +0100 +++ video4linux/tuner-simple.c 2005-04-26 01:21:12.000000000 +0200 @@ -212,6 +212,8 @@ static struct tunertype tuners[] = { 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, { "Philips FQ1236A MK4", Philips, NTSC, 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, + { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, + 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); @@ -427,6 +429,7 @@ static void default_set_radio_freq(struc switch (t->type) { case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FMD1216ME_MK3: buffer[3] = 0x19; break; case TUNER_PHILIPS_FM1256_IH3: @@ -463,9 +466,29 @@ int default_tuner_init(struct i2c_client t->radio_freq = default_set_radio_freq; t->has_signal = tuner_signal; t->is_stereo = tuner_stereo; + default_tuner_init2(c); return 0; } +void default_tuner_init2(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + unsigned char buffer[4]; + + switch (t->type) { + case TUNER_PHILIPS_FMD1216ME_MK3: + buffer[0] = 0x0b; + buffer[1] = 0xdc; + buffer[2] = 0x9c; + buffer[3] = 0x60; + i2c_master_send(c,buffer,4); + mdelay(1); + buffer[2] = 0x86; + buffer[3] = 0x54; + i2c_master_send(c,buffer,4); + break; + } +} /* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- diff -uprNw video4linux.orig/tuner.h video4linux/tuner.h --- video4linux.orig/tuner.h 2005-03-08 10:07:01.000000000 +0100 +++ video4linux/tuner.h 2005-04-26 01:04:53.000000000 +0200 @@ -97,6 +97,7 @@ #define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ #define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ +#define TUNER_PHILIPS_FMD1216ME_MK3 58 #define NOTUNER 0 #define PAL 1 /* PAL_BG */ @@ -121,6 +122,7 @@ #define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ #define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ +#define TUNER_SET_ANALOG _IO('t',6) /* reinitialize analog tuner */ #define TDA9887_SET_CONFIG _IOW('t',5,int) /* tv card specific */ @@ -178,6 +180,7 @@ extern unsigned const int tuner_count; extern int microtune_init(struct i2c_client *c); extern int tda8290_init(struct i2c_client *c); extern int default_tuner_init(struct i2c_client *c); +extern void default_tuner_init2(struct i2c_client *c); #define tuner_warn(fmt, arg...) \ dev_printk(KERN_WARNING , &t->i2c.dev , fmt , ## arg)