diff -r c314ec17335a linux/drivers/media/video/cx88/cx88-cards.c --- a/linux/drivers/media/video/cx88/cx88-cards.c Thu Jun 07 09:42:20 2007 -0300 +++ b/linux/drivers/media/video/cx88/cx88-cards.c Thu Jun 07 18:53:47 2007 +0200 @@ -1388,6 +1388,19 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0x07fa, }}, }, + [CX88_BOARD_SAMSUNG_SMT_7020] = { + .name = "Samsung SMT 7020 DVB-S", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, + .mpeg = CX88_MPEG_DVB, + }, + }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1698,6 +1711,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1421, .subdevice = 0x0390, .card = CX88_BOARD_ADSTECH_PTV_390, + },{ + .subvendor = 0x18ac, + .subdevice = 0xdc00, + .card = CX88_BOARD_SAMSUNG_SMT_7020, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1998,6 +2015,12 @@ void cx88_card_setup(struct cx88_core *c core->name, i); } break; + case CX88_BOARD_SAMSUNG_SMT_7020: + cx_set(MO_GP0_IO, 0x008989FF); + //cx_set(MO_GP3_IO, 0x00000000); + printk("!!Samsung RESET done.\n"); + break; + } if (cx88_boards[core->board].radio.type == CX88_RADIO) core->has_radio = 1; diff -r c314ec17335a linux/drivers/media/video/cx88/cx88-dvb.c --- a/linux/drivers/media/video/cx88/cx88-dvb.c Thu Jun 07 09:42:20 2007 -0300 +++ b/linux/drivers/media/video/cx88/cx88-dvb.c Thu Jun 07 18:49:06 2007 +0200 @@ -43,6 +43,7 @@ #include "lgdt330x.h" #include "nxt200x.h" #include "cx24123.h" +#include "stv0299.h" #include "isl6421.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); @@ -372,6 +373,187 @@ static struct cx24123_config kworld_dvbs .lnb_polarity = 1, }; + + +static u8 samsung_smt_7020_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7D, + 0x05, 0x0F, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x60, + + 0x0A, 0xC2, + 0x0B, 0x00, + + 0x0C, 0x01, + + 0x0D, 0x81, + 0x0E, 0x44, + 0x0F, 0x09, + 0x10, 0x3C, + 0x11, 0x84, + 0x12, 0xDA, + 0x13, 0x99, + 0x14, 0x8D, + 0x15, 0xCE, + 0x16, 0xE8, + 0x17, 0x43, + 0x18, 0x1C, + 0x19, 0x1B, + 0x1A, 0x1D, + + 0x1C, 0x12, + + 0x1D, 0x00, + 0x1E, 0x00, + + 0x1F, 0x00, + 0x20, 0x00, + 0x21, 0x00, + + 0x22, 0x00, + 0x23, 0x00, + + 0x28, 0x02, + + 0x29, 0x28, + 0x2A, 0x14, + 0x2B, 0x0F, + 0x2C, 0x09, + 0x2D, 0x05, + + 0x31, 0x1F, + 0x32, 0x19, + 0x33, 0xFC, + 0x34, 0x13, + 0xff, 0xff, +}; + + +static int samsung_smt_7020_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) +{ + struct cx8802_dev *dev= fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + +// printk("!!Samsung samsung_tuner_set_params() freq: %d\n",params->frequency); + + div = params->frequency / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x84; /* 0xC4 */ + buf[3] = 0x00; + + if (params->frequency < 1500000) buf[3] |= 0x10; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if ((i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + return -EIO; + } + +// printk("!!Samsung samsung_tuner_set_params() OK.\n"); + return 0; +} + +static int samsung_smt_7020_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + + cx_set(MO_GP0_IO, 0x0800); + + switch (tone) { + case SEC_TONE_ON: +// printk("!!Samsung samsung_set_tone() ON OK.\n"); + cx_set(MO_GP0_IO, 0x08); + break; + case SEC_TONE_OFF: +// printk("!!Samsung samsung_set_tone() OFF OK.\n"); + cx_clear(MO_GP0_IO, 0x08); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + + u8 data; + //struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv; + struct i2c_msg msg = { .addr = 8, .flags = 0, + .buf = &data, + .len = sizeof(data) }; + + cx_set(MO_GP0_IO, 0x8000); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + data = ISL6421_EN1; + cx_clear(MO_GP0_IO, 0x80); +// printk("!!Samsung samsung_set_voltage() 13V OK.\n"); + break; + case SEC_VOLTAGE_18: + data = ISL6421_EN1; + cx_set(MO_GP0_IO, 0x80); +// printk("!!Samsung samsung_set_voltage() 18V OK.\n"); + break; + default: + return -EINVAL; + }; + + return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; +} + +static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + +// printk("!!Samsung samsung_tuner_set_symbol_rate() srate:%d ratio:%d\n",srate,ratio); + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; +} + + +static struct stv0299_config samsung_stv0299_config = { + .demod_address = 0x68, + .inittab = samsung_smt_7020_inittab, + .mclk = 88000000UL, + .invert = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_LK, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, +}; + static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ @@ -625,6 +807,34 @@ static int dvb_register(struct cx8802_de dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; + case CX88_BOARD_SAMSUNG_SMT_7020: + dev->ts_gen_cntrl = 0x08; + { + struct cx88_core *core = dev->core; + + cx_set(MO_GP0_IO, 0x0101); + + cx_clear(MO_GP0_IO, 0x01); + mdelay(100); + cx_set(MO_GP0_IO, 0x01); + mdelay(200); + + //cx_clear(MO_GP0_IO, 0x0088); + + dev->dvb.frontend = dvb_attach(stv0299_attach, + &samsung_stv0299_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.set_params = samsung_smt_7020_tuner_set_params; + dev->dvb.frontend->tuner_priv = &dev->core->i2c_adap; + dev->dvb.frontend->ops.set_voltage = samsung_smt_7020_set_voltage; + dev->dvb.frontend->ops.set_tone = samsung_smt_7020_set_tone; + +// printk("!!Samsung INIT done.\n"); + } + } + break; + default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); diff -r c314ec17335a linux/drivers/media/video/cx88/cx88-mpeg.c --- a/linux/drivers/media/video/cx88/cx88-mpeg.c Thu Jun 07 09:42:20 2007 -0300 +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c Thu Jun 07 18:49:06 2007 +0200 @@ -135,6 +135,9 @@ static int cx8802_start_dma(struct cx880 case CX88_BOARD_PCHDTV_HD5500: cx_write(TS_SOP_STAT, 1<<13); break; + case CX88_BOARD_SAMSUNG_SMT_7020: + cx_write(TS_SOP_STAT, 0x00); + break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ diff -r c314ec17335a linux/drivers/media/video/cx88/cx88.h --- a/linux/drivers/media/video/cx88/cx88.h Thu Jun 07 09:42:20 2007 -0300 +++ b/linux/drivers/media/video/cx88/cx88.h Thu Jun 07 18:54:14 2007 +0200 @@ -213,6 +213,7 @@ extern struct sram_channel cx88_sram_cha #define CX88_BOARD_TE_DTV_250_OEM_SWANN 55 #define CX88_BOARD_HAUPPAUGE_HVR1300 56 #define CX88_BOARD_ADSTECH_PTV_390 57 +#define CX88_BOARD_SAMSUNG_SMT_7020 58 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1,