From e93854da880d6dc357c00625d8371b6a926fd19b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 14 Dec 2009 00:16:55 -0300 Subject: V4L/DVB (13634): ir-core: allow passing IR device parameters to ir-core Adds an structure to ir_input_register to contain IR device characteristics, like supported protocols and a callback to handle protocol event changes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 4 ++-- drivers/media/dvb/mantis/mantis_input.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index f0f483ac8b8..414d3b2444a 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -578,7 +578,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) { struct input_dev *input_dev; struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; - int ir_type = IR_TYPE_OTHER; + enum ir_type ir_type = IR_TYPE_OTHER; int err = -ENOMEM; input_dev = input_allocate_device(); @@ -611,7 +611,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) INIT_WORK(&dm1105->ir.work, dm1105_emit_key); - err = ir_input_register(input_dev, ir_codes); + err = ir_input_register(input_dev, ir_codes, NULL); return err; } diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 6a9df779441..4675a3b53c7 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -126,7 +126,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->id.version = 1; rc->dev = mantis->pdev->dev; - err = ir_input_register(rc, &ir_mantis); + err = ir_input_register(rc, &ir_mantis, NULL); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); input_free_device(rc); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 9782e059373..49c2a817a06 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -254,7 +254,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) budget_ci->ir.timer_keyup.function = msp430_ir_keyup; budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; budget_ci->ir.last_raw = 0xffff; /* An impossible value */ - error = ir_input_register(input_dev, ir_codes); + error = ir_input_register(input_dev, ir_codes, NULL); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); return error; -- cgit v1.2.3 From 971e8298dee4835fc2dfbd207a9786702aa01666 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 14 Dec 2009 13:53:37 -0300 Subject: V4L/DVB (13680): ir: use unsigned long instead of enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When preparing the linux-next patches, I got those errors: include/media/ir-core.h:29: warning: left shift count >= width of type In file included from include/media/ir-common.h:29, from drivers/media/video/ir-kbd-i2c.c:50: drivers/media/video/ir-kbd-i2c.c: In function ‘ir_probe’: drivers/media/video/ir-kbd-i2c.c:324: warning: left shift count >= width of type Unfortunately, enum is 32 bits on i386. As we define IR_TYPE_OTHER as 1<<63, it won't work on non 64 bits arch. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 414d3b2444a..aadf803c261 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -578,7 +578,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) { struct input_dev *input_dev; struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; - enum ir_type ir_type = IR_TYPE_OTHER; + u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; input_dev = input_allocate_device(); -- cgit v1.2.3 From cd79d33e168dba0d7de32c5bf010e20cff184b2a Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 14 Dec 2009 20:24:56 -0300 Subject: V4L/DVB (13818): Add Prof 7500 DVB-S2 USB card The card based on stv0903 demod, stb6100 tuner. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 94 ++++++++++++++++++++++++++---- drivers/media/dvb/frontends/stv0900.h | 2 + drivers/media/dvb/frontends/stv0900_core.c | 87 ++++++++++++++++++++++++++- drivers/media/dvb/frontends/stv0900_priv.h | 11 ++++ drivers/media/dvb/frontends/stv0900_reg.h | 6 ++ drivers/media/dvb/frontends/stv0900_sw.c | 44 +++++++++++--- 6 files changed, 226 insertions(+), 18 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 64132c0cf80..83a35524a82 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -1,6 +1,7 @@ /* DVB USB framework compliant Linux driver for the * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, -* TeVii S600, S630, S650 Cards +* TeVii S600, S630, S650, +* Prof 1100, 7500 Cards * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) * * This program is free software; you can redistribute it and/or modify it @@ -469,6 +470,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct usb_device *udev = d->udev; int ret = 0; int len, i, j; @@ -488,8 +490,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], } case (DW2102_VOLTAGE_CTRL): { u8 obuf[2]; + + obuf[0] = 1; + obuf[1] = msg[j].buf[1];/* off-on */ + ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, + obuf, 2, DW210X_WRITE_MSG); obuf[0] = 3; - obuf[1] = msg[j].buf[0]; + obuf[1] = msg[j].buf[0];/* 13v-18v */ ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); break; @@ -527,6 +534,17 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i += 16; len -= 16; } while (len > 0); + } else if ((udev->descriptor.idProduct == 0x7500) + && (j < (num - 1))) { + /* write register addr before read */ + u8 obuf[msg[j].len + 2]; + obuf[0] = msg[j + 1].len; + obuf[1] = (msg[j].addr << 1); + memcpy(obuf + 2, msg[j].buf, msg[j].len); + ret = dw210x_op_rw(d->udev, 0x92, 0, 0, + obuf, msg[j].len + 2, + DW210X_WRITE_MSG); + break; } else { /* write registers */ u8 obuf[msg[j].len + 2]; @@ -651,18 +669,25 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - static u8 command_13v[1] = {0x00}; - static u8 command_18v[1] = {0x01}; - struct i2c_msg msg[] = { - {.addr = DW2102_VOLTAGE_CTRL, .flags = 0, - .buf = command_13v, .len = 1}, + static u8 command_13v[] = {0x00, 0x01}; + static u8 command_18v[] = {0x01, 0x01}; + static u8 command_off[] = {0x00, 0x00}; + struct i2c_msg msg = { + .addr = DW2102_VOLTAGE_CTRL, + .flags = 0, + .buf = command_off, + .len = 2, }; struct dvb_usb_adapter *udev_adap = (struct dvb_usb_adapter *)(fe->dvb->priv); if (voltage == SEC_VOLTAGE_18) - msg[0].buf = command_18v; - i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); + msg.buf = command_18v; + else if (voltage == SEC_VOLTAGE_13) + msg.buf = command_13v; + + i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); + return 0; } @@ -735,6 +760,18 @@ static struct stv6110_config dw2104_stv6110_config = { .clk_div = 1, }; +static struct stv0900_config prof_7500_stv0900_config = { + .demod_address = 0x6a, + .demod_mode = 0, + .xtal = 27000000, + .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ + .diseqc_mode = 2,/* 2/3 PWM */ + .tun1_maddress = 0,/* 0x60 */ + .tun1_adc = 0,/* 2 Vpp */ + .path1_mode = 3, + .tun1_type = 3, +}; + static int dw2104_frontend_attach(struct dvb_usb_adapter *d) { struct dvb_tuner_ops *tuner_ops = NULL; @@ -882,6 +919,19 @@ static int s6x0_frontend_attach(struct dvb_usb_adapter *d) return -EIO; } +static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) +{ + d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config, + &d->dev->i2c_adap, 0); + if (d->fe == NULL) + return -EIO; + d->fe->ops.set_voltage = dw210x_set_voltage; + + info("Attached STV0900+STB6100A!\n"); + + return 0; +} + static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) { dvb_attach(dvb_pll_attach, adap->fe, 0x60, @@ -1073,6 +1123,7 @@ static struct usb_device_id dw2102_table[] = { {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, + {USB_DEVICE(0x3034, 0x7500)}, { } }; @@ -1387,9 +1438,30 @@ static struct dvb_usb_device_properties s6x0_properties = { } }; +struct dvb_usb_device_properties *p7500; +static struct dvb_usb_device_description d7500 = { + "Prof 7500 USB DVB-S2", + {&dw2102_table[9], NULL}, + {NULL}, +}; + static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { + + p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); + if (!p7500) + return -ENOMEM; + /* copy default structure */ + memcpy(p7500, &s6x0_properties, + sizeof(struct dvb_usb_device_properties)); + /* fill only different fields */ + p7500->firmware = "dvb-usb-p7500.fw"; + p7500->devices[0] = d7500; + p7500->rc_key_map = tbs_rc_keys; + p7500->rc_key_map_size = ARRAY_SIZE(tbs_rc_keys); + p7500->adapter->frontend_attach = prof_7500_frontend_attach; + if (0 == dvb_usb_device_init(intf, &dw2102_properties, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &dw2104_properties, @@ -1397,6 +1469,8 @@ static int dw2102_probe(struct usb_interface *intf, 0 == dvb_usb_device_init(intf, &dw3101_properties, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &s6x0_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, p7500, THIS_MODULE, NULL, adapter_nr)) return 0; @@ -1431,6 +1505,6 @@ MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," " DVB-C 3101 USB2.0," " TeVii S600, S630, S650, S660 USB2.0," - " Prof 1100 USB2.0 devices"); + " Prof 1100, 7500 USB2.0 devices"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h index 29c3fa85c22..e3e35d1ce83 100644 --- a/drivers/media/dvb/frontends/stv0900.h +++ b/drivers/media/dvb/frontends/stv0900.h @@ -49,6 +49,8 @@ struct stv0900_config { u8 tun2_maddress; u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ u8 tun2_adc; + u8 tun1_type;/* for now 3 for stb6100 auto, else - software */ + u8 tun2_type; /* Set device param to start dma */ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); }; diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 8762c86044a..115dc01c223 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -567,6 +567,46 @@ void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) } } +u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod) +{ + u32 freq, round; + /* Formulat : + Tuner_Frequency(MHz) = Regs / 64 + Tuner_granularity(MHz) = Regs / 2048 + real_Tuner_Frequency = Tuner_Frequency(MHz) - Tuner_granularity(MHz) + */ + freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) + + (stv0900_get_bits(intp, TUN_RFFREQ1) << 2) + + stv0900_get_bits(intp, TUN_RFFREQ0); + + freq = (freq * 1000) / 64; + + round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) + + stv0900_get_bits(intp, TUN_RFRESTE0); + + round = (round * 1000) / 2048; + + return freq + round; +} + +void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency, + u32 Bandwidth, int demod) +{ + u32 tunerFrequency; + /* Formulat: + Tuner_frequency_reg= Frequency(MHz)*64 + */ + tunerFrequency = (Frequency * 64) / 1000; + + stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10)); + stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff); + stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03)); + /* Low Pass Filter = BW /2 (MHz)*/ + stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000); + /* Tuner Write trig */ + stv0900_write_reg(intp, TNRLD, 1); +} + static s32 stv0900_get_rf_level(struct stv0900_internal *intp, const struct stv0900_table *lookup, enum fe_stv0900_demod_num demod) @@ -1329,7 +1369,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, enum fe_stv0900_error error = STV0900_NO_ERROR; enum fe_stv0900_error demodError = STV0900_NO_ERROR; struct stv0900_internal *intp = NULL; - int selosci, i; struct stv0900_inode *temp_int = find_inode(state->i2c_adap, @@ -1404,6 +1443,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); } + intp->tuner_type[0] = p_init->tuner1_type; + intp->tuner_type[1] = p_init->tuner2_type; + /* tuner init */ + switch (p_init->tuner1_type) { + case 3: /*FE_AUTO_STB6100:*/ + stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c); + stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86); + stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18); + stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */ + stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05); + stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17); + stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f); + stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0); + stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3); + break; + /* case FE_SW_TUNER: */ + default: + stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6); + break; + } + stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); switch (p_init->tuner1_adc) { case 1: @@ -1413,6 +1473,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, break; } + stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */ + + /* tuner init */ + switch (p_init->tuner2_type) { + case 3: /*FE_AUTO_STB6100:*/ + stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c); + stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86); + stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18); + stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */ + stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05); + stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17); + stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f); + stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0); + stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3); + break; + /* case FE_SW_TUNER: */ + default: + stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6); + break; + } + stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); switch (p_init->tuner2_adc) { case 1: @@ -1422,6 +1503,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, break; } + stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */ + stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv); stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv); stv0900_set_mclk(intp, 135000000); @@ -1824,10 +1907,12 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, init_params.tun1_maddress = config->tun1_maddress; init_params.tun1_iq_inv = STV0900_IQ_NORMAL; init_params.tuner1_adc = config->tun1_adc; + init_params.tuner1_type = config->tun1_type; init_params.path2_ts_clock = config->path2_mode; init_params.ts_config = config->ts_config_regs; init_params.tun2_maddress = config->tun2_maddress; init_params.tuner2_adc = config->tun2_adc; + init_params.tuner2_type = config->tun2_type; init_params.tun2_iq_inv = STV0900_IQ_SWAPPED; err_stv0900 = stv0900_init_internal(&state->frontend, diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h index d8ba8a984ab..b62b0f0a4fe 100644 --- a/drivers/media/dvb/frontends/stv0900_priv.h +++ b/drivers/media/dvb/frontends/stv0900_priv.h @@ -247,6 +247,7 @@ struct stv0900_init_params{ u8 tun1_maddress; int tuner1_adc; + int tuner1_type; /* IQ from the tuner1 to the demod */ enum stv0900_iq_inversion tun1_iq_inv; @@ -254,6 +255,7 @@ struct stv0900_init_params{ u8 tun2_maddress; int tuner2_adc; + int tuner2_type; /* IQ from the tuner2 to the demod */ enum stv0900_iq_inversion tun2_iq_inv; @@ -309,6 +311,8 @@ struct stv0900_internal{ s32 bw[2]; s32 symbol_rate[2]; s32 srch_range[2]; + /* for software/auto tuner */ + int tuner_type[2]; /* algorithm for search Blind, Cold or Warm*/ enum fe_stv0900_search_algo srch_algo[2]; @@ -394,4 +398,11 @@ extern enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, enum fe_stv0900_demod_num demod); +extern u32 +stv0900_get_freq_auto(struct stv0900_internal *intp, int demod); + +extern void +stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency, + u32 Bandwidth, int demod); + #endif diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h index 7b8edf192e9..731afe93a82 100644 --- a/drivers/media/dvb/frontends/stv0900_reg.h +++ b/drivers/media/dvb/frontends/stv0900_reg.h @@ -3174,17 +3174,21 @@ extern s32 shiftx(s32 x, int demod, s32 shift); #define R0900_P1_TNRRF1 0xf4e9 #define TNRRF1 REGx(R0900_P1_TNRRF1) #define F0900_P1_TUN_RFFREQ2 0xf4e900ff +#define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2) /*P1_TNRRF0*/ #define R0900_P1_TNRRF0 0xf4ea #define TNRRF0 REGx(R0900_P1_TNRRF0) #define F0900_P1_TUN_RFFREQ1 0xf4ea00ff +#define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1) /*P1_TNRBW*/ #define R0900_P1_TNRBW 0xf4eb #define TNRBW REGx(R0900_P1_TNRBW) #define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 +#define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0) #define F0900_P1_TUN_BW 0xf4eb003f +#define TUN_BW FLDx(F0900_P1_TUN_BW) /*P1_TNRADJ*/ #define R0900_P1_TNRADJ 0xf4ec @@ -3234,11 +3238,13 @@ extern s32 shiftx(s32 x, int demod, s32 shift); #define F0900_P1_TUN_I2CLOCKED 0xf4f60010 #define F0900_P1_TUN_PROGDONE 0xf4f6000c #define F0900_P1_TUN_RFRESTE1 0xf4f60003 +#define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1) /*P1_TNRRESTE*/ #define R0900_P1_TNRRESTE 0xf4f7 #define TNRRESTE REGx(R0900_P1_TNRRESTE) #define F0900_P1_TUN_RFRESTE0 0xf4f700ff +#define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0) /*P1_SMAPCOEF7*/ #define R0900_P1_SMAPCOEF7 0xf500 diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index b8da87fa637..5161c288442 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c @@ -606,7 +606,12 @@ static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe, tuner_freq -= (current_step * currier_step); if (intp->chip_id <= 0x20) { - stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); + if (intp->tuner_type[d] == 3) + stv0900_set_tuner_auto(intp, tuner_freq, + intp->bw[d], demod); + else + stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); + stv0900_write_reg(intp, DMDISTATE, 0x1c); stv0900_write_reg(intp, CFRINIT1, 0); stv0900_write_reg(intp, CFRINIT0, 0); @@ -976,8 +981,16 @@ static void stv0900_track_optimization(struct dvb_frontend *fe) intp->rolloff) + 10000000; if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) { - if (intp->srch_algo[demod] != STV0900_WARM_START) - stv0900_set_bandwidth(fe, intp->bw[demod]); + if (intp->srch_algo[demod] != STV0900_WARM_START) { + if (intp->tuner_type[demod] == 3) + stv0900_set_tuner_auto(intp, + intp->freq[demod], + intp->bw[demod], + demod); + else + stv0900_set_bandwidth(fe, + intp->bw[demod]); + } } if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) || @@ -1202,7 +1215,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) } result->standard = stv0900_get_standard(fe, d); - result->frequency = stv0900_get_tuner_freq(fe); + if (intp->tuner_type[demod] == 3) + result->frequency = stv0900_get_freq_auto(intp, d); + else + result->frequency = stv0900_get_tuner_freq(fe); + offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000; result->frequency += offsetFreq; result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d); @@ -1239,7 +1256,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) || (intp->symbol_rate[d] < 10000000)) { offsetFreq = result->frequency - intp->freq[d]; - intp->freq[d] = stv0900_get_tuner_freq(fe); + if (intp->tuner_type[demod] == 3) + intp->freq[d] = stv0900_get_freq_auto(intp, d); + else + intp->freq[d] = stv0900_get_tuner_freq(fe); + if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) range = STV0900_RANGEOK; else if (ABS(offsetFreq) <= @@ -1481,7 +1502,12 @@ static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe) else tuner_freq -= (current_step * currier_step); - stv0900_set_tuner(fe, tuner_freq, intp->bw[demod]); + if (intp->tuner_type[demod] == 3) + stv0900_set_tuner_auto(intp, tuner_freq, + intp->bw[demod], demod); + else + stv0900_set_tuner(fe, tuner_freq, + intp->bw[demod]); } } @@ -1875,7 +1901,11 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) } - stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); + if (intp->tuner_type[demod] == 3) + stv0900_set_tuner_auto(intp, intp->freq[demod], + intp->bw[demod], demod); + else + stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), stv0900_get_bits(intp, AGCIQ_VALUE0)); -- cgit v1.2.3 From c245c75c41b9693bcbd6c95e25af324188b4dce1 Mon Sep 17 00:00:00 2001 From: David Wong Date: Sat, 28 Nov 2009 08:36:31 -0300 Subject: V4L/DVB (13838): atbm8830: use AGC setting from config Improves ATBM8830 reception by using per card AGC configuration rather than register default. Signed-off-by: David T. L. Wong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 3 +++ drivers/media/dvb/frontends/atbm8830.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 05fb28e9c69..a7b8405c291 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -1184,6 +1184,9 @@ static struct atbm8830_config mygica_d689_atbm8830_cfg = { .osc_clk_freq = 30400, /* in kHz */ .if_freq = 0, /* zero IF */ .zif_swap_iq = 1, + .agc_min = 0x2E, + .agc_max = 0x90, + .agc_hold_loop = 0, }; static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c index 59881a5944e..43aac2f85c2 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb/frontends/atbm8830.c @@ -170,6 +170,19 @@ static int is_locked(struct atbm_state *priv, u8 *locked) return 0; } +static int set_agc_config(struct atbm_state *priv, + u8 min, u8 max, u8 hold_loop) +{ + /* no effect if both min and max are zero */ + if (!min && !max) + return 0; + + atbm8830_write_reg(priv, REG_AGC_MIN, min); + atbm8830_write_reg(priv, REG_AGC_MAX, max); + atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop); + + return 0; +} static int set_static_channel_mode(struct atbm_state *priv) { @@ -227,6 +240,9 @@ static int atbm8830_init(struct dvb_frontend *fe) /*Set IF frequency*/ set_if_freq(priv, cfg->if_freq); + /*Set AGC Config*/ + set_agc_config(priv, cfg->agc_min, cfg->agc_max, + cfg->agc_hold_loop); /*Set static channel mode*/ set_static_channel_mode(priv); -- cgit v1.2.3 From 6b26fcea513095cd8a86cb376ad5a9df2fa8fe14 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Dec 2009 21:08:49 -0300 Subject: V4L/DVB (13839): smsdvb: add ISDB-T as DVB-T tuning support hack Activate ISDB-T mode using module option default_mode=6. hack: use 4 lower bits in frequency for segment number [mchehab@redhat.com: fix merge conflicts and CodingStyle] Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsdvb.c | 81 +++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 9 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 68bf9fbd8fe..ca952eb8d56 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -134,6 +134,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) break; case MSG_SMS_RF_TUNE_RES: + case MSG_SMS_ISDBT_TUNE_RES: complete(&client->tune_done); break; @@ -413,8 +414,8 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe, return 0; } -static int smsdvb_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *fep) +static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) { struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); @@ -470,6 +471,75 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, &client->tune_done); } +static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep, + u32 SegmentNumber) +{ + struct smsdvb_client_t *client = + container_of(fe, struct smsdvb_client_t, frontend); + + struct { + struct SmsMsgHdr_ST Msg; + u32 Data[4]; + } Msg; + + Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; + Msg.Msg.msgDstId = HIF_TASK; + Msg.Msg.msgFlags = 0; + Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ; + Msg.Msg.msgLength = sizeof(Msg); + Msg.Data[0] = fep->frequency; + Msg.Data[2] = 12000000; + Msg.Data[3] = SegmentNumber; + + sms_debug("freq %d band %d seg %d\n", + fep->frequency, fep->u.ofdm.bandwidth, SegmentNumber); + + switch (fep->u.ofdm.bandwidth) { + case BANDWIDTH_8_MHZ: + Msg.Data[1] = BW_ISDBT_3SEG; + break; + case BANDWIDTH_7_MHZ: + Msg.Data[1] = BW_ISDBT_3SEG; + break; + case BANDWIDTH_6_MHZ: + Msg.Data[1] = BW_ISDBT_1SEG; + break; + case BANDWIDTH_AUTO: + return -EOPNOTSUPP; + default: + return -EINVAL; + } + + return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), + &client->tune_done); +} + +static int smsdvb_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct smsdvb_client_t *client = + container_of(fe, struct smsdvb_client_t, frontend); + struct smscore_device_t *coredev = client->coredev; + + switch (smscore_get_device_mode(coredev)) { + case DEVICE_MODE_DVBT: + case DEVICE_MODE_DVBT_BDA: + return smsdvb_dvbt_set_frontend(fe, fep); + case DEVICE_MODE_ISDBT: + case DEVICE_MODE_ISDBT_BDA: + { + u32 segmentnum; + /* XXX: hack - use 4 lower bits in frequency for segment num */ + segmentnum = fep->frequency & 0x0000000f; + fep->frequency &= ~0x0000000f; + return smsdvb_isdbt_set_frontend(fe, fep, segmentnum); + } + default: + return -EINVAL; + } +} + static int smsdvb_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) { @@ -557,13 +627,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, /* device removal handled by onremove callback */ if (!arrival) return 0; - - if (smscore_get_device_mode(coredev) != DEVICE_MODE_DVBT_BDA) { - sms_err("SMS Device mode is not set for " - "DVB operation."); - return 0; - } - client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); if (!client) { sms_err("kmalloc() failed"); -- cgit v1.2.3 From dcb0c53331c0cfcac52d0921d3e3d06fdb2c417a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Dec 2009 21:09:52 -0300 Subject: V4L/DVB (13840): smsusb: Add ISDB-T firmware for Hauppauge WinTV-Nova-T-MiniStick Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/sms-cards.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index 1067b22eb0c..cff77e2eb55 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -62,6 +62,7 @@ static struct sms_board sms_boards[] = { [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { .name = "Hauppauge WinTV MiniStick", .type = SMS_NOVA_B0, + .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", .board_cfg.leds_power = 26, .board_cfg.led0 = 27, -- cgit v1.2.3 From 67ae1d26bd9291280874b49b9f388722682fe58f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 23 Dec 2009 10:07:16 -0300 Subject: V4L/DVB (13841): smsdvb: Make stats to work Siano series of patches seemed to cause a regression on reporting DTV statistics. Due to that, signal indication weren't received, preventing applications like scan to work. Tested with ISDB-T signals and got the same scan result as with a dib0700/dib8000 device. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smscoreapi.h | 4 +- drivers/media/dvb/siano/smsdvb.c | 73 +++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h index eec18aaf551..7393e2b5265 100644 --- a/drivers/media/dvb/siano/smscoreapi.h +++ b/drivers/media/dvb/siano/smscoreapi.h @@ -212,6 +212,8 @@ struct smscore_device_t { #define MSG_SMS_DAB_CHANNEL 607 #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 +#define MSG_SMS_GET_STATISTICS_RES 616 +#define MSG_SMS_GET_STATISTICS_REQ 615 #define MSG_SMS_HO_PER_SLICES_IND 630 #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 @@ -340,7 +342,7 @@ struct SmsFirmware_ST { /* Statistics information returned as response for * SmsHostApiGetStatistics_Req */ struct SMSHOSTLIB_STATISTICS_S { - u32 Reserved; /* Reserved */ + u8 Reserved[5]; /* Reserved */ /* Common parameters */ u32 IsRfLocked; /* 0 - not locked, 1 - locked */ diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index ca952eb8d56..6b85b4872f5 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -218,6 +218,39 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) is_status_update = true; break; } + case MSG_SMS_GET_STATISTICS_RES: { + struct SMSHOSTLIB_STATISTICS_S *p = + (struct SMSHOSTLIB_STATISTICS_S *)(phdr + 1); + struct RECEPTION_STATISTICS_S *pReceptionData = + &client->sms_stat_dvb.ReceptionData; + + sms_info("MSG_SMS_GET_STATISTICS_RES"); + + is_status_update = true; + pReceptionData->IsDemodLocked = p->IsDemodLocked; + if (!pReceptionData->IsDemodLocked) { + pReceptionData->SNR = 0; + pReceptionData->BER = 0; + pReceptionData->BERErrorCount = 0; + pReceptionData->InBandPwr = 0; + pReceptionData->ErrorTSPackets = 0; + + complete(&client->tune_done); + break; + } + + pReceptionData->SNR = p->SNR; + pReceptionData->BER = p->BER; + pReceptionData->BERErrorCount = p->BERErrorCount; + pReceptionData->InBandPwr = p->InBandPwr; + pReceptionData->ErrorTSPackets = p->ErrorTSPackets; + + complete(&client->tune_done); + break; + } + default: + sms_info("Unhandled message %d", phdr->msgType); + } smscore_putbuffer(client->coredev, cb); @@ -326,6 +359,20 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 0 : -ETIME; } +static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) +{ + int rc; + struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, + DVBT_BDA_CONTROL_MSG_ID, + HIF_TASK, + sizeof(struct SmsMsgHdr_ST), 0 }; + + rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), + &client->tune_done); + + return rc; +} + static inline int led_feedback(struct smsdvb_client_t *client) { if (client->fe_status & FE_HAS_LOCK) @@ -338,33 +385,43 @@ static inline int led_feedback(struct smsdvb_client_t *client) static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) { + int rc; struct smsdvb_client_t *client; client = container_of(fe, struct smsdvb_client_t, frontend); + rc = smsdvb_send_statistics_request(client); + *stat = client->fe_status; led_feedback(client); - return 0; + return rc; } static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) { + int rc; struct smsdvb_client_t *client; client = container_of(fe, struct smsdvb_client_t, frontend); + rc = smsdvb_send_statistics_request(client); + *ber = client->sms_stat_dvb.ReceptionData.BER; led_feedback(client); - return 0; + return rc; } static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { + int rc; + struct smsdvb_client_t *client; client = container_of(fe, struct smsdvb_client_t, frontend); + rc = smsdvb_send_statistics_request(client); + if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) *strength = 0; else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) @@ -376,31 +433,37 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) led_feedback(client); - return 0; + return rc; } static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) { + int rc; struct smsdvb_client_t *client; client = container_of(fe, struct smsdvb_client_t, frontend); + rc = smsdvb_send_statistics_request(client); + *snr = client->sms_stat_dvb.ReceptionData.SNR; led_feedback(client); - return 0; + return rc; } static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { + int rc; struct smsdvb_client_t *client; client = container_of(fe, struct smsdvb_client_t, frontend); + rc = smsdvb_send_statistics_request(client); + *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; led_feedback(client); - return 0; + return rc; } static int smsdvb_get_tune_settings(struct dvb_frontend *fe, -- cgit v1.2.3 From cf4fab720c66b15a6cf3abeb5a38acb841efedf4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 23 Dec 2009 11:28:46 -0300 Subject: V4L/DVB (13842): smsdvb: Convert it to use DVB API v5 (S2API) Based on a patch originally written by Michael Krufky for a preliminar S2API spec. The patch were ported to the S2API and had the ISDB-T API additions to honor the auto mode, while keep allowing manual tuning. Tested with both the original dvb-apps and the new dvb-apps-isdbt scan, that uses a different channel.conf and uses S2API with ISDB-T extensions. Thanks-to: Michael Krufky for his first version Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsdvb.c | 86 +++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 32 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 6b85b4872f5..3b786de2271 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -478,8 +478,9 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe, } static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *fep) + struct dvb_frontend_parameters *p) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); @@ -499,18 +500,26 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, Msg.Msg.msgFlags = 0; Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; Msg.Msg.msgLength = sizeof(Msg); - Msg.Data[0] = fep->frequency; + Msg.Data[0] = c->frequency; Msg.Data[2] = 12000000; - sms_debug("freq %d band %d", - fep->frequency, fep->u.ofdm.bandwidth); + sms_info("%s: freq %d band %d", __func__, c->frequency, + c->bandwidth_hz); - switch (fep->u.ofdm.bandwidth) { - case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break; - case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break; - case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break; - case BANDWIDTH_AUTO: return -EOPNOTSUPP; - default: return -EINVAL; + switch (c->bandwidth_hz / 1000) { + case 8: + Msg.Data[1] = BW_8_MHZ; + break; + case 7: + Msg.Data[1] = BW_7_MHZ; + break; + case 6: + Msg.Data[1] = BW_6_MHZ; + break; + case 0: + return -EOPNOTSUPP; + default: + return -EINVAL; } /* Disable LNA, if any. An error is returned if no LNA is present */ ret = sms_board_lna_control(client->coredev, 0); @@ -535,9 +544,9 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, } static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *fep, - u32 SegmentNumber) + struct dvb_frontend_parameters *p) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); @@ -551,29 +560,48 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe, Msg.Msg.msgFlags = 0; Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ; Msg.Msg.msgLength = sizeof(Msg); - Msg.Data[0] = fep->frequency; - Msg.Data[2] = 12000000; - Msg.Data[3] = SegmentNumber; - sms_debug("freq %d band %d seg %d\n", - fep->frequency, fep->u.ofdm.bandwidth, SegmentNumber); + if (c->isdbt_sb_segment_idx == -1) + c->isdbt_sb_segment_idx = 0; - switch (fep->u.ofdm.bandwidth) { - case BANDWIDTH_8_MHZ: + switch (c->isdbt_sb_segment_count) { + case 3: Msg.Data[1] = BW_ISDBT_3SEG; break; - case BANDWIDTH_7_MHZ: - Msg.Data[1] = BW_ISDBT_3SEG; - break; - case BANDWIDTH_6_MHZ: + case 1: Msg.Data[1] = BW_ISDBT_1SEG; break; - case BANDWIDTH_AUTO: - return -EOPNOTSUPP; + case 0: /* AUTO */ + switch (c->bandwidth_hz / 1000) { + case 8: + case 7: + c->isdbt_sb_segment_count = 3; + Msg.Data[1] = BW_ISDBT_3SEG; + break; + case 6: + c->isdbt_sb_segment_count = 1; + Msg.Data[1] = BW_ISDBT_1SEG; + break; + default: /* Assumes 6 MHZ bw */ + c->isdbt_sb_segment_count = 1; + c->bandwidth_hz = 6000; + Msg.Data[1] = BW_ISDBT_1SEG; + break; + } + break; default: + sms_info("Segment count %d not supported", c->isdbt_sb_segment_count); return -EINVAL; } + Msg.Data[0] = c->frequency; + Msg.Data[2] = 12000000; + Msg.Data[3] = c->isdbt_sb_segment_idx; + + sms_info("%s: freq %d segwidth %d segindex %d\n", __func__, + c->frequency, c->isdbt_sb_segment_count, + c->isdbt_sb_segment_idx); + return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); } @@ -591,13 +619,7 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, return smsdvb_dvbt_set_frontend(fe, fep); case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: - { - u32 segmentnum; - /* XXX: hack - use 4 lower bits in frequency for segment num */ - segmentnum = fep->frequency & 0x0000000f; - fep->frequency &= ~0x0000000f; - return smsdvb_isdbt_set_frontend(fe, fep, segmentnum); - } + return smsdvb_isdbt_set_frontend(fe, fep); default: return -EINVAL; } -- cgit v1.2.3 From 910ef763c1c3a6761aaa75bc5d086b45d4022e64 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Dec 2009 06:59:21 -0300 Subject: V4L/DVB (13843): dib8000: Properly report Delivery System as SYS_ISDBT Cc: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib8000.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 6f6fa29d9ea..2aa97dd6a8a 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -1999,6 +1999,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par struct dib8000_state *state = fe->demodulator_priv; int time, ret; + fe->dtv_property_cache.delivery_system = SYS_ISDBT; + dib8000_set_output_mode(state, OUTMODE_HIGH_Z); if (fe->ops.tuner_ops.set_params) -- cgit v1.2.3 From e85c97a050f07bc5d2fe1382b994f063614af75b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Dec 2009 07:17:03 -0300 Subject: V4L/DVB (13844): smsdvb: Properly report the Delivery System Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsdvb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 3b786de2271..36f886768aa 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -494,6 +494,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, client->fe_status = FE_HAS_SIGNAL; client->event_fe_state = -1; client->event_unc_state = -1; + fe->dtv_property_cache.delivery_system = SYS_DVBT; Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; Msg.Msg.msgDstId = HIF_TASK; @@ -555,6 +556,8 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe, u32 Data[4]; } Msg; + fe->dtv_property_cache.delivery_system = SYS_ISDBT; + Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; Msg.Msg.msgDstId = HIF_TASK; Msg.Msg.msgFlags = 0; -- cgit v1.2.3 From 643e15a0f44156fa05d163f202a9dffb264d2078 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Dec 2009 07:29:06 -0300 Subject: V4L/DVB (13845): smsdvb: Fix the frequency switch that broke with v5 API conversion Bandwidth is in Hz, not in kHz. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsdvb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 36f886768aa..2f675cda947 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -507,7 +507,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, sms_info("%s: freq %d band %d", __func__, c->frequency, c->bandwidth_hz); - switch (c->bandwidth_hz / 1000) { + switch (c->bandwidth_hz / 1000000) { case 8: Msg.Data[1] = BW_8_MHZ; break; @@ -575,7 +575,7 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe, Msg.Data[1] = BW_ISDBT_1SEG; break; case 0: /* AUTO */ - switch (c->bandwidth_hz / 1000) { + switch (c->bandwidth_hz / 1000000) { case 8: case 7: c->isdbt_sb_segment_count = 3; -- cgit v1.2.3 From 5eb23975b441cb8814eab82f5768e09106d50578 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Dec 2009 11:29:42 -0300 Subject: V4L/DVB (13846): smsdvb: Properly implement stats for both DVB and ISDB-T After taking a look at the driver's history and doing some tests with DVB and ISDB-T, it was noticed that the stats were incomplete, for ISDB-T, and weren't working for DVB. Fixed the code and added a debug code to print the complete stats at dmesg. This debug is useful to improve the stats of this driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smscoreapi.h | 77 ++++++++++++++++++- drivers/media/dvb/siano/smsdvb.c | 138 ++++++++++++++++++++++++++++++++--- 2 files changed, 201 insertions(+), 14 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h index 7393e2b5265..8ecadecaa9d 100644 --- a/drivers/media/dvb/siano/smscoreapi.h +++ b/drivers/media/dvb/siano/smscoreapi.h @@ -341,8 +341,8 @@ struct SmsFirmware_ST { /* Statistics information returned as response for * SmsHostApiGetStatistics_Req */ -struct SMSHOSTLIB_STATISTICS_S { - u8 Reserved[5]; /* Reserved */ +struct SMSHOSTLIB_STATISTICS_ST { + u32 Reserved; /* Reserved */ /* Common parameters */ u32 IsRfLocked; /* 0 - not locked, 1 - locked */ @@ -426,6 +426,79 @@ struct SMSHOSTLIB_STATISTICS_S { u32 ReservedFields[10]; /* Reserved */ }; +struct SmsMsgStatisticsInfo_ST { + u32 RequestResult; + + struct SMSHOSTLIB_STATISTICS_ST Stat; + + /* Split the calc of the SNR in DAB */ + u32 Signal; /* dB */ + u32 Noise; /* dB */ + +}; + +struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST { + /* Per-layer information */ + u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, + * 255 means layer does not exist */ + u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET, + * 255 means layer does not exist */ + u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ + u32 BERErrorCount; /* Post Viterbi Error Bits Count */ + u32 BERBitCount; /* Post Viterbi Total Bits Count */ + u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ + u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */ + u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ + u32 TotalTSPackets; /* Total number of transport-stream packets */ + u32 TILdepthI; /* Time interleaver depth I parameter, + * 255 means layer does not exist */ + u32 NumberOfSegments; /* Number of segments in layer A, + * 255 means layer does not exist */ + u32 TMCCErrors; /* TMCC errors */ +}; + +struct SMSHOSTLIB_STATISTICS_ISDBT_ST { + u32 StatisticsType; /* Enumerator identifying the type of the + * structure. Values are the same as + * SMSHOSTLIB_DEVICE_MODES_E + * + * This field MUST always be first in any + * statistics structure */ + + u32 FullSize; /* Total size of the structure returned by the modem. + * If the size requested by the host is smaller than + * FullSize, the struct will be truncated */ + + /* Common parameters */ + u32 IsRfLocked; /* 0 - not locked, 1 - locked */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ + u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ + + /* Reception quality */ + s32 SNR; /* dB */ + s32 RSSI; /* dBm */ + s32 InBandPwr; /* In band power in dBM */ + s32 CarrierOffset; /* Carrier Offset in Hz */ + + /* Transmission parameters */ + u32 Frequency; /* Frequency in Hz */ + u32 Bandwidth; /* Bandwidth in MHz */ + u32 TransmissionMode; /* ISDB-T transmission mode */ + u32 ModemState; /* 0 - Acquisition, 1 - Locked */ + u32 GuardInterval; /* Guard Interval, 1 divided by value */ + u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */ + u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */ + u32 NumOfLayers; /* Number of ISDB-T layers in the network */ + + /* Per-layer information */ + /* Layers A, B and C */ + struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3]; + /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */ + + /* Interface information */ + u32 SmsToHostTxErrors; /* Total number of transmission errors. */ +}; + struct PID_STATISTICS_DATA_S { struct PID_BURST_S { u32 size; diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 2f675cda947..b44ba399799 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -116,6 +116,119 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client, } } + +static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData, + struct SMSHOSTLIB_STATISTICS_ST *p) +{ + if (sms_dbg & 2) { + printk(KERN_DEBUG "Reserved = %d", p->Reserved); + printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); + printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); + printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); + printk(KERN_DEBUG "SNR = %d", p->SNR); + printk(KERN_DEBUG "BER = %d", p->BER); + printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC); + printk(KERN_DEBUG "TS_PER = %d", p->TS_PER); + printk(KERN_DEBUG "MFER = %d", p->MFER); + printk(KERN_DEBUG "RSSI = %d", p->RSSI); + printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); + printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); + printk(KERN_DEBUG "Frequency = %d", p->Frequency); + printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); + printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); + printk(KERN_DEBUG "ModemState = %d", p->ModemState); + printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); + printk(KERN_DEBUG "CodeRate = %d", p->CodeRate); + printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate); + printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy); + printk(KERN_DEBUG "Constellation = %d", p->Constellation); + printk(KERN_DEBUG "BurstSize = %d", p->BurstSize); + printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration); + printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime); + printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime); + printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows); + printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols); + printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols); + printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets); + printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets); + printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs); + printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs); + printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs); + printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount); + printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount); + printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); + printk(KERN_DEBUG "PreBER = %d", p->PreBER); + printk(KERN_DEBUG "CellId = %d", p->CellId); + printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP); + printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP); + printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived); + printk(KERN_DEBUG "ReservedFields[10] = %d", p->ReservedFields[10]); + } + + pReceptionData->IsDemodLocked = p->IsDemodLocked; + + pReceptionData->SNR = p->SNR; + pReceptionData->BER = p->BER; + pReceptionData->BERErrorCount = p->BERErrorCount; + pReceptionData->InBandPwr = p->InBandPwr; + pReceptionData->ErrorTSPackets = p->ErrorTSPackets; +}; + + +static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData, + struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p) +{ + int i; + + if (sms_dbg & 2) { + printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); + printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); + printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); + printk(KERN_DEBUG "SNR = %d", p->SNR); + printk(KERN_DEBUG "RSSI = %d", p->RSSI); + printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); + printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); + printk(KERN_DEBUG "Frequency = %d", p->Frequency); + printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); + printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); + printk(KERN_DEBUG "ModemState = %d", p->ModemState); + printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); + printk(KERN_DEBUG "SystemType = %d", p->SystemType); + printk(KERN_DEBUG "PartialReception = %d", p->PartialReception); + printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers); + printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); + + for (i = 0; i < 3; i++) { + printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate); + printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation); + printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER); + printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount); + printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount); + printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER); + printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER); + printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets); + printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets); + printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI); + printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments); + printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors); + } + } + + pReceptionData->IsDemodLocked = p->IsDemodLocked; + + pReceptionData->SNR = p->SNR; + pReceptionData->InBandPwr = p->InBandPwr; + + pReceptionData->ErrorTSPackets = 0; + pReceptionData->BER = 0; + pReceptionData->BERErrorCount = 0; + for (i = 0; i < 3; i++) { + pReceptionData->BER += p->LayerInfo[i].BER; + pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount; + pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets; + } +} + static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; @@ -219,32 +332,33 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) break; } case MSG_SMS_GET_STATISTICS_RES: { - struct SMSHOSTLIB_STATISTICS_S *p = - (struct SMSHOSTLIB_STATISTICS_S *)(phdr + 1); + union { + struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt; + struct SmsMsgStatisticsInfo_ST dvb; + } *p = (void *) (phdr + 1); struct RECEPTION_STATISTICS_S *pReceptionData = &client->sms_stat_dvb.ReceptionData; sms_info("MSG_SMS_GET_STATISTICS_RES"); is_status_update = true; - pReceptionData->IsDemodLocked = p->IsDemodLocked; + + switch (smscore_get_device_mode(client->coredev)) { + case DEVICE_MODE_ISDBT: + case DEVICE_MODE_ISDBT_BDA: + smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt); + break; + default: + smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat); + } if (!pReceptionData->IsDemodLocked) { pReceptionData->SNR = 0; pReceptionData->BER = 0; pReceptionData->BERErrorCount = 0; pReceptionData->InBandPwr = 0; pReceptionData->ErrorTSPackets = 0; - - complete(&client->tune_done); - break; } - pReceptionData->SNR = p->SNR; - pReceptionData->BER = p->BER; - pReceptionData->BERErrorCount = p->BERErrorCount; - pReceptionData->InBandPwr = p->InBandPwr; - pReceptionData->ErrorTSPackets = p->ErrorTSPackets; - complete(&client->tune_done); break; } -- cgit v1.2.3 From 25f9461a03f5f5a577a626df3ae5bcf09542d96a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Dec 2009 11:47:33 -0300 Subject: V4L/DVB (13847): smsdvb: Remove a wrong debug message Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsdvb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index b44ba399799..4784c8f2122 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -162,7 +162,6 @@ static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionDat printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP); printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP); printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived); - printk(KERN_DEBUG "ReservedFields[10] = %d", p->ReservedFields[10]); } pReceptionData->IsDemodLocked = p->IsDemodLocked; -- cgit v1.2.3 From b4622c14a1450fa40dd89dc134ec008fd1c2d38c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Dec 2009 18:04:17 -0300 Subject: V4L/DVB (13848): smsdvb: Add the proper status for IsRfLocked Now, if RF is locked but demod is not locked, it will report: >>> tuning status == 0x03 This happens, for example, if the device is on DVB-T, and the video standard is ISDB-T. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsdvb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 4784c8f2122..5f3939821ca 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -380,10 +380,10 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) DVB3_EVENT_UNC_ERR); } else { - /*client->fe_status = - (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? - 0 : FE_HAS_SIGNAL;*/ - client->fe_status = 0; + if (client->sms_stat_dvb.ReceptionData.IsRfLocked) + client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER; + else + client->fe_status = 0; sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); } } -- cgit v1.2.3 From 639544d78c430fef875f3bb31083a60f3e2e0344 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 31 Dec 2009 17:49:32 -0300 Subject: V4L/DVB (13878): dvb_frontend: Print dump on get after filling the data Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 07461222a7f..ef664a16a94 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1199,8 +1199,6 @@ static int dtv_property_process_get(struct dvb_frontend *fe, { int r = 0; - dtv_property_dump(tvp); - /* Allow the frontend to validate incoming properties */ if (fe->ops.get_property) r = fe->ops.get_property(fe, tvp); @@ -1323,6 +1321,8 @@ static int dtv_property_process_get(struct dvb_frontend *fe, r = -1; } + dtv_property_dump(tvp); + return r; } -- cgit v1.2.3 From fb8253baa0852bb628b6f4fed1ed0b8ae20e4e3c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 31 Dec 2009 18:14:54 -0300 Subject: V4L/DVB (13879): dvb_frontend: report what ioctl were called on debug mode When printing that an iocl were called, report the ioctl number. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index ef664a16a94..ca2060e0439 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1488,7 +1488,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, struct dvb_frontend_private *fepriv = fe->frontend_priv; int err = -EOPNOTSUPP; - dprintk ("%s\n", __func__); + dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); if (fepriv->exit) return -ENODEV; -- cgit v1.2.3 From 6a2071006b72bf887e38c025c60f98d2998ceacb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 4 Jan 2010 02:43:19 -0300 Subject: V4L/DVB (13930): dib0700: rework IR logic for firmware 1.20 When firmware 1.20 was introduced, the dib0700 switched from a polling model using a USB control message, to the messages being delivered on a USB bulk pipe. The code I originally added would do a blocking read on the pipe with a 50ms timeout. Because the dvb-usb-remote code makes use of the global workqueue, this resulted in the global workqueue being blocked 50% of the time. Also, the synchronous urb_bulk_msg() call would burn excess CPU time (reflected as an abnormal increase in the system's load average when devices were connected). Rework the logic so that we now setup an asynchronous callback on the bulk pipe, so that we now only handle RC data when it arrives on the pipe. Note that we provide a stub function for the RC polling callback so that we can continue to leverage the shared code in dvb-usb-rc for the setting up of the input device. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700.h | 1 - drivers/media/dvb/dvb-usb/dib0700_core.c | 196 +++++++++++++++++++++++++++- drivers/media/dvb/dvb-usb/dib0700_devices.c | 160 ++--------------------- 3 files changed, 206 insertions(+), 151 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 495a90577c5..83fc24a6c31 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -42,7 +42,6 @@ struct dib0700_state { u16 mt2060_if1[2]; u8 rc_toggle; u8 rc_counter; - u8 rc_func_version; u8 is_dib7000pc; u8 fw_use_new_i2c_api; u8 disable_streaming_master_mode; diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 0d3c9a9a33b..4450214e2c6 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -471,14 +471,208 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return dib0700_ctrl_wr(adap->dev, b, 4); } +/* Number of keypresses to ignore before start repeating */ +#define RC_REPEAT_DELAY_V1_20 10 + +/* This is the structure of the RC response packet starting in firmware 1.20 */ +struct dib0700_rc_response { + u8 report_id; + u8 data_state; + u16 system; + u8 data; + u8 not_data; +}; +#define RC_MSG_SIZE_V1_20 6 + +static void dib0700_rc_urb_completion(struct urb *purb) +{ + struct dvb_usb_device *d = purb->context; + struct dvb_usb_rc_key *keymap; + struct dib0700_state *st; + struct dib0700_rc_response poll_reply; + u8 *buf; + int found = 0; + u32 event; + int state; + int i; + + deb_info("%s()\n", __func__); + if (d == NULL) + return; + + if (d->rc_input_dev == NULL) { + /* This will occur if disable_rc_polling=1 */ + usb_free_urb(purb); + return; + } + + keymap = d->props.rc_key_map; + st = d->priv; + buf = (u8 *)purb->transfer_buffer; + + if (purb->status < 0) { + deb_info("discontinuing polling\n"); + usb_free_urb(purb); + return; + } + + if (purb->actual_length != RC_MSG_SIZE_V1_20) { + deb_info("malformed rc msg size=%d\n", purb->actual_length); + goto resubmit; + } + + /* Set initial results in case we exit the function early */ + event = 0; + state = REMOTE_NO_KEY_PRESSED; + + deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0], + buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length); + + switch (dvb_usb_dib0700_ir_proto) { + case 0: + /* NEC Protocol */ + poll_reply.report_id = 0; + poll_reply.data_state = 1; + poll_reply.system = buf[2]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; + + /* NEC protocol sends repeat code as 0 0 0 FF */ + if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00) + && (poll_reply.not_data == 0xff)) { + poll_reply.data_state = 2; + break; + } + break; + default: + /* RC5 Protocol */ + poll_reply.report_id = buf[0]; + poll_reply.data_state = buf[1]; + poll_reply.system = (buf[2] << 8) | buf[3]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; + break; + } + + if ((poll_reply.data + poll_reply.not_data) != 0xff) { + /* Key failed integrity check */ + err("key failed integrity check: %04x %02x %02x", + poll_reply.system, + poll_reply.data, poll_reply.not_data); + goto resubmit; + } + + deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n", + poll_reply.report_id, poll_reply.data_state, + poll_reply.system, poll_reply.data, poll_reply.not_data); + + /* Find the key in the map */ + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && + rc5_data(&keymap[i]) == poll_reply.data) { + event = keymap[i].event; + found = 1; + break; + } + } + + if (found == 0) { + err("Unknown remote controller key: %04x %02x %02x", + poll_reply.system, poll_reply.data, poll_reply.not_data); + d->last_event = 0; + goto resubmit; + } + + if (poll_reply.data_state == 1) { + /* New key hit */ + st->rc_counter = 0; + event = keymap[i].event; + state = REMOTE_KEY_PRESSED; + d->last_event = keymap[i].event; + } else if (poll_reply.data_state == 2) { + /* Key repeated */ + st->rc_counter++; + + /* prevents unwanted double hits */ + if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { + event = d->last_event; + state = REMOTE_KEY_PRESSED; + st->rc_counter = RC_REPEAT_DELAY_V1_20; + } + } else { + err("Unknown data state [%d]", poll_reply.data_state); + } + + switch (state) { + case REMOTE_NO_KEY_PRESSED: + break; + case REMOTE_KEY_PRESSED: + deb_info("key pressed\n"); + d->last_event = event; + case REMOTE_KEY_REPEAT: + deb_info("key repeated\n"); + input_event(d->rc_input_dev, EV_KEY, event, 1); + input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); + input_sync(d->rc_input_dev); + break; + default: + break; + } + +resubmit: + /* Clean the buffer before we requeue */ + memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20); + + /* Requeue URB */ + usb_submit_urb(purb, GFP_ATOMIC); +} + int dib0700_rc_setup(struct dvb_usb_device *d) { + struct dib0700_state *st = d->priv; u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0}; - int i = dib0700_ctrl_wr(d, rc_setup, 3); + struct urb *purb; + int ret; + int i; + + if (d->props.rc_key_map == NULL) + return 0; + + /* Set the IR mode */ + i = dib0700_ctrl_wr(d, rc_setup, 3); if (i<0) { err("ir protocol setup failed"); return -1; } + + if (st->fw_version < 0x10200) + return 0; + + /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ + purb = usb_alloc_urb(0, GFP_KERNEL); + if (purb == NULL) { + err("rc usb alloc urb failed\n"); + return -1; + } + + purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL); + if (purb->transfer_buffer == NULL) { + err("rc kzalloc failed\n"); + usb_free_urb(purb); + return -1; + } + + purb->status = -EINPROGRESS; + usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1), + purb->transfer_buffer, RC_MSG_SIZE_V1_20, + dib0700_rc_urb_completion, d); + + ret = usb_submit_urb(purb, GFP_ATOMIC); + if (ret != 0) { + err("rc submit urb failed\n"); + return -1; + } + return 0; } diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 44972d01bbd..34eab05afc6 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -472,20 +472,25 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; /* Number of keypresses to ignore before start repeating */ #define RC_REPEAT_DELAY 6 -#define RC_REPEAT_DELAY_V1_20 10 - - -/* Used by firmware versions < 1.20 (deprecated) */ -static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, - int *state) +static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { u8 key[4]; int i; struct dvb_usb_rc_key *keymap = d->props.rc_key_map; struct dib0700_state *st = d->priv; + *event = 0; *state = REMOTE_NO_KEY_PRESSED; + + if (st->fw_version >= 0x10200) { + /* For 1.20 firmware , We need to keep the RC polling + callback so we can reuse the input device setup in + dvb-usb-remote.c. However, the actual work is being done + in the bulk URB completion handler. */ + return 0; + } + i=dib0700_ctrl_rd(d,rc_request,2,key,4); if (i<=0) { err("RC Query Failed"); @@ -557,149 +562,6 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, return 0; } -/* This is the structure of the RC response packet starting in firmware 1.20 */ -struct dib0700_rc_response { - u8 report_id; - u8 data_state; - u16 system; - u8 data; - u8 not_data; -}; - -/* This supports the new IR response format for firmware v1.20 */ -static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, - int *state) -{ - struct dvb_usb_rc_key *keymap = d->props.rc_key_map; - struct dib0700_state *st = d->priv; - struct dib0700_rc_response poll_reply; - u8 buf[6]; - int i; - int status; - int actlen; - int found = 0; - - /* Set initial results in case we exit the function early */ - *event = 0; - *state = REMOTE_NO_KEY_PRESSED; - - /* Firmware v1.20 provides RC data via bulk endpoint 1 */ - status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf, - sizeof(buf), &actlen, 50); - if (status < 0) { - /* No data available (meaning no key press) */ - return 0; - } - - - switch (dvb_usb_dib0700_ir_proto) { - case 0: - poll_reply.report_id = 0; - poll_reply.data_state = 1; - poll_reply.system = buf[2]; - poll_reply.data = buf[4]; - poll_reply.not_data = buf[5]; - - /* NEC protocol sends repeat code as 0 0 0 FF */ - if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00) - && (poll_reply.not_data == 0xff)) { - poll_reply.data_state = 2; - break; - } - break; - default: - if (actlen != sizeof(buf)) { - /* We didn't get back the 6 byte message we expected */ - err("Unexpected RC response size [%d]", actlen); - return -1; - } - - poll_reply.report_id = buf[0]; - poll_reply.data_state = buf[1]; - poll_reply.system = (buf[2] << 8) | buf[3]; - poll_reply.data = buf[4]; - poll_reply.not_data = buf[5]; - - break; - } - - if ((poll_reply.data + poll_reply.not_data) != 0xff) { - /* Key failed integrity check */ - err("key failed integrity check: %04x %02x %02x", - poll_reply.system, - poll_reply.data, poll_reply.not_data); - return -1; - } - - - /* Find the key in the map */ - for (i = 0; i < d->props.rc_key_map_size; i++) { - if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && - rc5_data(&keymap[i]) == poll_reply.data) { - *event = keymap[i].event; - found = 1; - break; - } - } - - if (found == 0) { - err("Unknown remote controller key: %04x %02x %02x", - poll_reply.system, - poll_reply.data, poll_reply.not_data); - d->last_event = 0; - return 0; - } - - if (poll_reply.data_state == 1) { - /* New key hit */ - st->rc_counter = 0; - *event = keymap[i].event; - *state = REMOTE_KEY_PRESSED; - d->last_event = keymap[i].event; - } else if (poll_reply.data_state == 2) { - /* Key repeated */ - st->rc_counter++; - - /* prevents unwanted double hits */ - if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { - *event = d->last_event; - *state = REMOTE_KEY_PRESSED; - st->rc_counter = RC_REPEAT_DELAY_V1_20; - } - } else { - err("Unknown data state [%d]", poll_reply.data_state); - } - - return 0; -} - -static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) -{ - struct dib0700_state *st = d->priv; - - /* Because some people may have improperly named firmware files, - let's figure out whether to use the new firmware call or the legacy - call based on the firmware version embedded in the file */ - if (st->rc_func_version == 0) { - u32 hwver, romver, ramver, fwtype; - int ret = dib0700_get_version(d, &hwver, &romver, &ramver, - &fwtype); - if (ret < 0) { - err("Could not determine version info"); - return -1; - } - if (ramver < 0x10200) - st->rc_func_version = 1; - else - st->rc_func_version = 2; - } - - if (st->rc_func_version == 2) - return dib0700_rc_query_v1_20(d, event, state); - else - return dib0700_rc_query_legacy(d, event, state); -} - static struct dvb_usb_rc_key dib0700_rc_keys[] = { /* Key codes for the tiny Pinnacle remote*/ { 0x0700, KEY_MUTE }, -- cgit v1.2.3 From e0572325d23b8c89930a08e0b8b3850a6fe75d7d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 21 Dec 2009 21:21:47 -0300 Subject: V4L/DVB (13946): proc_fops: convert av7110 Drop S_IRUGO, proc entry doesn't contain read hooks. Drop S_IFREG, simply unnecessary. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110_ir.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 23a1c6380d3..b070e88d8c6 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -268,8 +268,8 @@ int av7110_check_ir_config(struct av7110 *av7110, int force) /* /proc/av7110_ir interface */ -static int av7110_ir_write_proc(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { char *page; u32 ir_config; @@ -309,6 +309,10 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, return count; } +static const struct file_operations av7110_ir_proc_fops = { + .owner = THIS_MODULE, + .write = av7110_ir_proc_write, +}; /* interrupt handler */ static void ir_handler(struct av7110 *av7110, u32 ircom) @@ -368,11 +372,9 @@ int __devinit av7110_ir_init(struct av7110 *av7110) input_dev->timer.data = (unsigned long) &av7110->ir; if (av_cnt == 1) { - e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); - if (e) { - e->write_proc = av7110_ir_write_proc; + e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops); + if (e) e->size = 4 + 256 * sizeof(u16); - } } tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir); -- cgit v1.2.3 From 21ead03bdde189106e0625baac170385a6c360af Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 22 Dec 2009 18:00:07 -0300 Subject: V4L/DVB (13949): Move a dereference below a NULL test If the NULL test is necessary, then the dereference should be moved below the NULL test. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ type T; expression E; identifier i,fld; statement S; @@ - T i = E->fld; + T i; ... when != E when != i if (E == NULL) S + i = E->fld; // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dw2102.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 83a35524a82..accc65509b0 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -470,12 +470,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - struct usb_device *udev = d->udev; + struct usb_device *udev; int ret = 0; int len, i, j; if (!d) return -ENODEV; + udev = d->udev; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; -- cgit v1.2.3 From 7b2d3983f2b54b002fd045f2801514405530d224 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 23 Dec 2009 09:53:13 -0300 Subject: V4L/DVB (13950): usb-friio: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/friio-fe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c index ebb7b9fd115..d14bd227b50 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/dvb/dvb-usb/friio-fe.c @@ -366,7 +366,7 @@ static u8 init_code[][2] = { {0x76, 0x0C}, }; -const static int init_code_len = sizeof(init_code) / sizeof(u8[2]); +static const int init_code_len = sizeof(init_code) / sizeof(u8[2]); static int jdvbt90502_init(struct dvb_frontend *fe) { -- cgit v1.2.3 From b2ad41f9ef72d7b3309a2578bf4432a262ff2b47 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 25 Dec 2009 21:47:12 -0300 Subject: V4L/DVB (13953): firedtv: add missing NULL pointer check If there is ever going to be a FireDTV or FloppyDTV firmware which does not provide a minimal ASCII textual descriptor for Model_Id --- or if the descriptor is provided indirectly in a descriptor directory --- the ieee1394 variant of the device probe of firedtv would dereference a NULL pointer. The firewire variant of firedtv's device probe is not affected. The fix makes sure that such an unexpected firmware is safely recognized by fdtv_alloc as an unknown firmware. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-1394.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index 7c5459c27b7..81a56293540 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -192,9 +192,13 @@ static int node_probe(struct device *dev) int kv_len, err; void *kv_str; - kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); - kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); - + if (ud->model_name_kv) { + kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4; + kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); + } else { + kv_len = 0; + kv_str = NULL; + } fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); if (!fdtv) return -ENOMEM; -- cgit v1.2.3 From 211635654cb6785a5c102af6488f6b1d83b9a3c6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 28 Dec 2009 14:48:49 -0300 Subject: V4L/DVB (13956): fix weird array index in zl10036.c I was initially concerned about the weird array index (the 2 bumps into the next row of the array). Matthias Schwarzott look at the datasheet and it turns out it should be zl10036_init_tab[1][0] |= 0x01; Signed-off-by: Dan Carpenter Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10036.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb/frontends/zl10036.c index 4e814ff22b2..34c5de491d2 100644 --- a/drivers/media/dvb/frontends/zl10036.c +++ b/drivers/media/dvb/frontends/zl10036.c @@ -411,7 +411,7 @@ static int zl10036_init_regs(struct zl10036_state *state) state->bf = 0xff; if (!state->config->rf_loop_enable) - zl10036_init_tab[1][2] |= 0x01; + zl10036_init_tab[1][0] |= 0x01; deb_info("%s\n", __func__); -- cgit v1.2.3 From b46d37e61f886e901ba0b504125b135f450a19b5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 6 Jan 2010 13:45:27 -0300 Subject: V4L/DVB (13963): siano, fix memory leak Stanse found a memory leak in smscore_gpio_configure. buffer is not freed/assigned on all paths. Fix that. Signed-off-by: Jiri Slaby Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smscoreapi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index ca758bcb48c..4bfd3451b56 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -1459,8 +1459,10 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, - &groupCfg) != 0) - return -EINVAL; + &groupCfg) != 0) { + rc = -EINVAL; + goto free; + } pMsg->msgData[1] = TranslatedPinNum; pMsg->msgData[2] = GroupNum; @@ -1490,6 +1492,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, else sms_err("smscore_gpio_configure error"); } +free: kfree(buffer); return rc; -- cgit v1.2.3 From 78b06e0201fb32716211959bce133740a13873c4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 6 Jan 2010 19:04:07 -0300 Subject: V4L/DVB (13965): zl10039, jump to error on error Stanse found an unreachable statement in zl10039_attach. There is a `break' followed by `goto error'. Remove that break, so that it can handle the error. Cc: Igor M. Liplianin Signed-off-by: Jiri Slaby Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10039.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/zl10039.c b/drivers/media/dvb/frontends/zl10039.c index 11b29cb883e..c085e58a94b 100644 --- a/drivers/media/dvb/frontends/zl10039.c +++ b/drivers/media/dvb/frontends/zl10039.c @@ -287,7 +287,6 @@ struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, break; default: dprintk("Chip ID=%x does not match a known type\n", state->id); - break; goto error; } -- cgit v1.2.3 From 42a39e05928c6262347fba4ec9f649124bfc7a6f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 13 Jan 2010 03:59:15 -0300 Subject: V4L/DVB (13969): frontends/si21xx.c: Remove #define TRUE/FALSE, use bool And a little code refactoring/neatening around the removals Reduces object size a little bit: new: $ size drivers/media/dvb/frontends/si21xx.o text data bss dec hex filename 8984 56 1816 10856 2a68 drivers/media/dvb/frontends/si21xx.o old: $ size drivers/media/dvb/frontends/si21xx.o text data bss dec hex filename 9084 56 1792 10932 2ab4 drivers/media/dvb/frontends/si21xx.o Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/si21xx.c | 38 +++++++++++++++--------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c index 9552a22ccff..d21a327db62 100644 --- a/drivers/media/dvb/frontends/si21xx.c +++ b/drivers/media/dvb/frontends/si21xx.c @@ -97,8 +97,6 @@ #define LNB_SUPPLY_CTRL_REG_4 0xce #define LNB_SUPPLY_STATUS_REG 0xcf -#define FALSE 0 -#define TRUE 1 #define FAIL -1 #define PASS 0 @@ -718,7 +716,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, int fine_tune_freq; unsigned char sample_rate = 0; /* boolean */ - unsigned int inband_interferer_ind; + bool inband_interferer_ind; /* INTERMEDIATE VALUES */ int icoarse_tune_freq; /* MHz */ @@ -728,15 +726,8 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, unsigned int x1; unsigned int x2; int i; - unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = { - FALSE, FALSE, FALSE, FALSE, FALSE, - FALSE, FALSE, FALSE, FALSE, FALSE - }; - unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = { - FALSE, FALSE, FALSE, FALSE, FALSE, - FALSE, FALSE, FALSE, FALSE, FALSE - }; - + bool inband_interferer_div2[ALLOWABLE_FS_COUNT]; + bool inband_interferer_div4[ALLOWABLE_FS_COUNT]; int status; /* allowable sample rates for ADC in MHz */ @@ -762,7 +753,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, } for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) - inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE; + inband_interferer_div2[i] = inband_interferer_div4[i] = false; if_limit_high = -700000; if_limit_low = -100000; @@ -798,7 +789,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, if (((band_low < x1) && (x1 < band_high)) || ((band_low < x2) && (x2 < band_high))) - inband_interferer_div4[i] = TRUE; + inband_interferer_div4[i] = true; } @@ -811,25 +802,28 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, if (((band_low < x1) && (x1 < band_high)) || ((band_low < x2) && (x2 < band_high))) - inband_interferer_div2[i] = TRUE; + inband_interferer_div2[i] = true; } - inband_interferer_ind = TRUE; - for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) - inband_interferer_ind &= inband_interferer_div2[i] | - inband_interferer_div4[i]; + inband_interferer_ind = true; + for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { + if (inband_interferer_div2[i] || inband_interferer_div4[i]) { + inband_interferer_ind = false; + break; + } + } if (inband_interferer_ind) { for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { - if (inband_interferer_div2[i] == FALSE) { + if (!inband_interferer_div2[i]) { sample_rate = (u8) afs[i]; break; } } } else { for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { - if ((inband_interferer_div2[i] | - inband_interferer_div4[i]) == FALSE) { + if ((inband_interferer_div2[i] || + !inband_interferer_div4[i])) { sample_rate = (u8) afs[i]; break; } -- cgit v1.2.3 From 310b26286e5a88387feba0412a75aa2a943ec844 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 22 Dec 2009 05:38:14 -0300 Subject: V4L/DVB (13947): add __init/__exit macros to drivers/media/dvb/bt8xx/bt878.c Trivial patch which adds the __init/__exit macros to the module_init/ module_exit functions of drivers/media/dvb/bt8xx/bt878.c Please have a look at the small patch and either pull it through your tree, or please ack' it so Jiri can pull it through the trivial tree. Patch against linux-next-tree, 22. Dez 08:38:18 CET 2009 but also present in linus tree. Signed-off-by: Peter Huewe Acked-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/bt878.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index a24c125331f..2a0886ad787 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -582,7 +582,7 @@ static int bt878_pci_driver_registered; /* Module management functions */ /*******************************/ -static int bt878_init_module(void) +static int __init bt878_init_module(void) { bt878_num = 0; bt878_pci_driver_registered = 0; @@ -600,7 +600,7 @@ static int bt878_init_module(void) return pci_register_driver(&bt878_pci_driver); } -static void bt878_cleanup_module(void) +static void __exit bt878_cleanup_module(void) { if (bt878_pci_driver_registered) { bt878_pci_driver_registered = 0; -- cgit v1.2.3 From ceb59cf068d54761c653c42dd45c14e1ecf0f7d3 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Wed, 13 Jan 2010 05:01:56 -0300 Subject: V4L/DVB (13936): 22-kHz set_tone fix for NetUP Dual DVB-S2-CI card 22-kHz tone can be driven in two ways: 1. LNBH24 can produce 22kHz continuous tone when TEN=1 ( 22 KHz tone output is always activated ). 2. LNBH24 can reproduce 22kHz tone timings from DSQIN or EXTM pin's when TEN=0. From LNBH24 datasheet: "In order to improve design flexibility an external tone input pin is available (EXTM). The EXTM is a Logic input pin which activates the 22 kHz tone output, on the VoTX pin, by using the LNBH24 integrated tone generator (similar to the DSQIN pin function). In fact, the output tone waveform characteristics will always be internally controlled by the LNBH24 tone generator and the EXTM signal will be used as a timing control for DiSEqC tone data encoding on the VoTX output." In NetUP Dual DVB-S2-CI card 22kHz tone timings on EXTM pin produced by STV0900 demod: .set_tone = stv0900_set_tone redefine to "set_tone = lnbp21_set_tone" is not correct for "NetUP Dual DVB-S2-CI card". Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lnbp21.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c index b181bf023ad..49d2b1c1611 100644 --- a/drivers/media/dvb/frontends/lnbp21.c +++ b/drivers/media/dvb/frontends/lnbp21.c @@ -158,7 +158,8 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, /* override frontend ops */ fe->ops.set_voltage = lnbp21_set_voltage; fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - fe->ops.set_tone = lnbp21_set_tone; + if (!fe->ops.set_tone) /* don't redefine */ + fe->ops.set_tone = lnbp21_set_tone; printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); return fe; -- cgit v1.2.3 From b79c6df705e02b5dcb0e9360a15b28373813fec1 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:18:52 -0300 Subject: V4L/DVB (13974): [STV090x] Fix locking reliabilty issues in automatic mode. In automatic S/S2 detection mode, locking of a DVB-S transponder could fail when coming from a DVB-S2 transponder. This change fixes the issue by first disabling DVB-S and DVB-S2 mode before enabling it again. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 1573466a5c7..e57581d14cc 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1246,6 +1246,10 @@ static int stv090x_delivery_search(struct stv090x_state *state) default: /* enable DVB-S2 and DVB-S2 in Auto MODE */ reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) -- cgit v1.2.3 From 97f7a2ae1a8a1e44a481456375efced75210e5eb Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:19:43 -0300 Subject: V4L/DVB (13975): [STV090x] Added internal structure with shared settings and data. As the STV0900 features two demodulation paths in one chip there is some information used by both instances of the driver when used in dual mode. This information is now shared in an internal structure referenced by I2C adapter and address. Do initialisation of the demodulator only once when used in dual mode. Moved global mutex demod_lock to internal structure. Moved dev_ver and mclk to internal structure. Removed unused tuner_refclk from stv090x_state. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 289 ++++++++++++++++++++--------- drivers/media/dvb/frontends/stv090x.h | 2 - drivers/media/dvb/frontends/stv090x_priv.h | 16 +- drivers/media/dvb/ttpci/budget.c | 1 - 4 files changed, 216 insertions(+), 92 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index e57581d14cc..9a817a69ed3 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -37,7 +37,82 @@ static unsigned int verbose; module_param(verbose, int, 0644); -struct mutex demod_lock; +/* internal params node */ +struct stv090x_dev { + /* pointer for internal params, one for each pair of demods */ + struct stv090x_internal *internal; + struct stv090x_dev *next_dev; +}; + +/* first internal params */ +static struct stv090x_dev *stv090x_first_dev; + +/* find chip by i2c adapter and i2c address */ +static struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap, + u8 i2c_addr) +{ + struct stv090x_dev *temp_dev = stv090x_first_dev; + + /* + Search of the last stv0900 chip or + find it by i2c adapter and i2c address */ + while ((temp_dev != NULL) && + ((temp_dev->internal->i2c_adap != i2c_adap) || + (temp_dev->internal->i2c_addr != i2c_addr))) { + + temp_dev = temp_dev->next_dev; + } + + return temp_dev; +} + +/* deallocating chip */ +static void remove_dev(struct stv090x_internal *internal) +{ + struct stv090x_dev *prev_dev = stv090x_first_dev; + struct stv090x_dev *del_dev = find_dev(internal->i2c_adap, + internal->i2c_addr); + + if (del_dev != NULL) { + if (del_dev == stv090x_first_dev) { + stv090x_first_dev = del_dev->next_dev; + } else { + while (prev_dev->next_dev != del_dev) + prev_dev = prev_dev->next_dev; + + prev_dev->next_dev = del_dev->next_dev; + } + + kfree(del_dev); + } +} + +/* allocating new chip */ +static struct stv090x_dev *append_internal(struct stv090x_internal *internal) +{ + struct stv090x_dev *new_dev; + struct stv090x_dev *temp_dev; + + new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL); + if (new_dev != NULL) { + new_dev->internal = internal; + new_dev->next_dev = NULL; + + /* append to list */ + if (stv090x_first_dev == NULL) { + stv090x_first_dev = new_dev; + } else { + temp_dev = stv090x_first_dev; + while (temp_dev->next_dev != NULL) + temp_dev = temp_dev->next_dev; + + temp_dev->next_dev = new_dev; + } + } + + return new_dev; +} + /* DVBS1 and DSS C/N Lookup table */ static const struct stv090x_tab stv090x_s1cn_tab[] = { @@ -755,13 +830,13 @@ static int stv090x_set_srate(struct stv090x_state *state, u32 srate) if (srate > 60000000) { sym = (srate << 4); /* SR * 2^16 / master_clk */ - sym /= (state->mclk >> 12); + sym /= (state->internal->mclk >> 12); } else if (srate > 6000000) { sym = (srate << 6); - sym /= (state->mclk >> 10); + sym /= (state->internal->mclk >> 10); } else { sym = (srate << 9); - sym /= (state->mclk >> 7); + sym /= (state->internal->mclk >> 7); } if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */ @@ -782,13 +857,13 @@ static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate srate = 105 * (srate / 100); if (srate > 60000000) { sym = (srate << 4); /* SR * 2^16 / master_clk */ - sym /= (state->mclk >> 12); + sym /= (state->internal->mclk >> 12); } else if (srate > 6000000) { sym = (srate << 6); - sym /= (state->mclk >> 10); + sym /= (state->internal->mclk >> 10); } else { sym = (srate << 9); - sym /= (state->mclk >> 7); + sym /= (state->internal->mclk >> 7); } if (sym < 0x7fff) { @@ -816,13 +891,13 @@ static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate srate = 95 * (srate / 100); if (srate > 60000000) { sym = (srate << 4); /* SR * 2^16 / master_clk */ - sym /= (state->mclk >> 12); + sym /= (state->internal->mclk >> 12); } else if (srate > 6000000) { sym = (srate << 6); - sym /= (state->mclk >> 10); + sym /= (state->internal->mclk >> 10); } else { sym = (srate << 9); - sym /= (state->mclk >> 7); + sym /= (state->internal->mclk >> 7); } if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */ @@ -1103,21 +1178,21 @@ static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) switch (state->demod) { case STV090x_DEMODULATOR_0: - mutex_lock(&demod_lock); + mutex_lock(&state->internal->demod_lock); reg = stv090x_read_reg(state, STV090x_STOPCLK2); STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable); if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) goto err; - mutex_unlock(&demod_lock); + mutex_unlock(&state->internal->demod_lock); break; case STV090x_DEMODULATOR_1: - mutex_lock(&demod_lock); + mutex_lock(&state->internal->demod_lock); reg = stv090x_read_reg(state, STV090x_STOPCLK2); STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable); if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) goto err; - mutex_unlock(&demod_lock); + mutex_unlock(&state->internal->demod_lock); break; default: @@ -1126,14 +1201,14 @@ static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) } return 0; err: - mutex_unlock(&demod_lock); + mutex_unlock(&state->internal->demod_lock); dprintk(FE_ERROR, 1, "I/O error"); return -1; } static int stv090x_dvbs_track_crl(struct stv090x_state *state) { - if (state->dev_ver >= 0x30) { + if (state->internal->dev_ver >= 0x30) { /* Set ACLC BCLC optimised value vs SR */ if (state->srate >= 15000000) { if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0) @@ -1215,7 +1290,7 @@ static int stv090x_delivery_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) goto err; - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { /* enable S2 carrier loop */ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) goto err; @@ -1261,7 +1336,7 @@ static int stv090x_delivery_search(struct stv090x_state *state) if (stv090x_dvbs_track_crl(state) < 0) goto err; - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { /* enable S2 carrier loop */ if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) goto err; @@ -1308,7 +1383,7 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) goto err; - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { if (state->srate <= 5000000) { if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) goto err; @@ -1352,7 +1427,7 @@ static int stv090x_start_search(struct stv090x_state *state) * CFR max = +1MHz */ freq_abs = 1000 << 16; - freq_abs /= (state->mclk / 1000); + freq_abs /= (state->internal->mclk / 1000); freq = (s16) freq_abs; } else { /* COLD Start @@ -1362,7 +1437,7 @@ static int stv090x_start_search(struct stv090x_state *state) */ freq_abs = (state->search_range / 2000) + 600; freq_abs = freq_abs << 16; - freq_abs /= (state->mclk / 1000); + freq_abs /= (state->internal->mclk / 1000); freq = (s16) freq_abs; } @@ -1385,7 +1460,7 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) goto err; - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) goto err; if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) @@ -1422,10 +1497,10 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) goto err; - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { /*Frequency offset detector setting*/ if (state->srate < 2000000) { - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { /* Cut 2 */ if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) goto err; @@ -1516,7 +1591,7 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) steps = 1; dir = 1; - freq_step = (1000000 * 256) / (state->mclk / 256); + freq_step = (1000000 * 256) / (state->internal->mclk / 256); freq_init = 0; for (i = 0; i < steps; i++) { @@ -1587,7 +1662,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg; u32 agc2th; - if (state->dev_ver >= 0x30) + if (state->internal->dev_ver >= 0x30) agc2th = 0x2e00; else agc2th = 0x1f00; @@ -1623,13 +1698,13 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0) goto err; - if (state->dev_ver >= 0x30) { + if (state->internal->dev_ver >= 0x30) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0) goto err; - } else if (state->dev_ver >= 0x20) { + } else if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) @@ -1681,7 +1756,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) STV090x_READ_DEMOD(state, AGC2I0); } agc2 /= 10; - srate_coarse = stv090x_get_srate(state, state->mclk); + srate_coarse = stv090x_get_srate(state, state->internal->mclk); cur_step++; dir *= -1; if ((tmg_cpt >= 5) && (agc2 < agc2th) && @@ -1733,7 +1808,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) if (!tmg_lock) srate_coarse = 0; else - srate_coarse = stv090x_get_srate(state, state->mclk); + srate_coarse = stv090x_get_srate(state, state->internal->mclk); return srate_coarse; err: @@ -1745,7 +1820,7 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) { u32 srate_coarse, freq_coarse, sym, reg; - srate_coarse = stv090x_get_srate(state, state->mclk); + srate_coarse = stv090x_get_srate(state, state->internal->mclk); freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8; freq_coarse |= STV090x_READ_DEMOD(state, CFR1); sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ @@ -1771,10 +1846,10 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) goto err; - if (state->dev_ver >= 0x30) { + if (state->internal->dev_ver >= 0x30) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) goto err; - } else if (state->dev_ver >= 0x20) { + } else if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) goto err; } @@ -1782,20 +1857,20 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) if (srate_coarse > 3000000) { sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ sym = (sym / 1000) * 65536; - sym /= (state->mclk / 1000); + sym /= (state->internal->mclk / 1000); if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) goto err; sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */ sym = (sym / 1000) * 65536; - sym /= (state->mclk / 1000); + sym /= (state->internal->mclk / 1000); if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) goto err; sym = (srate_coarse / 1000) * 65536; - sym /= (state->mclk / 1000); + sym /= (state->internal->mclk / 1000); if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) @@ -1803,20 +1878,20 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) } else { sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ sym = (sym / 100) * 65536; - sym /= (state->mclk / 100); + sym /= (state->internal->mclk / 100); if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) goto err; sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */ sym = (sym / 100) * 65536; - sym /= (state->mclk / 100); + sym /= (state->internal->mclk / 100); if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) goto err; sym = (srate_coarse / 100) * 65536; - sym /= (state->mclk / 100); + sym /= (state->internal->mclk / 100); if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) @@ -1885,11 +1960,11 @@ static int stv090x_blind_search(struct stv090x_state *state) agc2 = stv090x_get_agc2_min_level(state); - if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) { + if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) { lock = 0; } else { - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) goto err; } else { @@ -1901,7 +1976,7 @@ static int stv090x_blind_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) goto err; - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) goto err; if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) @@ -2146,13 +2221,13 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s car_max = state->search_range / 1000; car_max += car_max / 10; car_max = 65536 * (car_max / 2); - car_max /= (state->mclk / 1000); + car_max /= (state->internal->mclk / 1000); if (car_max > 0x4000) car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */ inc = srate; - inc /= state->mclk / 1000; + inc /= state->internal->mclk / 1000; inc *= 256; inc *= 256; inc /= 1000; @@ -2213,7 +2288,7 @@ static int stv090x_chk_signal(struct stv090x_state *state) car_max += (car_max / 10); /* 10% margin */ car_max = (65536 * car_max / 2); - car_max /= state->mclk / 1000; + car_max /= state->internal->mclk / 1000; if (car_max > 0x4000) car_max = 0x4000; @@ -2238,7 +2313,7 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim car_max = state->search_range / 1000; car_max += (car_max / 10); car_max = (65536 * car_max / 2); - car_max /= (state->mclk / 1000); + car_max /= (state->internal->mclk / 1000); if (car_max > 0x4000) car_max = 0x4000; @@ -2308,7 +2383,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) case STV090x_SEARCH_DVBS1: case STV090x_SEARCH_DSS: /* accelerate the frequency detector */ - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) goto err; } @@ -2319,7 +2394,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) break; case STV090x_SEARCH_DVBS2: - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) goto err; } @@ -2332,7 +2407,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) case STV090x_SEARCH_AUTO: default: /* accelerate the frequency detector */ - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) @@ -2354,7 +2429,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) /*run the SW search 2 times maximum*/ if (lock || no_signal || (trials == 2)) { /*Check if the demod is not losing lock in DVBS2*/ - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) @@ -2376,7 +2451,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) /*FALSE lock, The demod is loosing lock */ lock = 0; if (trials < 2) { - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) goto err; } @@ -2426,11 +2501,11 @@ static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) derot |= STV090x_READ_DEMOD(state, CFR0); derot = comp2(derot, 24); - int_1 = state->mclk >> 12; + int_1 = mclk >> 12; int_2 = derot >> 12; /* carrier_frequency = MasterClock * Reg / 2^24 */ - tmp_1 = state->mclk % 0x1000; + tmp_1 = mclk % 0x1000; tmp_2 = derot % 0x1000; derot = (int_1 * int_2) + @@ -2512,7 +2587,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st if (stv090x_i2c_gate_ctrl(fe, 0) < 0) goto err; - offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000; + offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000; state->frequency += offst_freq; if (stv090x_get_viterbi(state) < 0) @@ -2583,7 +2658,7 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod s32 i; struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low; - if (state->dev_ver == 0x20) { + if (state->internal->dev_ver == 0x20) { car_loop = stv090x_s2_crl_cut20; car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20; car_loop_apsk_low = stv090x_s2_apsk_crl_cut20; @@ -2704,7 +2779,7 @@ static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) break; } - if (state->dev_ver >= 0x30) { + if (state->internal->dev_ver >= 0x30) { /* Cut 3.0 and up */ short_crl = stv090x_s2_short_crl_cut30; } else { @@ -2736,7 +2811,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0; u32 reg; - srate = stv090x_get_srate(state, state->mclk); + srate = stv090x_get_srate(state, state->internal->mclk); srate += stv090x_get_tmgoffst(state, srate); switch (state->delsys) { @@ -2755,7 +2830,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; - if (state->dev_ver >= 0x30) { + if (state->internal->dev_ver >= 0x30) { if (stv090x_get_viterbi(state) < 0) goto err; @@ -2872,7 +2947,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) goto err; } - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if ((state->search_mode == STV090x_SEARCH_DVBS1) || (state->search_mode == STV090x_SEARCH_DSS) || (state->search_mode == STV090x_SEARCH_AUTO)) { @@ -2894,7 +2969,8 @@ static int stv090x_optimize_track(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0) goto err; - if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) { + if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) || + (state->srate < 10000000)) { /* update initial carrier freq with the found freq offset */ if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) goto err; @@ -2902,7 +2978,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) goto err; state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000; - if ((state->dev_ver >= 0x20) || (blind_tune == 1)) { + if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) { if (state->algo != STV090x_WARM_SEARCH) { @@ -2954,7 +3030,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) } - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) goto err; } @@ -3030,7 +3106,7 @@ static int stv090x_set_s2rolloff(struct stv090x_state *state) { u32 reg; - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { /* rolloff to auto mode if DVBS2 */ reg = STV090x_READ_DEMOD(state, DEMOD); STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00); @@ -3066,7 +3142,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */ goto err; - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (state->srate > 5000000) { if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) goto err; @@ -3106,7 +3182,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) goto err; - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) goto err; if (state->algo == STV090x_COLD_SEARCH) @@ -3124,9 +3200,11 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (stv090x_set_srate(state, state->srate) < 0) goto err; - if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0) + if (stv090x_set_max_srate(state, state->internal->mclk, + state->srate) < 0) goto err; - if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0) + if (stv090x_set_min_srate(state, state->internal->mclk, + state->srate) < 0) goto err; if (state->srate >= 10000000) @@ -3198,7 +3276,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) reg = STV090x_READ_DEMOD(state, DEMOD); STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); - if (state->dev_ver <= 0x20) { + if (state->internal->dev_ver <= 0x20) { /* rolloff to auto mode if DVBS2 */ STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1); } else { @@ -3242,7 +3320,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ stv090x_optimize_track(state); - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { /* >= Cut 2.0 :release TS reset after * demod lock and optimized Tracking */ @@ -3774,6 +3852,15 @@ static void stv090x_release(struct dvb_frontend *fe) { struct stv090x_state *state = fe->demodulator_priv; + state->internal->num_used--; + if (state->internal->num_used <= 0) { + + dprintk(FE_ERROR, 1, "Actually removing"); + + remove_dev(state->internal); + kfree(state->internal); + } + kfree(state); } @@ -3905,10 +3992,10 @@ static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk) if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0) goto err; - state->mclk = stv090x_get_mclk(state); + state->internal->mclk = stv090x_get_mclk(state); /*Set the DiseqC frequency to 22KHz */ - div = state->mclk / 704000; + div = state->internal->mclk / 704000; if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0) goto err; if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0) @@ -3924,7 +4011,7 @@ static int stv090x_set_tspath(struct stv090x_state *state) { u32 reg; - if (state->dev_ver >= 0x20) { + if (state->internal->dev_ver >= 0x20) { switch (state->config->ts1_mode) { case STV090x_TSMODE_PARALLEL_PUNCTURED: case STV090x_TSMODE_DVBCI: @@ -4192,16 +4279,26 @@ static int stv090x_setup(struct dvb_frontend *fe) } /* STV090x init */ - if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */ + + /* Stop Demod */ + if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0) goto err; msleep(5); - if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */ + /* Set No Tuner Mode */ + if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0) goto err; + /* I2C repeater OFF */ STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); - if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */ + if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0) goto err; if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ @@ -4220,8 +4317,8 @@ static int stv090x_setup(struct dvb_frontend *fe) goto err; } - state->dev_ver = stv090x_read_reg(state, STV090x_MID); - if (state->dev_ver >= 0x20) { + state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID); + if (state->internal->dev_ver >= 0x20) { if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) goto err; @@ -4232,15 +4329,15 @@ static int stv090x_setup(struct dvb_frontend *fe) goto err; } - } else if (state->dev_ver < 0x20) { + } else if (state->internal->dev_ver < 0x20) { dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!", - state->dev_ver); + state->internal->dev_ver); goto err; - } else if (state->dev_ver > 0x30) { + } else if (state->internal->dev_ver > 0x30) { /* we shouldn't bail out from here */ dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!", - state->dev_ver); + state->internal->dev_ver); } if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) @@ -4303,6 +4400,7 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, enum stv090x_demodulator demod) { struct stv090x_state *state = NULL; + struct stv090x_dev *temp_int; state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL); if (state == NULL) @@ -4318,8 +4416,29 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, state->device = config->device; state->rolloff = STV090x_RO_35; /* default */ - if (state->demod == STV090x_DEMODULATOR_0) - mutex_init(&demod_lock); + temp_int = find_dev(state->i2c, + state->config->address); + + if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) { + state->internal = temp_int->internal; + state->internal->num_used++; + dprintk(FE_INFO, 1, "Found Internal Structure!"); + dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x", + state->device == STV0900 ? "STV0900" : "STV0903", + demod, + state->internal->dev_ver); + return &state->frontend; + } else { + state->internal = kmalloc(sizeof(struct stv090x_internal), + GFP_KERNEL); + temp_int = append_internal(state->internal); + state->internal->num_used = 1; + state->internal->i2c_adap = state->i2c; + state->internal->i2c_addr = state->config->address; + dprintk(FE_INFO, 1, "Create New Internal Structure!"); + } + + mutex_init(&state->internal->demod_lock); if (stv090x_sleep(&state->frontend) < 0) { dprintk(FE_ERROR, 1, "Error putting device to sleep"); @@ -4335,10 +4454,10 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, goto error; } - dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n", + dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x", state->device == STV0900 ? "STV0900" : "STV0903", demod, - state->dev_ver); + state->internal->dev_ver); return &state->frontend; diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h index b133807663e..e009183ad77 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb/frontends/stv090x.h @@ -68,8 +68,6 @@ struct stv090x_config { u32 xtal; /* default: 8000000 */ u8 address; /* default: 0x68 */ - u32 ref_clk; /* default: 16000000 FIXME to tuner config */ - u8 ts1_mode; u8 ts2_mode; diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h index 5921a8d6c89..d38542665b0 100644 --- a/drivers/media/dvb/frontends/stv090x_priv.h +++ b/drivers/media/dvb/frontends/stv090x_priv.h @@ -230,11 +230,22 @@ struct stv090x_tab { s32 read; }; +struct stv090x_internal { + struct i2c_adapter *i2c_adap; + u8 i2c_addr; + + struct mutex demod_lock; /* Lock access to shared register */ + s32 mclk; /* Masterclock Divider factor */ + u32 dev_ver; + + int num_used; +}; + struct stv090x_state { enum stv090x_device device; enum stv090x_demodulator demod; enum stv090x_mode demod_mode; - u32 dev_ver; + struct stv090x_internal *internal; struct i2c_adapter *i2c; const struct stv090x_config *config; @@ -256,11 +267,8 @@ struct stv090x_state { u32 frequency; u32 srate; - s32 mclk; /* Masterclock Divider factor */ s32 tuner_bw; - u32 tuner_refclk; - s32 search_range; s32 DemodTimeout; diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e48380c4899..d9aa9bd31b8 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -435,7 +435,6 @@ static struct stv090x_config tt1600_stv090x_config = { .xtal = 27000000, .address = 0x68, - .ref_clk = 27000000, .ts1_mode = STV090x_TSMODE_DVBCI, .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -- cgit v1.2.3 From 96506a5086d0e9fd7332d6da74f115fa37bb58c6 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:20:21 -0300 Subject: V4L/DVB (13976): [STV090x] Added mutex protection around tuner I2C access. With this change it is possible to have the same I2C address for both tuners. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 9 +++++++++ drivers/media/dvb/frontends/stv090x_priv.h | 1 + 2 files changed, 10 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 9a817a69ed3..e903334a832 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -758,6 +758,9 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) struct stv090x_state *state = fe->demodulator_priv; u32 reg; + if (enable) + mutex_lock(&state->internal->tuner_lock); + reg = STV090x_READ_DEMOD(state, I2CRPT); if (enable) { dprintk(FE_DEBUG, 1, "Enable Gate"); @@ -771,9 +774,14 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) goto err; } + + if (!enable) + mutex_unlock(&state->internal->tuner_lock); + return 0; err: dprintk(FE_ERROR, 1, "I/O error"); + mutex_unlock(&state->internal->tuner_lock); return -1; } @@ -4439,6 +4447,7 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, } mutex_init(&state->internal->demod_lock); + mutex_init(&state->internal->tuner_lock); if (stv090x_sleep(&state->frontend) < 0) { dprintk(FE_ERROR, 1, "Error putting device to sleep"); diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h index d38542665b0..5b780c80d49 100644 --- a/drivers/media/dvb/frontends/stv090x_priv.h +++ b/drivers/media/dvb/frontends/stv090x_priv.h @@ -235,6 +235,7 @@ struct stv090x_internal { u8 i2c_addr; struct mutex demod_lock; /* Lock access to shared register */ + struct mutex tuner_lock; /* Lock access to tuners */ s32 mclk; /* Masterclock Divider factor */ u32 dev_ver; -- cgit v1.2.3 From 729cbafaca5e24b4fa0b42e7b0f79cb53f2ebad5 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:21:02 -0300 Subject: V4L/DVB (13977): [STV090x] Test for valid frequency before starting to tune Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index e903334a832..3bdbce21de9 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3393,6 +3393,9 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron struct stv090x_state *state = fe->demodulator_priv; struct dtv_frontend_properties *props = &fe->dtv_property_cache; + if (p->frequency == 0) + return DVBFE_ALGO_SEARCH_INVALID; + state->delsys = props->delivery_system; state->frequency = p->frequency; state->srate = p->u.qpsk.symbol_rate; -- cgit v1.2.3 From c369b7c2820dcad91b1354362097f6d8f9cf9307 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:21:30 -0300 Subject: V4L/DVB (13978): [STV090x] set FE_HAS_SIGNAL flag in stv090x_read_status when locked. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 3bdbce21de9..2a25dd15b7f 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3446,7 +3446,8 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { reg = STV090x_READ_DEMOD(state, TSSTATUS); if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { - *status = FE_HAS_CARRIER | + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; @@ -3463,7 +3464,11 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { reg = STV090x_READ_DEMOD(state, TSSTATUS); if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { - *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC | + FE_HAS_LOCK; } } } -- cgit v1.2.3 From f91e59cb5e6add13d4e45c5cc8d45a614e1dc8e4 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:22:07 -0300 Subject: V4L/DVB (13979): [STV090x] Added possibility to set a fixed TS output clock. This could be useful for p.e. Common Interface applications where data rate is limited. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 65 +++++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/stv090x.h | 2 ++ 2 files changed, 67 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 2a25dd15b7f..93be76ced89 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -4199,6 +4199,71 @@ static int stv090x_set_tspath(struct stv090x_state *state) default: break; } + + if (state->config->ts1_clk > 0) { + u32 speed; + + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + default: + speed = state->internal->mclk / + (state->config->ts1_clk / 4); + if (speed < 0x08) + speed = 0x08; + if (speed > 0xFF) + speed = 0xFF; + break; + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + speed = state->internal->mclk / + (state->config->ts1_clk / 32); + if (speed < 0x20) + speed = 0x20; + if (speed > 0xFF) + speed = 0xFF; + break; + } + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0) + goto err; + } + + if (state->config->ts2_clk > 0) { + u32 speed; + + switch (state->config->ts2_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + default: + speed = state->internal->mclk / + (state->config->ts2_clk / 4); + if (speed < 0x08) + speed = 0x08; + if (speed > 0xFF) + speed = 0xFF; + break; + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + speed = state->internal->mclk / + (state->config->ts2_clk / 32); + if (speed < 0x20) + speed = 0x20; + if (speed > 0xFF) + speed = 0xFF; + break; + } + reg = stv090x_read_reg(state, STV090x_P2_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0) + goto err; + } + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h index e009183ad77..96e3dc758e0 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb/frontends/stv090x.h @@ -70,6 +70,8 @@ struct stv090x_config { u8 ts1_mode; u8 ts2_mode; + u32 ts1_clk; + u32 ts2_clk; enum stv090x_i2crpt repeater_level; -- cgit v1.2.3 From 0c3f9fd807d9ef842fcc7e47e447ed2c68d63e49 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:22:45 -0300 Subject: V4L/DVB (13980): [STV6110x] Added function stv6110x_write_regs The function stv6110x_write_regs is used to write several registers at once. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv6110x.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index bcfcb652464..09e3aef8073 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c @@ -58,12 +58,23 @@ static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) return 0; } -static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) +static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len) { int ret; const struct stv6110x_config *config = stv6110x->config; - u8 buf[] = { reg, data }; - struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 }; + u8 buf[len + 1]; + struct i2c_msg msg = { + .addr = config->addr, + .flags = 0, + .buf = buf, + .len = len + 1 + }; + + if (start + len > 8) + return -EINVAL; + + buf[0] = start; + memcpy(&buf[1], data, len); ret = i2c_transfer(stv6110x->i2c, &msg, 1); if (ret != 1) { @@ -74,18 +85,21 @@ static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) return 0; } +static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) +{ + return stv6110x_write_regs(stv6110x, reg, &data, 1); +} + static int stv6110x_init(struct dvb_frontend *fe) { struct stv6110x_state *stv6110x = fe->tuner_priv; int ret; - u8 i; - for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) { - ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]); - if (ret < 0) { - dprintk(FE_ERROR, 1, "Initialization failed"); - return -1; - } + ret = stv6110x_write_regs(stv6110x, 0, stv6110x_regs, + ARRAY_SIZE(stv6110x_regs)); + if (ret < 0) { + dprintk(FE_ERROR, 1, "Initialization failed"); + return -1; } return 0; -- cgit v1.2.3 From ec2d3a62eff54b9dc556e9d9c9125b9bdc640171 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:23:13 -0300 Subject: V4L/DVB (13981): [STV6110x] Add a local register map for each instance of the driver. Before there was used a static register map that could lead to issues when there are are multiple adapters with the STV6110(A). Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv6110x.c | 120 ++++++++++++++-------------- drivers/media/dvb/frontends/stv6110x_priv.h | 1 + 2 files changed, 61 insertions(+), 60 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index 09e3aef8073..945790ef3a4 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c @@ -35,8 +35,6 @@ static unsigned int verbose; module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "Set Verbosity level"); -static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; - static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) { int ret; @@ -95,8 +93,8 @@ static int stv6110x_init(struct dvb_frontend *fe) struct stv6110x_state *stv6110x = fe->tuner_priv; int ret; - ret = stv6110x_write_regs(stv6110x, 0, stv6110x_regs, - ARRAY_SIZE(stv6110x_regs)); + ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs, + ARRAY_SIZE(stv6110x->regs)); if (ret < 0) { dprintk(FE_ERROR, 1, "Initialization failed"); return -1; @@ -112,23 +110,23 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000; u8 i; - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); if (frequency <= 1023000) { - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); pVal = 40; } else if (frequency <= 1300000) { - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); pVal = 40; } else if (frequency <= 2046000) { - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); pVal = 20; } else { - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); pVal = 20; } @@ -144,21 +142,21 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; divider = (divider + 5) / 10; - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); /* VCO Auto calibration */ - STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); - stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); - stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]); - stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]); - stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); + stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]); + stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]); + stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]); + stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]); for (i = 0; i < TRIALS; i++) { - stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); - if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1])) + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); + if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1])) break; msleep(1); } @@ -170,14 +168,14 @@ static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct stv6110x_state *stv6110x = fe->tuner_priv; - stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]); - stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]); + stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]); + stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]); - *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]), - STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz; + *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]), + STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz; - *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) + - STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1]))); + *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) + + STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1]))); *frequency >>= 2; @@ -193,27 +191,27 @@ static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) halfbw = bandwidth >> 1; if (halfbw > 36000000) - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ else if (halfbw < 5000000) - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ else - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ - STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ + STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ - stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); - stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); + stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]); + stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]); for (i = 0; i < TRIALS; i++) { - stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); - if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1])) + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); + if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1])) break; msleep(1); } - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ - stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ + stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]); return 0; } @@ -222,8 +220,8 @@ static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) { struct stv6110x_state *stv6110x = fe->tuner_priv; - stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]); - *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000; + stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]); + *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000; return 0; } @@ -236,20 +234,20 @@ static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock) switch (refclock) { default: case 1: - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); break; case 2: - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); break; case 4: - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); break; case 8: case 0: - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); break; } - stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); + stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]); return 0; } @@ -258,8 +256,8 @@ static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain) { struct stv6110x_state *stv6110x = fe->tuner_priv; - stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]); - *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]); + stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]); + *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]); return 0; } @@ -268,8 +266,8 @@ static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain) { struct stv6110x_state *stv6110x = fe->tuner_priv; - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); - stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); + stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]); return 0; } @@ -281,19 +279,19 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode) switch (mode) { case TUNER_SLEEP: - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0); break; case TUNER_WAKE: - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1); - STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1); + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1); break; } - ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); + ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]); if (ret < 0) { dprintk(FE_ERROR, 1, "I/O Error"); return -EIO; @@ -311,9 +309,9 @@ static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) { struct stv6110x_state *stv6110x = fe->tuner_priv; - stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); - if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1])) + if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1])) *status = TUNER_PHASELOCKED; else *status = 0; @@ -363,6 +361,7 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c) { struct stv6110x_state *stv6110x; + u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); if (stv6110x == NULL) @@ -371,6 +370,7 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, stv6110x->i2c = i2c; stv6110x->config = config; stv6110x->devctl = &stv6110x_ctl; + memcpy(stv6110x->regs, default_regs, 8); fe->tuner_priv = stv6110x; fe->ops.tuner_ops = stv6110x_ops; diff --git a/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb/frontends/stv6110x_priv.h index 7260da633d4..0ec936a660a 100644 --- a/drivers/media/dvb/frontends/stv6110x_priv.h +++ b/drivers/media/dvb/frontends/stv6110x_priv.h @@ -68,6 +68,7 @@ struct stv6110x_state { struct i2c_adapter *i2c; const struct stv6110x_config *config; + u8 regs[8]; struct stv6110x_devctl *devctl; }; -- cgit v1.2.3 From 9045e729447192ab0ca27191ccab324c6b97fceb Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:23:41 -0300 Subject: V4L/DVB (13982): [STV090x] setup master clock in stv090x_init instead of stv090x_setup. This is needed when clock input is driven from tuner and an output divider different from 1 is used. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 93be76ced89..4dc30911f40 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -4292,6 +4292,15 @@ static int stv090x_init(struct dvb_frontend *fe) const struct stv090x_config *config = state->config; u32 reg; + if (state->internal->mclk == 0) { + stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ + msleep(5); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, + 0x20 | config->clk_mode) < 0) + goto err; + stv090x_get_mclk(state); + } + if (stv090x_wakeup(fe) < 0) { dprintk(FE_ERROR, 1, "Error waking device"); goto err; @@ -4426,12 +4435,6 @@ static int stv090x_setup(struct dvb_frontend *fe) if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) goto err; - stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ - msleep(5); - if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) - goto err; - stv090x_get_mclk(state); - return 0; err: dprintk(FE_ERROR, 1, "I/O error"); -- cgit v1.2.3 From ca108b39a75d9c6e8a18c8723ccb9c98fb8d6265 Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:24:10 -0300 Subject: V4L/DVB (13983): [STV6110x] add clk_div member to stv6110x_config structure Using clk_div member of stv6110x_config structure the tuner's clock output divider can be configured. It is set in stv6110x_attach. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv6110x.c | 38 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/stv6110x.h | 1 + 2 files changed, 39 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index 945790ef3a4..f931ed07e92 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c @@ -362,6 +362,7 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, { struct stv6110x_state *stv6110x; u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; + int ret; stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); if (stv6110x == NULL) @@ -372,6 +373,43 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, stv6110x->devctl = &stv6110x_ctl; memcpy(stv6110x->regs, default_regs, 8); + /* setup divider */ + switch (stv6110x->config->clk_div) { + default: + case 1: + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); + break; + case 2: + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); + break; + case 4: + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); + break; + case 8: + case 0: + STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); + break; + } + + if (fe->ops.i2c_gate_ctrl) { + ret = fe->ops.i2c_gate_ctrl(fe, 1); + if (ret < 0) + goto error; + } + + ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs, + ARRAY_SIZE(stv6110x->regs)); + if (ret < 0) { + dprintk(FE_ERROR, 1, "Initialization failed"); + goto error; + } + + if (fe->ops.i2c_gate_ctrl) { + ret = fe->ops.i2c_gate_ctrl(fe, 0); + if (ret < 0) + goto error; + } + fe->tuner_priv = stv6110x; fe->ops.tuner_ops = stv6110x_ops; diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h index a38257080e0..2429ae6d784 100644 --- a/drivers/media/dvb/frontends/stv6110x.h +++ b/drivers/media/dvb/frontends/stv6110x.h @@ -26,6 +26,7 @@ struct stv6110x_config { u8 addr; u32 refclk; + u8 clk_div; /* divisor value for the output clock */ }; enum tuner_mode { -- cgit v1.2.3 From 93e32cdafbe70d66bd8c133dd1b663198723654f Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:24:32 -0300 Subject: V4L/DVB (13984): [BUDGET] Use a tuner clock output divider of 2 for TT S2-1600. This gives the STV090x and improved clock signal (rectangle instead of sine). Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index d9aa9bd31b8..9fdf26cc699 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -433,7 +433,7 @@ static struct stv090x_config tt1600_stv090x_config = { .demod_mode = STV090x_SINGLE, .clk_mode = STV090x_CLK_EXT, - .xtal = 27000000, + .xtal = 13500000, .address = 0x68, .ts1_mode = STV090x_TSMODE_DVBCI, @@ -456,6 +456,7 @@ static struct stv090x_config tt1600_stv090x_config = { static struct stv6110x_config tt1600_stv6110x_config = { .addr = 0x60, .refclk = 27000000, + .clk_div = 2, }; static struct isl6423_config tt1600_isl6423_config = { -- cgit v1.2.3 From 76b9ef97953c120172dfc07d48e6d219164c6f6a Mon Sep 17 00:00:00 2001 From: Andreas Regel Date: Tue, 5 Jan 2010 19:24:56 -0300 Subject: V4L/DVB (13985): [STV090x] reset mclk and dev_ver of internal structure after allocating When mclk is not 0 then it will never be set to the correct value and the Demodulator will not work. Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 4dc30911f40..3c5fba83882 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -4517,6 +4517,8 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, GFP_KERNEL); temp_int = append_internal(state->internal); state->internal->num_used = 1; + state->internal->mclk = 0; + state->internal->dev_ver = 0; state->internal->i2c_adap = state->i2c; state->internal->i2c_addr = state->config->address; dprintk(FE_INFO, 1, "Create New Internal Structure!"); -- cgit v1.2.3 From 2c1f750ba3fbd4a54544a68b57087bb89f3ba92c Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 10 Jan 2010 15:38:38 -0300 Subject: V4L/DVB (13986): [STV090x] Disable I2C gate on error The I2C gate must also be disabled, if a tuner command failed. Otherwise the tuner mutex would be locked forever. Signed-off-by: Oliver Endriss Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 3c5fba83882..cc487f6bdce 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1782,12 +1782,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) if (state->config->tuner_set_frequency) { if (state->config->tuner_set_frequency(fe, freq) < 0) - goto err; + goto err_gateoff; } if (state->config->tuner_set_bandwidth) { if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -1800,7 +1800,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) if (state->config->tuner_get_status) { if (state->config->tuner_get_status(fe, ®) < 0) - goto err; + goto err_gateoff; } if (reg) @@ -1819,6 +1819,9 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) srate_coarse = stv090x_get_srate(state, state->internal->mclk); return srate_coarse; + +err_gateoff: + stv090x_i2c_gate_ctrl(fe, 0); err: dprintk(FE_ERROR, 1, "I/O error"); return -1; @@ -2167,12 +2170,12 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) if (state->config->tuner_set_frequency) { if (state->config->tuner_set_frequency(fe, freq) < 0) - goto err; + goto err_gateoff; } if (state->config->tuner_set_bandwidth) { if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -2185,7 +2188,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) if (state->config->tuner_get_status) { if (state->config->tuner_get_status(fe, ®) < 0) - goto err; + goto err_gateoff; } if (reg) @@ -2216,6 +2219,8 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) return lock; +err_gateoff: + stv090x_i2c_gate_ctrl(fe, 0); err: dprintk(FE_ERROR, 1, "I/O error"); return -1; @@ -2589,7 +2594,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st if (state->config->tuner_get_frequency) { if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -2617,7 +2622,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st if (state->config->tuner_get_frequency) { if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -2637,6 +2642,9 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st } return STV090x_OUTOFRANGE; + +err_gateoff: + stv090x_i2c_gate_ctrl(fe, 0); err: dprintk(FE_ERROR, 1, "I/O error"); return -1; @@ -2995,7 +3003,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) if (state->config->tuner_set_bandwidth) { if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -3047,6 +3055,9 @@ static int stv090x_optimize_track(struct stv090x_state *state) stv090x_set_vit_thtracq(state); return 0; + +err_gateoff: + stv090x_i2c_gate_ctrl(fe, 0); err: dprintk(FE_ERROR, 1, "I/O error"); return -1; @@ -3227,17 +3238,17 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (state->config->tuner_set_bbgain) { if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */ - goto err; + goto err_gateoff; } if (state->config->tuner_set_frequency) { if (state->config->tuner_set_frequency(fe, state->frequency) < 0) - goto err; + goto err_gateoff; } if (state->config->tuner_set_bandwidth) { if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -3250,7 +3261,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (state->config->tuner_get_status) { if (state->config->tuner_get_status(fe, ®) < 0) - goto err; + goto err_gateoff; } if (reg) @@ -3383,6 +3394,8 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) } return signal_state; +err_gateoff: + stv090x_i2c_gate_ctrl(fe, 0); err: dprintk(FE_ERROR, 1, "I/O error"); return -1; @@ -4323,12 +4336,12 @@ static int stv090x_init(struct dvb_frontend *fe) if (config->tuner_set_mode) { if (config->tuner_set_mode(fe, TUNER_WAKE) < 0) - goto err; + goto err_gateoff; } if (config->tuner_init) { if (config->tuner_init(fe) < 0) - goto err; + goto err_gateoff; } if (stv090x_i2c_gate_ctrl(fe, 0) < 0) @@ -4338,6 +4351,9 @@ static int stv090x_init(struct dvb_frontend *fe) goto err; return 0; + +err_gateoff: + stv090x_i2c_gate_ctrl(fe, 0); err: dprintk(FE_ERROR, 1, "I/O error"); return -1; -- cgit v1.2.3 From 41894b97009adcabc51c6a4943045fd944c46236 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 10 Jan 2010 15:39:45 -0300 Subject: V4L/DVB (13987): [STV090x] Quit processing if the tuner did not lock Exit stv090x_algo() if the tuner did not lock. This might happen due to missing signal or invalid/incomplete tuning parameters. Signed-off-by: Oliver Endriss Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index cc487f6bdce..a5bae404701 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3256,21 +3256,21 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) msleep(50); - if (stv090x_i2c_gate_ctrl(fe, 1) < 0) - goto err; - if (state->config->tuner_get_status) { + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; if (state->config->tuner_get_status(fe, ®) < 0) goto err_gateoff; - } - - if (reg) - dprintk(FE_DEBUG, 1, "Tuner phase locked"); - else - dprintk(FE_DEBUG, 1, "Tuner unlocked"); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; - if (stv090x_i2c_gate_ctrl(fe, 0) < 0) - goto err; + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else { + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + return STV090x_NOCARRIER; + } + } msleep(10); agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1), -- cgit v1.2.3 From d8b5a8e449a08a1a87170144a42d0a0b167bcad6 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 10 Jan 2010 15:40:28 -0300 Subject: V4L/DVB (13988): [STV090x] Configuration parameters adc1_range, adc2_range, tuner_bbgain Add parameters adc1_range, adc2_range and tuner_bbgain to the config struct. Defaults: adc1_range = adc2_range = 2Vpp, tuner_bbgain = 10db Signed-off-by: Oliver Endriss Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 19 ++++++++++++++++++- drivers/media/dvb/frontends/stv090x.h | 9 +++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index a5bae404701..e1d4647b1a9 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -3237,7 +3237,10 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) goto err; if (state->config->tuner_set_bbgain) { - if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */ + reg = state->config->tuner_bbgain; + if (reg == 0) + reg = 10; /* default: 10dB */ + if (state->config->tuner_set_bbgain(fe, reg) < 0) goto err_gateoff; } @@ -4446,6 +4449,20 @@ static int stv090x_setup(struct dvb_frontend *fe) state->internal->dev_ver); } + /* ADC1 range */ + reg = stv090x_read_reg(state, STV090x_TSTTNR1); + STV090x_SETFIELD(reg, ADC1_INMODE_FIELD, + (config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1); + if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) + goto err; + + /* ADC2 range */ + reg = stv090x_read_reg(state, STV090x_TSTTNR3); + STV090x_SETFIELD(reg, ADC2_INMODE_FIELD, + (config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1); + if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) goto err; if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h index 96e3dc758e0..30f01a6902a 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb/frontends/stv090x.h @@ -60,6 +60,11 @@ enum stv090x_i2crpt { STV090x_RPTLEVEL_2 = 7, }; +enum stv090x_adc_range { + STV090x_ADC_2Vpp = 0, + STV090x_ADC_1Vpp = 1 +}; + struct stv090x_config { enum stv090x_device device; enum stv090x_mode demod_mode; @@ -75,6 +80,10 @@ struct stv090x_config { enum stv090x_i2crpt repeater_level; + u8 tuner_bbgain; /* default: 10db */ + enum stv090x_adc_range adc1_range; /* default: 2Vpp */ + enum stv090x_adc_range adc2_range; /* default: 2Vpp */ + bool diseqc_envelope_mode; int (*tuner_init) (struct dvb_frontend *fe); -- cgit v1.2.3 From 225ee0ca190b2e5d1d20c6278b6369b987aaaddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arvo=20J=C3=A4rve?= Date: Sun, 10 Jan 2010 17:15:57 -0300 Subject: V4L/DVB (13989): [TDA8261] Fix TDA8261 I2C read bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TDA8261 driver would crash when reading more than a byte as described. ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff [ 8.430350] KNC1-2: MAC addr = 00:09:d6:65:2d:91 [ 8.610008] saa7146 (1) saa7146_i2c_writeout [irq]: timed out waiting for end of xfer [ 8.734457] stb0899_attach: Attaching STB0899 [ 8.768481] tda8261_attach: Attaching TDA8261 8PSK/QPSK tuner [ 8.768485] DVB: registering adapter 2 frontend 0 (STB0899 Multistandard)... Once I launch scan-s2: scan-s2 -vvvv -a 2 -s 1 -l UNIVERSAL /usr/share/dvb/dvb-s/Hotbird-13.0E I see the following via dmesg: [ 435.040017] saa7146 (1) saa7146_i2c_writeout [irq]: timed out waiting for end of xfer [ 435.778648] tda8261_get_bandwidth: Bandwidth=40000000 [ 435.781781] tda8261_get_bandwidth: Bandwidth=40000000 [ 435.783311] tda8261_set_state: Step size=1, Divider=1000, PG=0x793 (1939) [ 435.783512] tda8261_set_state: Waiting to Phase LOCK [ 435.810134] tda8261_get_status: Tuner Phase Locked [ 435.810137] tda8261_set_state: Tuner Phase locked: status=1 [ 435.810139] tda8261_set_frequency: Frequency=1939000 [ 435.810141] tda8261_get_frequency: Frequency=7574 [ 435.830008] tda8261_get_bandwidth: Bandwidth=40000000 [ 436.402814] tda8261_get_bandwidth: Bandwidth=40000000 [ 436.405946] tda8261_get_bandwidth: Bandwidth=40000000 [ 436.407458] general protection fault: 0000 [#1] SMP [ 436.407527] last sysfs file: /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor [ 436.407560] CPU 0 [ 436.407601] Modules linked in: tda8261 stb0899 dvb_pll mt352 lnbp21 budget_av saa7146_vv snd_hda_codec_realtek videodev stv0299 v4l1_compat coretemp snd_hda_intel v4l2_compat_ioctl32 i915 videobuf_dma_sg b2c2_flexcop_pci snd_hda_codec budget_ci videobuf_core b2c2_flexcop ir_common w83627ehf drm snd_hwdep cx24123 budget_core hwmon_vid snd_pcm cx24113 dvb_core iptable_filter snd_timer i2c_algo_bit ip_tables saa7146 s5h1420 snd ttpci_eeprom soundcore intel_agp video serio_raw pcspkr lp snd_page_alloc x_tables output parport pata_it8213 e1000e [ 436.408757] Pid: 1410, comm: kdvb-ad-2-fe-0 Not tainted 2.6.31-14-server #48-Ubuntu C2SBC-Q [ 436.408818] RIP: 0010:[] [] tda8261_set_state+0x51/0x250 [tda8261] [ 436.408903] RSP: 0018:ffff88013649bc70 EFLAGS: 00010283 [ 436.408945] RAX: 00000000000f1748 RBX: ffff880138870680 RCX: 0000000000000018 [ 436.408990] RDX: ffff88013649bcd0 RSI: 0000000000000001 RDI: ffff880135273010 [ 436.409035] RBP: ffff88013649bcc0 R08: 0000000000000001 R09: 0000000000000002 [ 436.409081] R10: ffff88013649bc40 R11: 0000000055555556 R12: 00000000001d9638 [ 436.409126] R13: 38ffffffa0261568 R14: 0000000000000000 R15: ffff880135273010 [ 436.409172] FS: 0000000000000000(0000) GS:ffff880028022000(0000) knlGS:0000000000000000 [ 436.409232] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b [ 436.409274] CR2: 00007fff925e4cd8 CR3: 000000013642a000 CR4: 00000000000406f0 [ 436.409320] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 436.409365] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 436.409411] Process kdvb-ad-2-fe-0 (pid: 1410, threadinfo ffff88013649a000, task ffff88013658ad60) [ 436.409473] Stack: [ 436.409508] ffff880136ee2af1 00000000bcd5d166 ffff000200000068 0000000035273000 [ 436.409608] <0> 0000000000000001 ffff880135273000 ffffffffa0265260 00003473bc000000 [ 436.409758] <0> 0000000000000000 ffff88013a4e05e0 ffff88013649bd00 ffffffffa025f133 [ 436.409938] Call Trace: [ 436.409978] [] tda8261_set_frequency+0x23/0x70 [budget_av] [ 436.410027] [] ? stb0899_i2c_gate_ctrl+0x49/0xf0 [stb0899] [ 436.410074] [] ? stb0899_write_reg+0x19/0x20 [stb0899] [ 436.410121] [] stb0899_dvbs_algo+0x3a2/0x13c8 [stb0899] [ 436.410170] [] ? i2c_transfer+0xbd/0x100 [ 436.410215] [] ? stb0899_write_regs+0xac/0x1b0 [stb0899] [ 436.410262] [] stb0899_search+0x489/0x750 [stb0899] [ 436.410308] [] ? down_interruptible+0x33/0x60 [ 436.410360] [] dvb_frontend_thread+0x57c/0x720 [dvb_core] [ 436.410407] [] ? autoremove_wake_function+0x0/0x40 [ 436.410457] [] ? dvb_frontend_thread+0x0/0x720 [dvb_core] [ 436.410504] [] kthread+0xa6/0xb0 [ 436.410547] [] child_rip+0xa/0x20 [ 436.410589] [] ? kthread+0x0/0xb0 [ 436.410631] [] ? child_rip+0x0/0x20 [ 436.410672] Code: 00 03 00 00 4c 8b 6b 10 c7 45 cc 00 00 00 00 0f 84 e8 01 00 00 44 8b 22 41 8d 84 24 10 81 f1 ff 3d 80 4f 12 00 0f 87 af 01 00 00 <41> 8b 75 04 31 d2 48 c7 c7 d8 46 02 a0 89 f0 8b 0c 85 f0 45 02 [ 436.411950] RIP [] tda8261_set_state+0x51/0x250 [tda8261] [ 436.412015] RSP [ 436.412064] ---[ end trace c1d7ae4d9e05c51b ]--- Signed-off-by: Arvo Järve Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda8261.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/tda8261.c b/drivers/media/dvb/frontends/tda8261.c index 320c3c36d8b..614afcec05f 100644 --- a/drivers/media/dvb/frontends/tda8261.c +++ b/drivers/media/dvb/frontends/tda8261.c @@ -39,7 +39,7 @@ static int tda8261_read(struct tda8261_state *state, u8 *buf) { const struct tda8261_config *config = state->config; int err = 0; - struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 2 }; + struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 1 }; if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) printk("%s: read error, err=%d\n", __func__, err); -- cgit v1.2.3 From 0726681a7080cef6a9fd414894690fac16418772 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Fri, 22 Jan 2010 16:01:44 -0300 Subject: V4L/DVB: 22-kHz set_tone fix for NetUP Dual DVB-S2-CI card. 22kHz logic controlled by demod 22-kHz tone can be driven in two ways: 1. LNBH24 can produce 22kHz continuous tone when TEN=1 ( 22 KHz tone output is always activated ). 2. LNBH24 can reproduce 22kHz tone timings from DSQIN or EXTM pin's when TEN=0. From LNBH24 datasheet: "In order to improve design flexibility an external tone input pin is available (EXTM). The EXTM is a Logic input pin which activates the 22 kHz tone output, on the VoTX pin, by using the LNBH24 integrated tone generator (similar to the DSQIN pin function). In fact, the output tone waveform characteristics will always be internally controlled by the LNBH24 tone generator and the EXTM signal will be used as a timing control for DiSEqC tone data encoding on the VoTX output." In NetUP Dual DVB-S2-CI card 22kHz tone timings on EXTM pin produced by STV0900 demod: .set_tone = stv0900_set_tone redefine to "set_tone = lnbp21_set_tone" is not correct for "NetUP Dual DVB-S2-CI card". Signed-off-by: Abylay Ospan Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lnbp21.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c index 49d2b1c1611..13437259eea 100644 --- a/drivers/media/dvb/frontends/lnbp21.c +++ b/drivers/media/dvb/frontends/lnbp21.c @@ -158,7 +158,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, /* override frontend ops */ fe->ops.set_voltage = lnbp21_set_voltage; fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - if (!fe->ops.set_tone) /* don't redefine */ + if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/ fe->ops.set_tone = lnbp21_set_tone; printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); -- cgit v1.2.3 From b4a0e816fbe2af815674c514588b6cb444ec5fd9 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 17 Jan 2010 10:32:26 -0300 Subject: V4L/DVB: Add Support for DVBWorld DVB-S2 PCI 2004D card The PCI card contains dm1105 PCI bridge and ds3000 demod. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/Kconfig | 1 + drivers/media/dvb/dm1105/dm1105.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index de3eeb0a8d6..695239227cb 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig @@ -8,6 +8,7 @@ config DVB_DM1105 select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE + select DVB_DS3000 if !DVB_FE_CUSTOMISE select VIDEO_IR help Support for cards based on the SDMC DM1105 PCI chip like diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index aadf803c261..033e1f35674 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -43,6 +43,7 @@ #include "si21xx.h" #include "cx24116.h" #include "z0194a.h" +#include "ds3000.h" #define UNSET (-1U) @@ -685,6 +686,10 @@ static struct cx24116_config serit_sp2633_config = { .demod_address = 0x55, }; +static struct ds3000_config dvbworld_ds3000_config = { + .demod_address = 0x68, +}; + static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) { int ret; @@ -694,6 +699,14 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) dm1105dvb->fe = dvb_attach( cx24116_attach, &serit_sp2633_config, &dm1105dvb->i2c_adap); + if (dm1105dvb->fe) { + dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; + break; + } + + dm1105dvb->fe = dvb_attach( + ds3000_attach, &dvbworld_ds3000_config, + &dm1105dvb->i2c_adap); if (dm1105dvb->fe) dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; -- cgit v1.2.3 From ed7c847aef137a5e1f5de0eac0ad2c03e183839d Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 17 Jan 2010 11:15:06 -0300 Subject: V4L/DVB: dm1105: connect splitted else-if statements Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 66 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 033e1f35674..cc6577c4c12 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -346,41 +346,19 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, goto err; msgs[i].buf[byte] = rc; } - } else { - if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { - /* prepaired for cx24116 firmware */ - /* Write in small blocks */ - len = msgs[i].len - 1; - k = 1; - do { - outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT)); - outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1)); - for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { - data = msgs[i].buf[k+byte]; - outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2)); - } - outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR)); - for (j = 0; j < 25; j++) { - mdelay(10); - status = inb(dm_io_mem(DM1105_I2CSTS)); - if ((status & 0xc0) == 0x40) - break; - } - - if (j >= 25) - return -1; - - k += 48; - len -= 48; - } while (len > 0); - } else { - /* write bytes */ - outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT)); - for (byte = 0; byte < msgs[i].len; byte++) { - data = msgs[i].buf[byte]; - outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1)); + } else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { + /* prepaired for cx24116 firmware */ + /* Write in small blocks */ + len = msgs[i].len - 1; + k = 1; + do { + outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT)); + outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1)); + for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { + data = msgs[i].buf[k + byte]; + outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2)); } - outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); + outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR)); for (j = 0; j < 25; j++) { mdelay(10); status = inb(dm_io_mem(DM1105_I2CSTS)); @@ -390,7 +368,27 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, if (j >= 25) return -1; + + k += 48; + len -= 48; + } while (len > 0); + } else { + /* write bytes */ + outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT)); + for (byte = 0; byte < msgs[i].len; byte++) { + data = msgs[i].buf[byte]; + outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1)); + } + outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); + for (j = 0; j < 25; j++) { + mdelay(10); + status = inb(dm_io_mem(DM1105_I2CSTS)); + if ((status & 0xc0) == 0x40) + break; } + + if (j >= 25) + return -1; } } return num; -- cgit v1.2.3 From 34d2f9bf189c36ef8642cf6b64e80dfb756d888f Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 17 Jan 2010 12:11:00 -0300 Subject: V4L/DVB: dm1105: use dm1105_dev & dev instead of dm1105dvb This is for better readability and smaller size of code. Also it is similar to other drivers. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 357 +++++++++++++++++++------------------- 1 file changed, 178 insertions(+), 179 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index cc6577c4c12..abc26adec2a 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -270,7 +270,7 @@ struct infrared { u32 ir_command; }; -struct dm1105dvb { +struct dm1105_dev { /* pci */ struct pci_dev *pdev; u8 __iomem *io_mem; @@ -309,17 +309,17 @@ struct dm1105dvb { spinlock_t lock; }; -#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) +#define dm_io_mem(reg) ((unsigned long)(&dev->io_mem[reg])) static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { - struct dm1105dvb *dm1105dvb ; + struct dm1105_dev *dev ; int addr, rc, i, j, k, len, byte, data; u8 status; - dm1105dvb = i2c_adap->algo_data; + dev = i2c_adap->algo_data; for (i = 0; i < num; i++) { outb(0x00, dm_io_mem(DM1105_I2CCTR)); if (msgs[i].flags & I2C_M_RD) { @@ -406,22 +406,22 @@ static struct i2c_algorithm dm1105_algo = { .functionality = functionality, }; -static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed) +static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed) { - return container_of(feed->demux, struct dm1105dvb, demux); + return container_of(feed->demux, struct dm1105_dev, demux); } -static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) +static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe) { - return container_of(fe->dvb, struct dm1105dvb, dvb_adapter); + return container_of(fe->dvb, struct dm1105_dev, dvb_adapter); } -static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); + struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; - switch (dm1105dvb->boardnr) { + switch (dev->boardnr) { case DM1105_BOARD_AXESS_DM05: lnb_mask = DM05_LNB_MASK; lnb_off = DM05_LNB_OFF; @@ -448,51 +448,56 @@ static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volta return 0; } -static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb) +static void dm1105_set_dma_addr(struct dm1105_dev *dev) { - outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR)); + outl(cpu_to_le32(dev->dma_addr), dm_io_mem(DM1105_STADR)); } -static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb) +static int __devinit dm1105_dma_map(struct dm1105_dev *dev) { - dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr); + dev->ts_buf = pci_alloc_consistent(dev->pdev, + 6 * DM1105_DMA_BYTES, + &dev->dma_addr); - return !dm1105dvb->ts_buf; + return !dev->ts_buf; } -static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) +static void dm1105_dma_unmap(struct dm1105_dev *dev) { - pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); + pci_free_consistent(dev->pdev, + 6 * DM1105_DMA_BYTES, + dev->ts_buf, + dev->dma_addr); } -static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) +static void dm1105_enable_irqs(struct dm1105_dev *dev) { outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); outb(1, dm_io_mem(DM1105_CR)); } -static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb) +static void dm1105_disable_irqs(struct dm1105_dev *dev) { outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK)); outb(0, dm_io_mem(DM1105_CR)); } -static int dm1105dvb_start_feed(struct dvb_demux_feed *f) +static int dm1105_start_feed(struct dvb_demux_feed *f) { - struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); + struct dm1105_dev *dev = feed_to_dm1105_dev(f); - if (dm1105dvb->full_ts_users++ == 0) - dm1105dvb_enable_irqs(dm1105dvb); + if (dev->full_ts_users++ == 0) + dm1105_enable_irqs(dev); return 0; } -static int dm1105dvb_stop_feed(struct dvb_demux_feed *f) +static int dm1105_stop_feed(struct dvb_demux_feed *f) { - struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); + struct dm1105_dev *dev = feed_to_dm1105_dev(f); - if (--dm1105dvb->full_ts_users == 0) - dm1105dvb_disable_irqs(dm1105dvb); + if (--dev->full_ts_users == 0) + dm1105_disable_irqs(dev); return 0; } @@ -516,42 +521,39 @@ static void dm1105_emit_key(struct work_struct *work) /* work handler */ static void dm1105_dmx_buffer(struct work_struct *work) { - struct dm1105dvb *dm1105dvb = - container_of(work, struct dm1105dvb, work); + struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work); unsigned int nbpackets; - u32 oldwrp = dm1105dvb->wrp; - u32 nextwrp = dm1105dvb->nextwrp; + u32 oldwrp = dev->wrp; + u32 nextwrp = dev->nextwrp; - if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && - (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && - (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { - dm1105dvb->PacketErrorCount++; + if (!((dev->ts_buf[oldwrp] == 0x47) && + (dev->ts_buf[oldwrp + 188] == 0x47) && + (dev->ts_buf[oldwrp + 188 * 2] == 0x47))) { + dev->PacketErrorCount++; /* bad packet found */ - if ((dm1105dvb->PacketErrorCount >= 2) && - (dm1105dvb->dmarst == 0)) { + if ((dev->PacketErrorCount >= 2) && + (dev->dmarst == 0)) { outb(1, dm_io_mem(DM1105_RST)); - dm1105dvb->wrp = 0; - dm1105dvb->PacketErrorCount = 0; - dm1105dvb->dmarst = 0; + dev->wrp = 0; + dev->PacketErrorCount = 0; + dev->dmarst = 0; return; } } if (nextwrp < oldwrp) { - memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, - dm1105dvb->ts_buf, nextwrp); - nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188; + memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp); + nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188; } else nbpackets = (nextwrp - oldwrp) / 188; - dm1105dvb->wrp = nextwrp; - dvb_dmx_swfilter_packets(&dm1105dvb->demux, - &dm1105dvb->ts_buf[oldwrp], nbpackets); + dev->wrp = nextwrp; + dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets); } -static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) +static irqreturn_t dm1105_irq(int irq, void *dev_id) { - struct dm1105dvb *dm1105dvb = dev_id; + struct dm1105_dev *dev = dev_id; /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS)); @@ -560,20 +562,20 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) switch (intsts) { case INTSTS_TSIRQ: case (INTSTS_TSIRQ | INTSTS_IR): - dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - + dev->nextwrp = inl(dm_io_mem(DM1105_WRP)) - inl(dm_io_mem(DM1105_STADR)); - queue_work(dm1105dvb->wq, &dm1105dvb->work); + queue_work(dev->wq, &dev->work); break; case INTSTS_IR: - dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); - schedule_work(&dm1105dvb->ir.work); + dev->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); + schedule_work(&dev->ir.work); break; } return IRQ_HANDLED; } -int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) +int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) { struct input_dev *input_dev; struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; @@ -615,14 +617,14 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) return err; } -void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) +void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105) { ir_input_unregister(dm1105->ir.input_dev); } -static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) +static int __devinit dm1105_hw_init(struct dm1105_dev *dev) { - dm1105dvb_disable_irqs(dm1105dvb); + dm1105_disable_irqs(dev); outb(0, dm_io_mem(DM1105_HOST_CTR)); @@ -632,8 +634,8 @@ static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) outw(0xc10a, dm_io_mem(DM1105_TSCTR)); /* map DMA and set address */ - dm1105dvb_dma_map(dm1105dvb); - dm1105dvb_set_dma_addr(dm1105dvb); + dm1105_dma_map(dev); + dm1105_set_dma_addr(dev); /* big buffer */ outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN)); outb(47, dm_io_mem(DM1105_INTCNT)); @@ -646,15 +648,15 @@ static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) return 0; } -static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb) +static void dm1105_hw_exit(struct dm1105_dev *dev) { - dm1105dvb_disable_irqs(dm1105dvb); + dm1105_disable_irqs(dev); /* IR disable */ outb(0, dm_io_mem(DM1105_IRCTR)); outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK)); - dm1105dvb_dma_unmap(dm1105dvb); + dm1105_dma_unmap(dev); } static struct stv0299_config sharp_z0194a_config = { @@ -688,78 +690,75 @@ static struct ds3000_config dvbworld_ds3000_config = { .demod_address = 0x68, }; -static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) +static int __devinit frontend_init(struct dm1105_dev *dev) { int ret; - switch (dm1105dvb->boardnr) { + switch (dev->boardnr) { case DM1105_BOARD_DVBWORLD_2004: - dm1105dvb->fe = dvb_attach( + dev->fe = dvb_attach( cx24116_attach, &serit_sp2633_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) { - dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; + &dev->i2c_adap); + if (dev->fe) { + dev->fe->ops.set_voltage = dm1105_set_voltage; break; } - dm1105dvb->fe = dvb_attach( + dev->fe = dvb_attach( ds3000_attach, &dvbworld_ds3000_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) - dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; + &dev->i2c_adap); + if (dev->fe) + dev->fe->ops.set_voltage = dm1105_set_voltage; break; case DM1105_BOARD_DVBWORLD_2002: case DM1105_BOARD_AXESS_DM05: default: - dm1105dvb->fe = dvb_attach( + dev->fe = dvb_attach( stv0299_attach, &sharp_z0194a_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) { - dm1105dvb->fe->ops.set_voltage = - dm1105dvb_set_voltage; - dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, - &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); + &dev->i2c_adap); + if (dev->fe) { + dev->fe->ops.set_voltage = dm1105_set_voltage; + dvb_attach(dvb_pll_attach, dev->fe, 0x60, + &dev->i2c_adap, DVB_PLL_OPERA1); break; } - dm1105dvb->fe = dvb_attach( + dev->fe = dvb_attach( stv0288_attach, &earda_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) { - dm1105dvb->fe->ops.set_voltage = - dm1105dvb_set_voltage; - dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, - &dm1105dvb->i2c_adap); + &dev->i2c_adap); + if (dev->fe) { + dev->fe->ops.set_voltage = dm1105_set_voltage; + dvb_attach(stb6000_attach, dev->fe, 0x61, + &dev->i2c_adap); break; } - dm1105dvb->fe = dvb_attach( + dev->fe = dvb_attach( si21xx_attach, &serit_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) - dm1105dvb->fe->ops.set_voltage = - dm1105dvb_set_voltage; + &dev->i2c_adap); + if (dev->fe) + dev->fe->ops.set_voltage = dm1105_set_voltage; } - if (!dm1105dvb->fe) { - dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n"); + if (!dev->fe) { + dev_err(&dev->pdev->dev, "could not attach frontend\n"); return -ENODEV; } - ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe); + ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe); if (ret < 0) { - if (dm1105dvb->fe->ops.release) - dm1105dvb->fe->ops.release(dm1105dvb->fe); - dm1105dvb->fe = NULL; + if (dev->fe->ops.release) + dev->fe->ops.release(dev->fe); + dev->fe = NULL; return ret; } return 0; } -static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) +static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac) { static u8 command[1] = { 0x28 }; @@ -777,47 +776,47 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) }, }; - dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); - dev_info(&dm1105dvb->pdev->dev, "MAC %pM\n", mac); + dm1105_i2c_xfer(&dev->i2c_adap, msg , 2); + dev_info(&dev->pdev->dev, "MAC %pM\n", mac); } static int __devinit dm1105_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct dm1105dvb *dm1105dvb; + struct dm1105_dev *dev; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; int ret = -ENOMEM; int i; - dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); - if (!dm1105dvb) + dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL); + if (!dev) return -ENOMEM; /* board config */ - dm1105dvb->nr = dm1105_devcount; - dm1105dvb->boardnr = UNSET; - if (card[dm1105dvb->nr] < ARRAY_SIZE(dm1105_boards)) - dm1105dvb->boardnr = card[dm1105dvb->nr]; - for (i = 0; UNSET == dm1105dvb->boardnr && + dev->nr = dm1105_devcount; + dev->boardnr = UNSET; + if (card[dev->nr] < ARRAY_SIZE(dm1105_boards)) + dev->boardnr = card[dev->nr]; + for (i = 0; UNSET == dev->boardnr && i < ARRAY_SIZE(dm1105_subids); i++) if (pdev->subsystem_vendor == dm1105_subids[i].subvendor && pdev->subsystem_device == dm1105_subids[i].subdevice) - dm1105dvb->boardnr = dm1105_subids[i].card; + dev->boardnr = dm1105_subids[i].card; - if (UNSET == dm1105dvb->boardnr) { - dm1105dvb->boardnr = DM1105_BOARD_UNKNOWN; + if (UNSET == dev->boardnr) { + dev->boardnr = DM1105_BOARD_UNKNOWN; dm1105_card_list(pdev); } dm1105_devcount++; - dm1105dvb->pdev = pdev; - dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; - dm1105dvb->PacketErrorCount = 0; - dm1105dvb->dmarst = 0; + dev->pdev = pdev; + dev->buffer_size = 5 * DM1105_DMA_BYTES; + dev->PacketErrorCount = 0; + dev->dmarst = 0; ret = pci_enable_device(pdev); if (ret < 0) @@ -833,47 +832,47 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, if (ret < 0) goto err_pci_disable_device; - dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); - if (!dm1105dvb->io_mem) { + dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); + if (!dev->io_mem) { ret = -EIO; goto err_pci_release_regions; } - spin_lock_init(&dm1105dvb->lock); - pci_set_drvdata(pdev, dm1105dvb); + spin_lock_init(&dev->lock); + pci_set_drvdata(pdev, dev); - ret = dm1105dvb_hw_init(dm1105dvb); + ret = dm1105_hw_init(dev); if (ret < 0) goto err_pci_iounmap; /* i2c */ - i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); - strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME); - dm1105dvb->i2c_adap.owner = THIS_MODULE; - dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; - dm1105dvb->i2c_adap.dev.parent = &pdev->dev; - dm1105dvb->i2c_adap.algo = &dm1105_algo; - dm1105dvb->i2c_adap.algo_data = dm1105dvb; - ret = i2c_add_adapter(&dm1105dvb->i2c_adap); + i2c_set_adapdata(&dev->i2c_adap, dev); + strcpy(dev->i2c_adap.name, DRIVER_NAME); + dev->i2c_adap.owner = THIS_MODULE; + dev->i2c_adap.class = I2C_CLASS_TV_DIGITAL; + dev->i2c_adap.dev.parent = &pdev->dev; + dev->i2c_adap.algo = &dm1105_algo; + dev->i2c_adap.algo_data = dev; + ret = i2c_add_adapter(&dev->i2c_adap); if (ret < 0) - goto err_dm1105dvb_hw_exit; + goto err_dm1105_hw_exit; /* dvb */ - ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME, + ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev, adapter_nr); if (ret < 0) goto err_i2c_del_adapter; - dvb_adapter = &dm1105dvb->dvb_adapter; + dvb_adapter = &dev->dvb_adapter; - dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac); + dm1105_read_mac(dev, dvb_adapter->proposed_mac); - dvbdemux = &dm1105dvb->demux; + dvbdemux = &dev->demux; dvbdemux->filternum = 256; dvbdemux->feednum = 256; - dvbdemux->start_feed = dm1105dvb_start_feed; - dvbdemux->stop_feed = dm1105dvb_stop_feed; + dvbdemux->start_feed = dm1105_start_feed; + dvbdemux->stop_feed = dm1105_stop_feed; dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); ret = dvb_dmx_init(dvbdemux); @@ -881,113 +880,113 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, goto err_dvb_unregister_adapter; dmx = &dvbdemux->dmx; - dm1105dvb->dmxdev.filternum = 256; - dm1105dvb->dmxdev.demux = dmx; - dm1105dvb->dmxdev.capabilities = 0; + dev->dmxdev.filternum = 256; + dev->dmxdev.demux = dmx; + dev->dmxdev.capabilities = 0; - ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter); + ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter); if (ret < 0) goto err_dvb_dmx_release; - dm1105dvb->hw_frontend.source = DMX_FRONTEND_0; + dev->hw_frontend.source = DMX_FRONTEND_0; - ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend); + ret = dmx->add_frontend(dmx, &dev->hw_frontend); if (ret < 0) goto err_dvb_dmxdev_release; - dm1105dvb->mem_frontend.source = DMX_MEMORY_FE; + dev->mem_frontend.source = DMX_MEMORY_FE; - ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend); + ret = dmx->add_frontend(dmx, &dev->mem_frontend); if (ret < 0) goto err_remove_hw_frontend; - ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend); + ret = dmx->connect_frontend(dmx, &dev->hw_frontend); if (ret < 0) goto err_remove_mem_frontend; - ret = frontend_init(dm1105dvb); + ret = frontend_init(dev); if (ret < 0) goto err_disconnect_frontend; - dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); - dm1105_ir_init(dm1105dvb); + dvb_net_init(dvb_adapter, &dev->dvbnet, dmx); + dm1105_ir_init(dev); - INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); - sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); - dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn); - if (!dm1105dvb->wq) + INIT_WORK(&dev->work, dm1105_dmx_buffer); + sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); + dev->wq = create_singlethread_workqueue(dev->wqn); + if (!dev->wq) goto err_dvb_net; - ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, - DRIVER_NAME, dm1105dvb); + ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED, + DRIVER_NAME, dev); if (ret < 0) goto err_workqueue; return 0; err_workqueue: - destroy_workqueue(dm1105dvb->wq); + destroy_workqueue(dev->wq); err_dvb_net: - dvb_net_release(&dm1105dvb->dvbnet); + dvb_net_release(&dev->dvbnet); err_disconnect_frontend: dmx->disconnect_frontend(dmx); err_remove_mem_frontend: - dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); + dmx->remove_frontend(dmx, &dev->mem_frontend); err_remove_hw_frontend: - dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); + dmx->remove_frontend(dmx, &dev->hw_frontend); err_dvb_dmxdev_release: - dvb_dmxdev_release(&dm1105dvb->dmxdev); + dvb_dmxdev_release(&dev->dmxdev); err_dvb_dmx_release: dvb_dmx_release(dvbdemux); err_dvb_unregister_adapter: dvb_unregister_adapter(dvb_adapter); err_i2c_del_adapter: - i2c_del_adapter(&dm1105dvb->i2c_adap); -err_dm1105dvb_hw_exit: - dm1105dvb_hw_exit(dm1105dvb); + i2c_del_adapter(&dev->i2c_adap); +err_dm1105_hw_exit: + dm1105_hw_exit(dev); err_pci_iounmap: - pci_iounmap(pdev, dm1105dvb->io_mem); + pci_iounmap(pdev, dev->io_mem); err_pci_release_regions: pci_release_regions(pdev); err_pci_disable_device: pci_disable_device(pdev); err_kfree: pci_set_drvdata(pdev, NULL); - kfree(dm1105dvb); + kfree(dev); return ret; } static void __devexit dm1105_remove(struct pci_dev *pdev) { - struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev); - struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter; - struct dvb_demux *dvbdemux = &dm1105dvb->demux; + struct dm1105_dev *dev = pci_get_drvdata(pdev); + struct dvb_adapter *dvb_adapter = &dev->dvb_adapter; + struct dvb_demux *dvbdemux = &dev->demux; struct dmx_demux *dmx = &dvbdemux->dmx; - dm1105_ir_exit(dm1105dvb); + dm1105_ir_exit(dev); dmx->close(dmx); - dvb_net_release(&dm1105dvb->dvbnet); - if (dm1105dvb->fe) - dvb_unregister_frontend(dm1105dvb->fe); + dvb_net_release(&dev->dvbnet); + if (dev->fe) + dvb_unregister_frontend(dev->fe); dmx->disconnect_frontend(dmx); - dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); - dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); - dvb_dmxdev_release(&dm1105dvb->dmxdev); + dmx->remove_frontend(dmx, &dev->mem_frontend); + dmx->remove_frontend(dmx, &dev->hw_frontend); + dvb_dmxdev_release(&dev->dmxdev); dvb_dmx_release(dvbdemux); dvb_unregister_adapter(dvb_adapter); - if (&dm1105dvb->i2c_adap) - i2c_del_adapter(&dm1105dvb->i2c_adap); + if (&dev->i2c_adap) + i2c_del_adapter(&dev->i2c_adap); - dm1105dvb_hw_exit(dm1105dvb); + dm1105_hw_exit(dev); synchronize_irq(pdev->irq); - free_irq(pdev->irq, dm1105dvb); - pci_iounmap(pdev, dm1105dvb->io_mem); + free_irq(pdev->irq, dev); + pci_iounmap(pdev, dev->io_mem); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); dm1105_devcount--; - kfree(dm1105dvb); + kfree(dev); } static struct pci_device_id dm1105_id_table[] __devinitdata = { -- cgit v1.2.3 From 5eb3291fe84b30a8e2fda31fd5fa44c40575f283 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 17 Jan 2010 12:23:04 -0300 Subject: V4L/DVB: dm1105: use macro for read/write registers This is for better readability and smaller size of code lines. Also it is for future improvements like GPIO handling. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 95 ++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 40 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index abc26adec2a..383cca378b8 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -311,6 +311,22 @@ struct dm1105_dev { #define dm_io_mem(reg) ((unsigned long)(&dev->io_mem[reg])) +#define dm_readb(reg) inb(dm_io_mem(reg)) +#define dm_writeb(reg, value) outb((value), (dm_io_mem(reg))) + +#define dm_readw(reg) inw(dm_io_mem(reg)) +#define dm_writew(reg, value) outw((value), (dm_io_mem(reg))) + +#define dm_readl(reg) inl(dm_io_mem(reg)) +#define dm_writel(reg, value) outl((value), (dm_io_mem(reg))) + +#define dm_andorl(reg, mask, value) \ + outl((inl(dm_io_mem(reg)) & ~(mask)) |\ + ((value) & (mask)), (dm_io_mem(reg))) + +#define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) +#define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) + static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { @@ -321,19 +337,19 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, dev = i2c_adap->algo_data; for (i = 0; i < num; i++) { - outb(0x00, dm_io_mem(DM1105_I2CCTR)); + dm_writeb(DM1105_I2CCTR, 0x00); if (msgs[i].flags & I2C_M_RD) { /* read bytes */ addr = msgs[i].addr << 1; addr |= 1; - outb(addr, dm_io_mem(DM1105_I2CDAT)); + dm_writeb(DM1105_I2CDAT, addr); for (byte = 0; byte < msgs[i].len; byte++) - outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1)); + dm_writeb(DM1105_I2CDAT + byte + 1, 0); - outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); + dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len); for (j = 0; j < 55; j++) { mdelay(10); - status = inb(dm_io_mem(DM1105_I2CSTS)); + status = dm_readb(DM1105_I2CSTS); if ((status & 0xc0) == 0x40) break; } @@ -341,7 +357,7 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, return -1; for (byte = 0; byte < msgs[i].len; byte++) { - rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1)); + rc = dm_readb(DM1105_I2CDAT + byte + 1); if (rc < 0) goto err; msgs[i].buf[byte] = rc; @@ -352,16 +368,16 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, len = msgs[i].len - 1; k = 1; do { - outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT)); - outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1)); + dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1); + dm_writeb(DM1105_I2CDAT + 1, 0xf7); for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { data = msgs[i].buf[k + byte]; - outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2)); + dm_writeb(DM1105_I2CDAT + byte + 2, data); } - outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR)); + dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len)); for (j = 0; j < 25; j++) { mdelay(10); - status = inb(dm_io_mem(DM1105_I2CSTS)); + status = dm_readb(DM1105_I2CSTS); if ((status & 0xc0) == 0x40) break; } @@ -374,15 +390,15 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, } while (len > 0); } else { /* write bytes */ - outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT)); + dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1); for (byte = 0; byte < msgs[i].len; byte++) { data = msgs[i].buf[byte]; - outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1)); + dm_writeb(DM1105_I2CDAT + byte + 1, data); } - outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); + dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len); for (j = 0; j < 25; j++) { mdelay(10); - status = inb(dm_io_mem(DM1105_I2CSTS)); + status = dm_readb(DM1105_I2CSTS); if ((status & 0xc0) == 0x40) break; } @@ -437,20 +453,20 @@ static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) lnb_18v = DM1105_LNB_18V; } - outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR)); + dm_writel(DM1105_GPIOCTR, lnb_mask); if (voltage == SEC_VOLTAGE_18) - outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL)); + dm_writel(DM1105_GPIOVAL, lnb_18v); else if (voltage == SEC_VOLTAGE_13) - outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL)); + dm_writel(DM1105_GPIOVAL, lnb_13v); else - outl(lnb_off, dm_io_mem(DM1105_GPIOVAL)); + dm_writel(DM1105_GPIOVAL, lnb_off); return 0; } static void dm1105_set_dma_addr(struct dm1105_dev *dev) { - outl(cpu_to_le32(dev->dma_addr), dm_io_mem(DM1105_STADR)); + dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr)); } static int __devinit dm1105_dma_map(struct dm1105_dev *dev) @@ -472,14 +488,14 @@ static void dm1105_dma_unmap(struct dm1105_dev *dev) static void dm1105_enable_irqs(struct dm1105_dev *dev) { - outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); - outb(1, dm_io_mem(DM1105_CR)); + dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK); + dm_writeb(DM1105_CR, 1); } static void dm1105_disable_irqs(struct dm1105_dev *dev) { - outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK)); - outb(0, dm_io_mem(DM1105_CR)); + dm_writeb(DM1105_INTMAK, INTMAK_IRM); + dm_writeb(DM1105_CR, 0); } static int dm1105_start_feed(struct dvb_demux_feed *f) @@ -533,7 +549,7 @@ static void dm1105_dmx_buffer(struct work_struct *work) /* bad packet found */ if ((dev->PacketErrorCount >= 2) && (dev->dmarst == 0)) { - outb(1, dm_io_mem(DM1105_RST)); + dm_writeb(DM1105_RST, 1); dev->wrp = 0; dev->PacketErrorCount = 0; dev->dmarst = 0; @@ -556,18 +572,17 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id) struct dm1105_dev *dev = dev_id; /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ - unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS)); - outb(intsts, dm_io_mem(DM1105_INTSTS)); + unsigned int intsts = dm_readb(DM1105_INTSTS); + dm_writeb(DM1105_INTSTS, intsts); switch (intsts) { case INTSTS_TSIRQ: case (INTSTS_TSIRQ | INTSTS_IR): - dev->nextwrp = inl(dm_io_mem(DM1105_WRP)) - - inl(dm_io_mem(DM1105_STADR)); + dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR); queue_work(dev->wq, &dev->work); break; case INTSTS_IR: - dev->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); + dev->ir.ir_command = dm_readl(DM1105_IRCODE); schedule_work(&dev->ir.work); break; } @@ -626,24 +641,24 @@ static int __devinit dm1105_hw_init(struct dm1105_dev *dev) { dm1105_disable_irqs(dev); - outb(0, dm_io_mem(DM1105_HOST_CTR)); + dm_writeb(DM1105_HOST_CTR, 0); /*DATALEN 188,*/ - outb(188, dm_io_mem(DM1105_DTALENTH)); + dm_writeb(DM1105_DTALENTH, 188); /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ - outw(0xc10a, dm_io_mem(DM1105_TSCTR)); + dm_writew(DM1105_TSCTR, 0xc10a); /* map DMA and set address */ dm1105_dma_map(dev); dm1105_set_dma_addr(dev); /* big buffer */ - outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN)); - outb(47, dm_io_mem(DM1105_INTCNT)); + dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES); + dm_writeb(DM1105_INTCNT, 47); /* IR NEC mode enable */ - outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR)); - outb(0, dm_io_mem(DM1105_IRMODE)); - outw(0, dm_io_mem(DM1105_SYSTEMCODE)); + dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK)); + dm_writeb(DM1105_IRMODE, 0); + dm_writew(DM1105_SYSTEMCODE, 0); return 0; } @@ -653,8 +668,8 @@ static void dm1105_hw_exit(struct dm1105_dev *dev) dm1105_disable_irqs(dev); /* IR disable */ - outb(0, dm_io_mem(DM1105_IRCTR)); - outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK)); + dm_writeb(DM1105_IRCTR, 0); + dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK); dm1105_dma_unmap(dev); } -- cgit v1.2.3 From 6e3924aa8dad3ac7d5cbfb4e27b6cdd2dc7b7e68 Mon Sep 17 00:00:00 2001 From: Thiago Farina Date: Sat, 16 Jan 2010 10:25:38 -0300 Subject: V4L/DVB: dvb-core: remove unnecessary casting of kmalloc drivers/media/dvb/dvb-core/dvb_frontend.c | 6 ++---- Signed-off-by: Thiago Farina Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index ca2060e0439..55ea260572b 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1536,8 +1536,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) return -EINVAL; - tvp = (struct dtv_property *) kmalloc(tvps->num * - sizeof(struct dtv_property), GFP_KERNEL); + tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); if (!tvp) { err = -ENOMEM; goto out; @@ -1569,8 +1568,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) return -EINVAL; - tvp = (struct dtv_property *) kmalloc(tvps->num * - sizeof(struct dtv_property), GFP_KERNEL); + tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); if (!tvp) { err = -ENOMEM; goto out; -- cgit v1.2.3 From 521e86eb4354080dc2d178e3d8a7ebd8f0e8b4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 16 Jan 2010 13:35:36 -0300 Subject: V4L/DVB: stv0900: make local functions static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functions stv0900_sw_algo() and stv0900_set_dvbs1_track_car_loop() are only used locally so mark them static. This will remove the following sparse warnings (see "make C=1"): * symbol 'stv0900_sw_algo' was not declared. Should it be static? * symbol 'stv0900_set_dvbs1_track_car_loop' was not declared. Should it be static? Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_sw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index 5161c288442..96a5a5e29ed 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c @@ -193,7 +193,7 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *intp, return lock; } -int stv0900_sw_algo(struct stv0900_internal *intp, +static int stv0900_sw_algo(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod) { int lock = FALSE, @@ -795,7 +795,7 @@ static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp, return prate; } -void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp, +static void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp, enum fe_stv0900_demod_num demod, u32 srate) { -- cgit v1.2.3 From 936c05e7f677640a9bc4d77354899f199d7d958f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 16 Jan 2010 13:41:43 -0300 Subject: V4L/DVB: stv0900: make more local functions static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some functions are only used locally so mark them static. This will remove the following sparse warnings (see "make C=1"): * symbol 'extract_mask_pos' was not declared. Should it be static? * symbol 'stv0900_initialize' was not declared. Should it be static? * symbol 'stv0900_get_mclk_freq' was not declared. Should it be static? * symbol 'stv0900_set_mclk' was not declared. Should it be static? * symbol 'stv0900_get_err_count' was not declared. Should it be static? Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 115dc01c223..74791d550dc 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -177,7 +177,7 @@ u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg) return buf; } -void extract_mask_pos(u32 label, u8 *mask, u8 *pos) +static void extract_mask_pos(u32 label, u8 *mask, u8 *pos) { u8 position = 0, i = 0; @@ -218,7 +218,7 @@ u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label) return val; } -enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) +static enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) { s32 i; @@ -282,7 +282,7 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) return STV0900_NO_ERROR; } -u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) +static u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) { u32 mclk = 90000000, div = 0, ad_div = 0; @@ -296,7 +296,7 @@ u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) return mclk; } -enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) +static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) { u32 m_div, clk_sel; @@ -334,7 +334,7 @@ enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) return STV0900_NO_ERROR; } -u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr, +static u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr, enum fe_stv0900_demod_num demod) { u32 lsb, msb, hsb, err_val; -- cgit v1.2.3 From 43e3e6d9df13da0c82b99e1144de053043545894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 16 Jan 2010 14:35:03 -0300 Subject: V4L/DVB: dib0090: cleanup dib0090_dcc_freq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'extern' is not needed at function definition. This will remove the following sparse warning (see "make C=1"): * function 'dib0090_dcc_freq' with external linkage has definition Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib0090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index 614552709a6..7eac178f57b 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c @@ -283,7 +283,7 @@ static int dib0090_sleep(struct dvb_frontend *fe) return 0; } -extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) +void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) { struct dib0090_state *state = fe->tuner_priv; if (fast) -- cgit v1.2.3 From 2c1fee024d86b718b3198f664747c9028776c751 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Tue, 19 Jan 2010 19:43:44 -0300 Subject: V4L/DVB: [Mantis] remove duplicated #include Remove duplicated #include('s) in drivers/media/dvb/mantis/mantis_hif.c drivers/media/dvb/mantis/mantis_pci.c Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 2 -- drivers/media/dvb/mantis/mantis_pci.c | 5 ----- 2 files changed, 7 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 7477dac628b..5772ebb3a69 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -22,8 +22,6 @@ #include #include -#include -#include #include #include "dmxdev.h" diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 6c7534af6b4..59feeb84aec 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -41,11 +41,6 @@ #include "dvb_frontend.h" #include "dvb_net.h" -#include -#include -#include -#include - #include "mantis_common.h" #include "mantis_reg.h" #include "mantis_pci.h" -- cgit v1.2.3 From 3fb80ef3bc0f2b1008e14f695dcb32415cbacc90 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 18 Nov 2009 16:02:01 -0300 Subject: V4L/DVB: firedtv: do not DMA-map stack addresses This is a portability fix and reduces stack usage. The DMA mapping API cannot map on-stack addresses, as explained in Documentation/DMA-mapping.txt. Convert the two cases of on-stack packet payload buffers in firedtv (payload of write requests in avc_write and of lock requests in cmp_lock) to slab-allocated memory. We use the 512 bytes sized FCP frame buffer in struct firedtv for this purpose. Previously it held only incoming FCP responses, now it holds pending FCP requests and is then overwriten by an FCP response from the tuner subunit. Ditto for CMP lock requests and responses. Accesses to the payload buffer are serialized by fdtv->avc_mutex. As a welcome side effect, stack usage of the AV/C transaction functions is reduced by 512 bytes. Alas, avc_register_remote_control() is a special case: It previously did not wait for a response. To fit better in with the other FCP transactions, let it wait for an interim response. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-1394.c | 9 +- drivers/media/dvb/firewire/firedtv-avc.c | 437 +++++++++++++++++------------- drivers/media/dvb/firewire/firedtv-dvb.c | 1 - drivers/media/dvb/firewire/firedtv-fw.c | 2 +- drivers/media/dvb/firewire/firedtv.h | 6 +- 5 files changed, 264 insertions(+), 191 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index 81a56293540..c3e0ec2dcfc 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c @@ -90,13 +90,14 @@ static inline struct node_entry *node_of(struct firedtv *fdtv) return container_of(fdtv->device, struct unit_directory, device)->ne; } -static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) +static int node_lock(struct firedtv *fdtv, u64 addr, void *data) { + quadlet_t *d = data; int ret; - ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, - (__force quadlet_t *)&data[1], (__force quadlet_t)data[0]); - data[0] = data[1]; + ret = hpsb_node_lock(node_of(fdtv), addr, + EXTCODE_COMPARE_SWAP, &d[1], d[0]); + d[0] = d[1]; return ret; } diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 50c42a4b972..8f310542075 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -74,7 +74,6 @@ #define EN50221_TAG_CA_INFO 0x9f8031 struct avc_command_frame { - int length; u8 ctype; u8 subunit; u8 opcode; @@ -82,7 +81,6 @@ struct avc_command_frame { }; struct avc_response_frame { - int length; u8 response; u8 subunit; u8 opcode; @@ -202,78 +200,65 @@ static void debug_pmt(char *msg, int length) 16, 1, msg, length, false); } -static int __avc_write(struct firedtv *fdtv, - const struct avc_command_frame *c, struct avc_response_frame *r) +static int avc_write(struct firedtv *fdtv) { int err, retry; - if (r) - fdtv->avc_reply_received = false; + fdtv->avc_reply_received = false; for (retry = 0; retry < 6; retry++) { if (unlikely(avc_debug)) - debug_fcp(&c->ctype, c->length); + debug_fcp(fdtv->avc_data, fdtv->avc_data_length); err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER, - (void *)&c->ctype, c->length); + fdtv->avc_data, fdtv->avc_data_length); if (err) { - fdtv->avc_reply_received = true; dev_err(fdtv->device, "FCP command write failed\n"); + return err; } - if (!r) - return 0; - /* * AV/C specs say that answers should be sent within 150 ms. * Time out after 200 ms. */ if (wait_event_timeout(fdtv->avc_wait, fdtv->avc_reply_received, - msecs_to_jiffies(200)) != 0) { - r->length = fdtv->response_length; - memcpy(&r->response, fdtv->response, r->length); - + msecs_to_jiffies(200)) != 0) return 0; - } } dev_err(fdtv->device, "FCP response timed out\n"); + return -ETIMEDOUT; } -static int avc_write(struct firedtv *fdtv, - const struct avc_command_frame *c, struct avc_response_frame *r) +static bool is_register_rc(struct avc_response_frame *r) { - int ret; - - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; - - ret = __avc_write(fdtv, c, r); - - mutex_unlock(&fdtv->avc_mutex); - return ret; + return r->opcode == AVC_OPCODE_VENDOR && + r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && + r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && + r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && + r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; } int avc_recv(struct firedtv *fdtv, void *data, size_t length) { - struct avc_response_frame *r = - data - offsetof(struct avc_response_frame, response); + struct avc_response_frame *r = data; if (unlikely(avc_debug)) debug_fcp(data, length); - if (length >= 8 && - r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && - r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && - r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && - r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) { - if (r->response == AVC_RESPONSE_CHANGED) { - fdtv_handle_rc(fdtv, - r->operand[4] << 8 | r->operand[5]); + if (length >= 8 && is_register_rc(r)) { + switch (r->response) { + case AVC_RESPONSE_CHANGED: + fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]); schedule_work(&fdtv->remote_ctrl_work); - } else if (r->response != AVC_RESPONSE_INTERIM) { + break; + case AVC_RESPONSE_INTERIM: + if (is_register_rc((void *)fdtv->avc_data)) + goto wake; + break; + default: dev_info(fdtv->device, "remote control result = %d\n", r->response); } @@ -285,9 +270,9 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length) return -EIO; } - memcpy(fdtv->response, data, length); - fdtv->response_length = length; - + memcpy(fdtv->avc_data, data, length); + fdtv->avc_data_length = length; +wake: fdtv->avc_reply_received = true; wake_up(&fdtv->avc_wait); @@ -319,9 +304,10 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand) * (not supported by the AVC standard) */ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, - struct dvb_frontend_parameters *params, - struct avc_command_frame *c) + struct dvb_frontend_parameters *params) { + struct avc_command_frame *c = (void *)fdtv->avc_data; + c->opcode = AVC_OPCODE_VENDOR; c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; @@ -370,16 +356,17 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, c->operand[13] = 0x1; c->operand[14] = 0xff; c->operand[15] = 0xff; - c->length = 20; + fdtv->avc_data_length = 20; } else { - c->length = 16; + fdtv->avc_data_length = 16; } } static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, - struct dvb_frontend_parameters *params, - struct avc_command_frame *c) + struct dvb_frontend_parameters *params) { + struct avc_command_frame *c = (void *)fdtv->avc_data; + c->opcode = AVC_OPCODE_DSD; c->operand[0] = 0; /* source plug */ @@ -441,14 +428,15 @@ static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, c->operand[21] = 0x00; /* Add PIDs to filter */ - c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4); + fdtv->avc_data_length = + ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4); } static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, - struct dvb_frontend_parameters *params, - struct avc_command_frame *c) + struct dvb_frontend_parameters *params) { struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; + struct avc_command_frame *c = (void *)fdtv->avc_data; c->opcode = AVC_OPCODE_DSD; @@ -544,15 +532,18 @@ static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, c->operand[16] = 0x00; /* network_ID[1] */ /* Add PIDs to filter */ - c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4); + fdtv->avc_data_length = + ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4); } int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -561,36 +552,41 @@ int avc_tuner_dsd(struct firedtv *fdtv, switch (fdtv->type) { case FIREDTV_DVB_S: - case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; - case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break; - case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break; + case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params); break; + case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params); break; + case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params); break; default: BUG(); } - - if (avc_write(fdtv, c, r) < 0) - return -EIO; - - msleep(500); + ret = avc_write(fdtv); #if 0 - /* FIXME: */ - /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ + /* + * FIXME: + * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller. + * Check for AVC_RESPONSE_ACCEPTED here instead? + */ if (status) *status = r->operand[2]; #endif - return 0; + mutex_unlock(&fdtv->avc_mutex); + + if (ret == 0) + msleep(500); + + return ret; } int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ - int pos, k; + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret, pos, k; if (pidc > 16 && pidc != 0xff) return -EINVAL; + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; + memset(c, 0, sizeof(*c)); c->ctype = AVC_CTYPE_CONTROL; @@ -615,21 +611,26 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) c->operand[pos++] = 0x00; /* filter_length */ } - c->length = ALIGN(3 + pos, 4); + fdtv->avc_data_length = ALIGN(3 + pos, 4); + ret = avc_write(fdtv); - if (avc_write(fdtv, c, r) < 0) - return -EIO; + /* FIXME: check response code? */ - msleep(50); - return 0; + mutex_unlock(&fdtv->avc_mutex); + + if (ret == 0) + msleep(50); + + return ret; } int avc_tuner_get_ts(struct firedtv *fdtv) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ - int sl; + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret, sl; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -650,20 +651,27 @@ int avc_tuner_get_ts(struct firedtv *fdtv) c->operand[8] = 0x00; /* valid_flags [1] */ c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */ - c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; + fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; + ret = avc_write(fdtv); - if (avc_write(fdtv, c, r) < 0) - return -EIO; + /* FIXME: check response code? */ - msleep(250); - return 0; + mutex_unlock(&fdtv->avc_mutex); + + if (ret == 0) + msleep(250); + + return ret; } int avc_identify_subunit(struct firedtv *fdtv) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -679,28 +687,33 @@ int avc_identify_subunit(struct firedtv *fdtv) c->operand[5] = 0x00; /* offset highbyte */ c->operand[6] = 0x0d; /* offset lowbyte */ - c->length = 12; - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); + if (ret < 0) + goto out; if ((r->response != AVC_RESPONSE_STABLE && r->response != AVC_RESPONSE_ACCEPTED) || (r->operand[3] << 8) + r->operand[4] != 8) { dev_err(fdtv->device, "cannot read subunit identifier\n"); - return -EINVAL; + ret = -EINVAL; } - return 0; +out: + mutex_unlock(&fdtv->avc_mutex); + + return ret; } #define SIZEOF_ANTENNA_INPUT_INFO 22 int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; - int length; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int length, ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -716,21 +729,23 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) c->operand[5] = 0x00; c->operand[6] = 0x00; - c->length = 12; - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); + if (ret < 0) + goto out; if (r->response != AVC_RESPONSE_STABLE && r->response != AVC_RESPONSE_ACCEPTED) { dev_err(fdtv->device, "cannot read tuner status\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } length = r->operand[9]; if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) { dev_err(fdtv->device, "got invalid tuner status\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } stat->active_system = r->operand[10]; @@ -766,18 +781,22 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) stat->ca_dvb_flag = r->operand[31] >> 3 & 1; stat->ca_error_flag = r->operand[31] >> 2 & 1; stat->ca_initialization_status = r->operand[31] >> 1 & 1; +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, char conttone, char nrdiseq, struct dvb_diseqc_master_cmd *diseqcmd) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; - int i, j, k; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int i, j, k, ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -805,23 +824,28 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, c->operand[i++] = burst; c->operand[i++] = conttone; - c->length = ALIGN(3 + i, 4); - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = ALIGN(3 + i, 4); + ret = avc_write(fdtv); + if (ret < 0) + goto out; if (r->response != AVC_RESPONSE_ACCEPTED) { dev_err(fdtv->device, "LNB control failed\n"); - return -EINVAL; + ret = -EINVAL; } +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } int avc_register_remote_control(struct firedtv *fdtv) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -834,9 +858,14 @@ int avc_register_remote_control(struct firedtv *fdtv) c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; - c->length = 8; + fdtv->avc_data_length = 8; + ret = avc_write(fdtv); - return avc_write(fdtv, c, NULL); + /* FIXME: check response code? */ + + mutex_unlock(&fdtv->avc_mutex); + + return ret; } void avc_remote_ctrl_work(struct work_struct *work) @@ -851,9 +880,11 @@ void avc_remote_ctrl_work(struct work_struct *work) #if 0 /* FIXME: unused */ int avc_tuner_host2ca(struct firedtv *fdtv) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -870,12 +901,14 @@ int avc_tuner_host2ca(struct firedtv *fdtv) c->operand[6] = 0; /* more/last */ c->operand[7] = 0; /* length */ - c->length = 12; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); - if (avc_write(fdtv, c, r) < 0) - return -EIO; + /* FIXME: check response code? */ - return 0; + mutex_unlock(&fdtv->avc_mutex); + + return ret; } #endif @@ -906,10 +939,12 @@ static int get_ca_object_length(struct avc_response_frame *r) int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; - int pos; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int pos, ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -924,10 +959,10 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ - c->length = 12; - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); + if (ret < 0) + goto out; /* FIXME: check response code and validate response data */ @@ -939,16 +974,20 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) app_info[4] = 0x01; memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]); *len = app_info[3] + 4; +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; - int pos; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int pos, ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -963,10 +1002,12 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ - c->length = 12; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); + if (ret < 0) + goto out; - if (avc_write(fdtv, c, r) < 0) - return -EIO; + /* FIXME: check response code and validate response data */ pos = get_ca_object_pos(r); app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff; @@ -976,15 +1017,19 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) app_info[4] = r->operand[pos + 0]; app_info[5] = r->operand[pos + 1]; *len = app_info[3] + 4; +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } int avc_ca_reset(struct firedtv *fdtv) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -1002,19 +1047,20 @@ int avc_ca_reset(struct firedtv *fdtv) c->operand[7] = 1; /* length */ c->operand[8] = 0; /* force hardware reset */ - c->length = 12; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); - if (avc_write(fdtv, c, r) < 0) - return -EIO; + /* FIXME: check response code? */ - return 0; + mutex_unlock(&fdtv->avc_mutex); + + return ret; } int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; int list_management; int program_info_length; int pmt_cmd_id; @@ -1022,10 +1068,14 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) int write_pos; int es_info_length; int crc32_csum; + int ret; if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT)) debug_pmt(msg, length); + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; + memset(c, 0, sizeof(*c)); c->ctype = AVC_CTYPE_CONTROL; @@ -1124,25 +1174,30 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; - c->length = ALIGN(3 + write_pos, 4); - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = ALIGN(3 + write_pos, 4); + ret = avc_write(fdtv); + if (ret < 0) + goto out; if (r->response != AVC_RESPONSE_ACCEPTED) { dev_err(fdtv->device, "CA PMT failed with response 0x%x\n", r->response); - return -EFAULT; + ret = -EFAULT; } +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -1159,23 +1214,27 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) c->operand[6] = 0; /* more/last */ c->operand[7] = 0; /* length */ - c->length = 12; - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); + if (ret < 0) + goto out; /* FIXME: check response code and validate response data */ *interval = r->operand[get_ca_object_pos(r)]; +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } int avc_ca_enter_menu(struct firedtv *fdtv) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ + struct avc_command_frame *c = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -1192,19 +1251,24 @@ int avc_ca_enter_menu(struct firedtv *fdtv) c->operand[6] = 0; /* more/last */ c->operand[7] = 0; /* length */ - c->length = 12; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); - if (avc_write(fdtv, c, r) < 0) - return -EIO; + /* FIXME: check response code? */ - return 0; + mutex_unlock(&fdtv->avc_mutex); + + return ret; } int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) { - char buffer[sizeof(struct avc_command_frame)]; - struct avc_command_frame *c = (void *)buffer; - struct avc_response_frame *r = (void *)buffer; + struct avc_command_frame *c = (void *)fdtv->avc_data; + struct avc_response_frame *r = (void *)fdtv->avc_data; + int ret; + + if (mutex_lock_interruptible(&fdtv->avc_mutex)) + return -EINTR; memset(c, 0, sizeof(*c)); @@ -1221,17 +1285,19 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) c->operand[6] = 0; /* more/last */ c->operand[7] = 0; /* length */ - c->length = 12; - - if (avc_write(fdtv, c, r) < 0) - return -EIO; + fdtv->avc_data_length = 12; + ret = avc_write(fdtv); + if (ret < 0) + goto out; /* FIXME: check response code and validate response data */ *len = get_ca_object_length(r); memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len); +out: + mutex_unlock(&fdtv->avc_mutex); - return 0; + return ret; } #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL @@ -1248,6 +1314,7 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data) dev_err(fdtv->device, "CMP: read I/O error\n"); mutex_unlock(&fdtv->avc_mutex); + return ret; } @@ -1258,11 +1325,17 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) if (mutex_lock_interruptible(&fdtv->avc_mutex)) return -EINTR; - ret = fdtv->backend->lock(fdtv, addr, data); + /* data[] is stack-allocated and should not be DMA-mapped. */ + memcpy(fdtv->avc_data, data, 8); + + ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data); if (ret < 0) dev_err(fdtv->device, "CMP: lock I/O error\n"); + else + memcpy(data, fdtv->avc_data, 8); mutex_unlock(&fdtv->avc_mutex); + return ret; } diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c index fc9996c13e1..079e8c5b047 100644 --- a/drivers/media/dvb/firewire/firedtv-dvb.c +++ b/drivers/media/dvb/firewire/firedtv-dvb.c @@ -277,7 +277,6 @@ struct firedtv *fdtv_alloc(struct device *dev, mutex_init(&fdtv->avc_mutex); init_waitqueue_head(&fdtv->avc_wait); - fdtv->avc_reply_received = true; mutex_init(&fdtv->demux_mutex); INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 6223bf01efe..7a3de16fba0 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -41,7 +41,7 @@ static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len, return rcode != RCODE_COMPLETE ? -EIO : 0; } -static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) +static int node_lock(struct firedtv *fdtv, u64 addr, void *data) { return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP); } diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h index 35080dbb3c6..78cc28f3691 100644 --- a/drivers/media/dvb/firewire/firedtv.h +++ b/drivers/media/dvb/firewire/firedtv.h @@ -73,7 +73,7 @@ struct input_dev; struct firedtv; struct firedtv_backend { - int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]); + int (*lock)(struct firedtv *fdtv, u64 addr, void *data); int (*read)(struct firedtv *fdtv, u64 addr, void *data); int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); int (*start_iso)(struct firedtv *fdtv); @@ -114,8 +114,8 @@ struct firedtv { unsigned long channel_active; u16 channel_pid[16]; - size_t response_length; - u8 response[512]; + int avc_data_length; + u8 avc_data[512]; }; /* firedtv-1394.c */ -- cgit v1.2.3 From 6385c5bf98a9922917a563af3fdbd514888fa4ac Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 18 Nov 2009 16:03:03 -0300 Subject: V4L/DVB: firedtv: remove check for interrupting signal FCP transactions as well as CMP transactions were serialized with mutex_lock_interruptible. It is extremely unlikly though that a signal will arrive while a concurrent process holds the mutex. And even if one does, the duration of a transaction is reasonably short (1.2 seconds if all retries time out, usually much shorter). Hence simplify the code to plain mutex_lock. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-avc.c | 51 +++++++++++--------------------- 1 file changed, 17 insertions(+), 34 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 8f310542075..e7064281121 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -542,8 +542,7 @@ int avc_tuner_dsd(struct firedtv *fdtv, struct avc_command_frame *c = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -584,8 +583,7 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) if (pidc > 16 && pidc != 0xff) return -EINVAL; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -629,8 +627,7 @@ int avc_tuner_get_ts(struct firedtv *fdtv) struct avc_command_frame *c = (void *)fdtv->avc_data; int ret, sl; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -670,8 +667,7 @@ int avc_identify_subunit(struct firedtv *fdtv) struct avc_response_frame *r = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -712,8 +708,7 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) struct avc_response_frame *r = (void *)fdtv->avc_data; int length, ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -795,8 +790,7 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, struct avc_response_frame *r = (void *)fdtv->avc_data; int i, j, k, ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -844,8 +838,7 @@ int avc_register_remote_control(struct firedtv *fdtv) struct avc_command_frame *c = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -883,8 +876,7 @@ int avc_tuner_host2ca(struct firedtv *fdtv) struct avc_command_frame *c = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -943,8 +935,7 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) struct avc_response_frame *r = (void *)fdtv->avc_data; int pos, ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -986,8 +977,7 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) struct avc_response_frame *r = (void *)fdtv->avc_data; int pos, ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -1028,8 +1018,7 @@ int avc_ca_reset(struct firedtv *fdtv) struct avc_command_frame *c = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -1073,8 +1062,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT)) debug_pmt(msg, length); - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -1196,8 +1184,7 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) struct avc_response_frame *r = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -1233,8 +1220,7 @@ int avc_ca_enter_menu(struct firedtv *fdtv) struct avc_command_frame *c = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -1267,8 +1253,7 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) struct avc_response_frame *r = (void *)fdtv->avc_data; int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); memset(c, 0, sizeof(*c)); @@ -1306,8 +1291,7 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data) { int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); ret = fdtv->backend->read(fdtv, addr, data); if (ret < 0) @@ -1322,8 +1306,7 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) { int ret; - if (mutex_lock_interruptible(&fdtv->avc_mutex)) - return -EINTR; + mutex_lock(&fdtv->avc_mutex); /* data[] is stack-allocated and should not be DMA-mapped. */ memcpy(fdtv->avc_data, data, 8); -- cgit v1.2.3 From 1e4348c85a2643441174cfb7073f8cb1a313366f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 18 Nov 2009 16:03:31 -0300 Subject: V4L/DVB: firedtv: reduce memset()s Before each FCP transdaction, the entire 512 bytes of the FCP frame were cleared, then values filled in. Clear only the bytes between filled-in bytes and end of the - request frame, or - response frame if data from a larger response will be needed, or - whole frame if data from a variable length response will be taken. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/firewire/firedtv-avc.c | 146 ++++++++++++++----------------- 1 file changed, 65 insertions(+), 81 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index e7064281121..1b31bebc27d 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -87,6 +87,21 @@ struct avc_response_frame { u8 operand[509]; }; +#define LAST_OPERAND (509 - 1) + +static inline void clear_operands(struct avc_command_frame *c, int from, int to) +{ + memset(&c->operand[from], 0, to - from + 1); +} + +static void pad_operands(struct avc_command_frame *c, int from) +{ + int to = ALIGN(from, 4); + + if (from <= to && to <= LAST_OPERAND) + clear_operands(c, from, to); +} + #define AVC_DEBUG_READ_DESCRIPTOR 0x0001 #define AVC_DEBUG_DSIT 0x0002 #define AVC_DEBUG_DSD 0x0004 @@ -303,8 +318,8 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand) * tuning command for setting the relative LNB frequency * (not supported by the AVC standard) */ -static void avc_tuner_tuneqpsk(struct firedtv *fdtv, - struct dvb_frontend_parameters *params) +static int avc_tuner_tuneqpsk(struct firedtv *fdtv, + struct dvb_frontend_parameters *params) { struct avc_command_frame *c = (void *)fdtv->avc_data; @@ -356,14 +371,15 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, c->operand[13] = 0x1; c->operand[14] = 0xff; c->operand[15] = 0xff; - fdtv->avc_data_length = 20; + + return 16; } else { - fdtv->avc_data_length = 16; + return 13; } } -static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, - struct dvb_frontend_parameters *params) +static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv, + struct dvb_frontend_parameters *params) { struct avc_command_frame *c = (void *)fdtv->avc_data; @@ -427,13 +443,11 @@ static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, c->operand[20] = 0x00; c->operand[21] = 0x00; - /* Add PIDs to filter */ - fdtv->avc_data_length = - ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4); + return 22 + add_pid_filter(fdtv, &c->operand[22]); } -static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, - struct dvb_frontend_parameters *params) +static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv, + struct dvb_frontend_parameters *params) { struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; struct avc_command_frame *c = (void *)fdtv->avc_data; @@ -531,32 +545,31 @@ static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, c->operand[15] = 0x00; /* network_ID[0] */ c->operand[16] = 0x00; /* network_ID[1] */ - /* Add PIDs to filter */ - fdtv->avc_data_length = - ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4); + return 17 + add_pid_filter(fdtv, &c->operand[17]); } int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params) { struct avc_command_frame *c = (void *)fdtv->avc_data; - int ret; + int pos, ret; mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; switch (fdtv->type) { case FIREDTV_DVB_S: - case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params); break; - case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params); break; - case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params); break; + case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break; + case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break; + case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break; default: BUG(); } + pad_operands(c, pos); + + fdtv->avc_data_length = ALIGN(3 + pos, 4); ret = avc_write(fdtv); #if 0 /* @@ -585,8 +598,6 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_DSD; @@ -608,6 +619,7 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) c->operand[pos++] = 0x00; /* tableID */ c->operand[pos++] = 0x00; /* filter_length */ } + pad_operands(c, pos); fdtv->avc_data_length = ALIGN(3 + pos, 4); ret = avc_write(fdtv); @@ -629,8 +641,6 @@ int avc_tuner_get_ts(struct firedtv *fdtv) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_DSIT; @@ -644,9 +654,12 @@ int avc_tuner_get_ts(struct firedtv *fdtv) c->operand[4] = 0x00; /* antenna number */ c->operand[5] = 0x0; /* system_specific_search_flags */ c->operand[6] = sl; /* system_specific_multiplex selection_length */ - c->operand[7] = 0x00; /* valid_flags [0] */ - c->operand[8] = 0x00; /* valid_flags [1] */ - c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */ + /* + * operand[7]: valid_flags[0] + * operand[8]: valid_flags[1] + * operand[7 + sl]: nr_of_dsit_sel_specs (always 0) + */ + clear_operands(c, 7, 24); fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; ret = avc_write(fdtv); @@ -669,8 +682,6 @@ int avc_identify_subunit(struct firedtv *fdtv) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_READ_DESCRIPTOR; @@ -682,6 +693,7 @@ int avc_identify_subunit(struct firedtv *fdtv) c->operand[4] = 0x08; /* length lowbyte */ c->operand[5] = 0x00; /* offset highbyte */ c->operand[6] = 0x0d; /* offset lowbyte */ + clear_operands(c, 7, 8); /* padding */ fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -710,19 +722,18 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_READ_DESCRIPTOR; c->operand[0] = DESCRIPTOR_TUNER_STATUS; c->operand[1] = 0xff; /* read_result_status */ - c->operand[2] = 0x00; /* reserved */ - c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */ - c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */ - c->operand[5] = 0x00; - c->operand[6] = 0x00; + /* + * operand[2]: reserved + * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8 + * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff + */ + clear_operands(c, 2, 31); fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -788,12 +799,10 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, { struct avc_command_frame *c = (void *)fdtv->avc_data; struct avc_response_frame *r = (void *)fdtv->avc_data; - int i, j, k, ret; + int pos, j, k, ret; mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -802,23 +811,21 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL; - c->operand[4] = voltage; c->operand[5] = nrdiseq; - i = 6; - + pos = 6; for (j = 0; j < nrdiseq; j++) { - c->operand[i++] = diseqcmd[j].msg_len; + c->operand[pos++] = diseqcmd[j].msg_len; for (k = 0; k < diseqcmd[j].msg_len; k++) - c->operand[i++] = diseqcmd[j].msg[k]; + c->operand[pos++] = diseqcmd[j].msg[k]; } + c->operand[pos++] = burst; + c->operand[pos++] = conttone; + pad_operands(c, pos); - c->operand[i++] = burst; - c->operand[i++] = conttone; - - fdtv->avc_data_length = ALIGN(3 + i, 4); + fdtv->avc_data_length = ALIGN(3 + pos, 4); ret = avc_write(fdtv); if (ret < 0) goto out; @@ -840,8 +847,6 @@ int avc_register_remote_control(struct firedtv *fdtv) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_NOTIFY; c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7; c->opcode = AVC_OPCODE_VENDOR; @@ -850,6 +855,7 @@ int avc_register_remote_control(struct firedtv *fdtv) c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; + c->operand[4] = 0; /* padding */ fdtv->avc_data_length = 8; ret = avc_write(fdtv); @@ -878,8 +884,6 @@ int avc_tuner_host2ca(struct firedtv *fdtv) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -890,8 +894,7 @@ int avc_tuner_host2ca(struct firedtv *fdtv) c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ - c->operand[6] = 0; /* more/last */ - c->operand[7] = 0; /* length */ + clear_operands(c, 6, 8); fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -937,8 +940,6 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_STATUS; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -949,6 +950,7 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ + clear_operands(c, 6, LAST_OPERAND); fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -979,8 +981,6 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_STATUS; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -991,6 +991,7 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ + clear_operands(c, 6, LAST_OPERAND); fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -1020,8 +1021,6 @@ int avc_ca_reset(struct firedtv *fdtv) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -1064,8 +1063,6 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_CONTROL; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -1096,7 +1093,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) c->operand[12] = 0x02; /* Table id=2 */ c->operand[13] = 0x80; /* Section syntax + length */ - /* c->operand[14] = XXXprogram_info_length + 12; */ + c->operand[15] = msg[1]; /* Program number */ c->operand[16] = msg[2]; c->operand[17] = 0x01; /* Version number=0 + current/next=1 */ @@ -1144,12 +1141,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) write_pos += es_info_length; } } - - /* CRC */ - c->operand[write_pos++] = 0x00; - c->operand[write_pos++] = 0x00; - c->operand[write_pos++] = 0x00; - c->operand[write_pos++] = 0x00; + write_pos += 4; /* CRC */ c->operand[7] = 0x82; c->operand[8] = (write_pos - 10) >> 8; @@ -1161,6 +1153,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff; c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; + pad_operands(c, write_pos); fdtv->avc_data_length = ALIGN(3 + write_pos, 4); ret = avc_write(fdtv); @@ -1186,8 +1179,6 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_STATUS; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -1198,8 +1189,7 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */ - c->operand[6] = 0; /* more/last */ - c->operand[7] = 0; /* length */ + clear_operands(c, 6, LAST_OPERAND); fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -1222,8 +1212,6 @@ int avc_ca_enter_menu(struct firedtv *fdtv) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_STATUS; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -1234,8 +1222,7 @@ int avc_ca_enter_menu(struct firedtv *fdtv) c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; - c->operand[6] = 0; /* more/last */ - c->operand[7] = 0; /* length */ + clear_operands(c, 6, 8); fdtv->avc_data_length = 12; ret = avc_write(fdtv); @@ -1255,8 +1242,6 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) mutex_lock(&fdtv->avc_mutex); - memset(c, 0, sizeof(*c)); - c->ctype = AVC_CTYPE_STATUS; c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; c->opcode = AVC_OPCODE_VENDOR; @@ -1267,8 +1252,7 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; c->operand[4] = 0; /* slot */ c->operand[5] = SFE_VENDOR_TAG_CA_MMI; - c->operand[6] = 0; /* more/last */ - c->operand[7] = 0; /* length */ + clear_operands(c, 6, LAST_OPERAND); fdtv->avc_data_length = 12; ret = avc_write(fdtv); -- cgit v1.2.3 From 2abf6dd8e8754db6b18a4d55d3e4425c0a22d280 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 26 Jan 2010 16:46:58 -0300 Subject: V4L/DVB: dvb/bt8xx: Clean-up init and exit functions The init and exit functions are needlessly complex. Remove the bloat: * Drop irrelevant/outdated comments. * Remove useless bt878_pci_driver_registered global variable. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/bt878.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 2a0886ad787..99d62094f90 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -576,8 +576,6 @@ static struct pci_driver bt878_pci_driver = { .remove = __devexit_p(bt878_remove), }; -static int bt878_pci_driver_registered; - /*******************************/ /* Module management functions */ /*******************************/ @@ -585,34 +583,23 @@ static int bt878_pci_driver_registered; static int __init bt878_init_module(void) { bt878_num = 0; - bt878_pci_driver_registered = 0; printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n", (BT878_VERSION_CODE >> 16) & 0xff, (BT878_VERSION_CODE >> 8) & 0xff, BT878_VERSION_CODE & 0xff); -/* - bt878_check_chipset(); -*/ - /* later we register inside of bt878_find_audio_dma() - * because we may want to ignore certain cards */ - bt878_pci_driver_registered = 1; + return pci_register_driver(&bt878_pci_driver); } static void __exit bt878_cleanup_module(void) { - if (bt878_pci_driver_registered) { - bt878_pci_driver_registered = 0; - pci_unregister_driver(&bt878_pci_driver); - } - return; + pci_unregister_driver(&bt878_pci_driver); } module_init(bt878_init_module); module_exit(bt878_cleanup_module); -//MODULE_AUTHOR("XXX"); MODULE_LICENSE("GPL"); /* -- cgit v1.2.3 From fb3ab105a5ef43b03d2788e9b124c7c69112682f Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 29 Aug 2009 15:31:49 -0300 Subject: V4L/DVB: stv0900: dereference of state->internal in fe_stv0900_error stv0900_init_internal() state->internal allocation may fail as well as the allocation of stv0900_first_inode or new_node->next_inode in append_internal(). Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 74791d550dc..e5791b2b913 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -1384,7 +1384,14 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, } else { state->internal = kmalloc(sizeof(struct stv0900_internal), GFP_KERNEL); + if (state->internal == NULL) + return STV0900_INVALID_HANDLE; temp_int = append_internal(state->internal); + if (temp_int == NULL) { + kfree(state->internal); + state->internal = NULL; + return STV0900_INVALID_HANDLE; + } state->internal->dmds_used = 1; state->internal->i2c_adap = state->i2c_adap; state->internal->i2c_addr = state->config->demod_address; -- cgit v1.2.3 From 3d36f5c652d9d1b4406b0f8f32d9452eaad8e33a Mon Sep 17 00:00:00 2001 From: Massimo Del Fedele Date: Sat, 24 Oct 2009 13:12:37 -0300 Subject: V4L/DVB: m920x: Add support for Pinnacle PCTV310e card Adds support to Pinnacle PCTV310e hybrid tuner card, for DVB-T and remote control, still no analog video. [mchehab@redhat.com: fix CodingStyle issues] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + drivers/media/dvb/dvb-usb/m920x.c | 141 ++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/m920x.h | 2 +- 3 files changed, 143 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index bc3581d58ce..90cdac7ccd8 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -209,6 +209,7 @@ #define USB_PID_PINNACLE_PCTV71E 0x022b #define USB_PID_PINNACLE_PCTV72E 0x0236 #define USB_PID_PINNACLE_PCTV73E 0x0237 +#define USB_PID_PINNACLE_PCTV310E 0x3211 #define USB_PID_PINNACLE_PCTV801E 0x023a #define USB_PID_PINNACLE_PCTV801E_SE 0x023b #define USB_PID_PINNACLE_PCTV73A 0x0243 diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index ef9b7bed13f..737ffa36ac9 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -16,6 +16,9 @@ #include "qt1010.h" #include "tda1004x.h" #include "tda827x.h" + +#include +#include "tuner-simple.h" #include /* debug */ @@ -158,11 +161,14 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) case 0x93: case 0x92: + case 0x83: /* pinnacle PCTV310e */ + case 0x82: m->rep_count = 0; *state = REMOTE_KEY_PRESSED; goto unlock; case 0x91: + case 0x81: /* pinnacle PCTV310e */ /* prevent immediate auto-repeat */ if (++m->rep_count > 2) *state = REMOTE_KEY_REPEAT; @@ -546,6 +552,14 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) +{ + dvb_attach(simple_tuner_attach, adap->fe, + &adap->dev->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3); + return 0; +} + /* device-specific initialization */ static struct m920x_inits megasky_rc_init [] = { { M9206_RC_INIT2, 0xa8 }, @@ -562,6 +576,18 @@ static struct m920x_inits tvwalkertwin_rc_init [] = { { } /* terminating entry */ }; +static struct m920x_inits pinnacle310e_init[] = { + /* without these the tuner don't work */ + { 0xff20, 0x9b }, + { 0xff22, 0x70 }, + + /* rc settings */ + { 0xff50, 0x80 }, + { M9206_RC_INIT1, 0x00 }, + { M9206_RC_INIT2, 0xff }, + { } /* terminating entry */ +}; + /* ir keymaps */ static struct dvb_usb_rc_key megasky_rc_keys [] = { { 0x0012, KEY_POWER }, @@ -602,11 +628,68 @@ static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { { 0x001e, KEY_VOLUMEUP }, }; +static struct dvb_usb_rc_key pinnacle310e_rc_keys[] = { + { 0x16, KEY_POWER }, + { 0x17, KEY_FAVORITES }, + { 0x0f, KEY_TEXT }, + { 0x48, KEY_MEDIA }, /* preview */ + { 0x1c, KEY_EPG }, + { 0x04, KEY_LIST }, /* record list */ + { 0x03, KEY_1 }, + { 0x01, KEY_2 }, + { 0x06, KEY_3 }, + { 0x09, KEY_4 }, + { 0x1d, KEY_5 }, + { 0x1f, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x19, KEY_8 }, + { 0x1b, KEY_9 }, + { 0x15, KEY_0 }, + { 0x0c, KEY_CANCEL }, + { 0x4a, KEY_CLEAR }, + { 0x13, KEY_BACK }, + { 0x00, KEY_TAB }, + { 0x4b, KEY_UP }, + { 0x4e, KEY_LEFT }, + { 0x52, KEY_RIGHT }, + { 0x51, KEY_DOWN }, + { 0x4f, KEY_ENTER }, /* could also be KEY_OK */ + { 0x1e, KEY_VOLUMEUP }, + { 0x0a, KEY_VOLUMEDOWN }, + { 0x05, KEY_CHANNELUP }, + { 0x02, KEY_CHANNELDOWN }, + { 0x11, KEY_RECORD }, + { 0x14, KEY_PLAY }, + { 0x4c, KEY_PAUSE }, + { 0x1a, KEY_STOP }, + { 0x40, KEY_REWIND }, + { 0x12, KEY_FASTFORWARD }, + { 0x41, KEY_PREVIOUSSONG }, /* Replay */ + { 0x42, KEY_NEXTSONG }, /* Skip */ + { 0x54, KEY_CAMERA }, /* Capture */ +/* { 0x50, KEY_SAP }, */ /* Sap */ + { 0x47, KEY_CYCLEWINDOWS }, /* Pip */ + { 0x4d, KEY_SCREEN }, /* FullScreen */ + { 0x08, KEY_SUBTITLE }, + { 0x0e, KEY_MUTE }, +/* { 0x49, KEY_LR }, */ /* L/R */ + { 0x07, KEY_SLEEP }, /* Hibernate */ + { 0x08, KEY_MEDIA }, /* A/V */ + { 0x0e, KEY_MENU }, /* Recall */ + { 0x45, KEY_ZOOMIN }, + { 0x46, KEY_ZOOMOUT }, + { 0x18, KEY_TV }, /* Red */ + { 0x53, KEY_VCR }, /* Green */ + { 0x5e, KEY_SAT }, /* Yellow */ + { 0x5f, KEY_PLAYER }, /* Blue */ +}; + /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; static struct dvb_usb_device_properties digivox_mini_ii_properties; static struct dvb_usb_device_properties tvwalkertwin_properties; static struct dvb_usb_device_properties dposh_properties; +static struct dvb_usb_device_properties pinnacle_pctv310e_properties; static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -652,6 +735,13 @@ static int m920x_probe(struct usb_interface *intf, goto found; } + ret = dvb_usb_device_init(intf, &pinnacle_pctv310e_properties, + THIS_MODULE, &d, adapter_nr); + if (ret == 0) { + rc_init_seq = pinnacle310e_init; + goto found; + } + return ret; } else { /* Another interface on a multi-tuner device */ @@ -682,6 +772,7 @@ static struct usb_device_id m920x_table [] = { USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, + { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, m920x_table); @@ -895,6 +986,56 @@ static struct dvb_usb_device_properties dposh_properties = { } }; +static struct dvb_usb_device_properties pinnacle_pctv310e_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = NULL, + + .rc_interval = 100, + .rc_key_map = pinnacle310e_rc_keys, + .rc_key_map_size = ARRAY_SIZE(pinnacle310e_rc_keys), + .rc_query = m920x_rc_query, + + .size_of_priv = sizeof(struct m920x_state), + + .identify_state = m920x_identify_state, + .num_adapters = 1, + .adapter = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 8, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, + + .frontend_attach = m920x_mt352_frontend_attach, + .tuner_attach = m920x_fmd1216me_tuner_attach, + + .stream = { + .type = USB_ISOC, + .count = 5, + .endpoint = 0x84, + .u = { + .isoc = { + .framesperurb = 128, + .framesize = 564, + .interval = 1, + } + } + }, + } }, + .i2c_algo = &m920x_i2c_algo, + + .num_device_descs = 1, + .devices = { + { "Pinnacle PCTV 310e", + { &m920x_table[6], NULL }, + { NULL }, + } + } +}; + static struct usb_driver m920x_driver = { .name = "dvb_usb_m920x", .probe = m920x_probe, diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h index 37532890acc..3c061518ffc 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/dvb/dvb-usb/m920x.h @@ -18,7 +18,7 @@ #define M9206_FW 0x30 #define M9206_MAX_FILTERS 8 -#define M9206_MAX_ADAPTERS 2 +#define M9206_MAX_ADAPTERS 4 /* sequences found in logs: -- cgit v1.2.3 From 5d26b6443292027314a2e2c9178140e60acd3587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Fri, 29 Jan 2010 17:42:17 -0300 Subject: V4L/DVB: smsir: make local variables static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the file local parameters static. This will remove the following sparse warnings (see "make C=1"): * warning: symbol 'ir_pos' was not declared. Should it be static? * warning: symbol 'ir_word' was not declared. Should it be static? * warning: symbol 'ir_toggle' was not declared. Should it be static? Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/smsir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c index e3d776feeac..a56eac76e0f 100644 --- a/drivers/media/dvb/siano/smsir.c +++ b/drivers/media/dvb/siano/smsir.c @@ -85,9 +85,9 @@ static struct keyboard_layout_map_t keyboard_layout_maps[] = { { } /* Terminating entry */ }; -u32 ir_pos; -u32 ir_word; -u32 ir_toggle; +static u32 ir_pos; +static u32 ir_word; +static u32 ir_toggle; #define RC5_PUSH_BIT(dst, bit, pos) \ { dst <<= 1; dst |= bit; pos++; } -- cgit v1.2.3 From 407df29363f10642d87dbe49854c97eb57c84c94 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 11:29:46 -0300 Subject: V4L/DVB: dvb: return -ENOMEM if kzalloc failed in dvb_usb_device_init() If in a cold state and the download succeeded ret is zero, but we should return -ENOMEM. Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index e331db8c77b..5d91f70d2d2 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -243,7 +243,7 @@ int dvb_usb_device_init(struct usb_interface *intf, d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); if (d == NULL) { err("no memory for 'struct dvb_usb_device'"); - return ret; + return -ENOMEM; } d->udev = udev; -- cgit v1.2.3 From 690c79ae7a0d928459ee6a09be781a2503c27e3e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 2 Feb 2010 19:40:50 -0300 Subject: V4L/DVB: drivers/media/dvb/frontends/stv090x.c: fix use-uninitialised drivers/media/dvb/frontends/stv090x.c: In function 'stv090x_blind_search': drivers/media/dvb/frontends/stv090x.c:1967: warning: 'coarse_fail' may be used uninitialized in this function Cc: Manu Abraham Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Reviewed-by: Manu Abraham Acked-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index e1d4647b1a9..a11a2eb27f5 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1964,7 +1964,8 @@ static int stv090x_blind_search(struct stv090x_state *state) u32 agc2, reg, srate_coarse; s32 cpt_fail, agc2_ovflw, i; u8 k_ref, k_max, k_min; - int coarse_fail, lock; + int coarse_fail = 0; + int lock; k_max = 110; k_min = 10; -- cgit v1.2.3 From 08c45cd58560f10e08e0ec4686845625b7030e8c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 2 Feb 2010 19:40:51 -0300 Subject: V4L/DVB: drivers/media/dvb/frontends/stv090x.c: fix use-uninitlalised Mad guess. Signed-off-by: Andrew Morton Reviewed-by: Manu Abraham Acked-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv090x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index a11a2eb27f5..c52c3357dc5 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -2047,7 +2047,7 @@ static int stv090x_chk_tmg(struct stv090x_state *state) u32 reg; s32 tmg_cpt = 0, i; u8 freq, tmg_thh, tmg_thl; - int tmg_lock; + int tmg_lock = 0; freq = STV090x_READ_DEMOD(state, CARFREQ); tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE); -- cgit v1.2.3 From 6c614044ff00bf3e7403ac6c4ed4e53db8c349f3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 22 Jan 2010 12:10:52 -0300 Subject: V4L/DVB: media: dvb/af9015, implement eeprom hashing This will be useful for matching of IR tables later. We read the eeprom anyway for dumping. Switch the dumping to print_hex_dump_bytes and compute hash above that by hash = 0; for (u32 VAL) in (eeprom): hash *= GOLDEN_RATIO_PRIME_32 hash += VAL; // while preserving endinaness The computation is moved earlier to the flow, namely from af9015_af9013_frontend_attach to af9015_read_config, so that we can access the sum in af9015_read_config already. Signed-off-by: Jiri Slaby Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 65 +++++++++++++++++++++++++------------- drivers/media/dvb/dvb-usb/af9015.h | 1 + 2 files changed, 44 insertions(+), 22 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 8b60a601fb8..9f8370f4cc8 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -21,6 +21,8 @@ * */ +#include + #include "af9015.h" #include "af9013.h" #include "mt2060.h" @@ -553,26 +555,45 @@ exit: return ret; } -/* dump eeprom */ -static int af9015_eeprom_dump(struct dvb_usb_device *d) +/* hash (and dump) eeprom */ +static int af9015_eeprom_hash(struct usb_device *udev) { - u8 reg, val; + static const unsigned int eeprom_size = 256; + unsigned int reg; + int ret; + u8 val, *eeprom; + struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; - for (reg = 0; ; reg++) { - if (reg % 16 == 0) { - if (reg) - deb_info(KERN_CONT "\n"); - deb_info(KERN_DEBUG "%02x:", reg); - } - if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) - deb_info(KERN_CONT " %02x", val); - else - deb_info(KERN_CONT " --"); - if (reg == 0xff) - break; + eeprom = kmalloc(eeprom_size, GFP_KERNEL); + if (eeprom == NULL) + return -ENOMEM; + + for (reg = 0; reg < eeprom_size; reg++) { + req.addr = reg; + ret = af9015_rw_udev(udev, &req); + if (ret) + goto free; + eeprom[reg] = val; } - deb_info(KERN_CONT "\n"); - return 0; + + if (dvb_usb_af9015_debug & 0x01) + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom, + eeprom_size); + + BUG_ON(eeprom_size % 4); + + af9015_config.eeprom_sum = 0; + for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) { + af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32; + af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]); + } + + deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum); + + ret = 0; +free: + kfree(eeprom); + return ret; } static int af9015_download_ir_table(struct dvb_usb_device *d) @@ -728,6 +749,11 @@ static int af9015_read_config(struct usb_device *udev) } if (ret) goto error; + + ret = af9015_eeprom_hash(udev); + if (ret) + goto error; + deb_info("%s: IR mode:%d\n", __func__, val); for (i = 0; i < af9015_properties_count; i++) { if (val == AF9015_IR_MODE_DISABLED) { @@ -1125,11 +1151,6 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) deb_info("%s: init I2C\n", __func__); ret = af9015_i2c_init(adap->dev); - - /* dump eeprom (debug) */ - ret = af9015_eeprom_dump(adap->dev); - if (ret) - return ret; } else { /* select I2C adapter */ i2c_adap = &state->i2c_adap; diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 931c8515830..ef36b183149 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -107,6 +107,7 @@ struct af9015_config { u16 mt2060_if1[2]; u16 firmware_size; u16 firmware_checksum; + u32 eeprom_sum; u8 *ir_table; u16 ir_table_size; }; -- cgit v1.2.3 From 634d2d757a435037576bac465a84a02a72c747b6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 22 Jan 2010 12:10:53 -0300 Subject: V4L/DVB: media: dvb/af9015, factor out remote setting This is just a code shuffle without functional changes. For easier review of later changes, i.e. preparation. Signed-off-by: Jiri Slaby Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 305 +++++++++++++++++++------------------ 1 file changed, 157 insertions(+), 148 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 9f8370f4cc8..9a799d2e879 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -732,12 +732,166 @@ error: return ret; } +static void af9015_set_remote_config(struct usb_device *udev, + struct dvb_usb_device_properties *props) +{ + if (dvb_usb_af9015_remote) { + /* load remote defined as module param */ + switch (dvb_usb_af9015_remote) { + case AF9015_REMOTE_A_LINK_DTU_M: + props->rc_key_map = + af9015_rc_keys_a_link; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_a_link); + af9015_config.ir_table = af9015_ir_table_a_link; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_a_link); + break; + case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: + props->rc_key_map = + af9015_rc_keys_msi; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_msi); + af9015_config.ir_table = af9015_ir_table_msi; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_msi); + break; + case AF9015_REMOTE_MYGICTV_U718: + props->rc_key_map = + af9015_rc_keys_mygictv; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_mygictv); + af9015_config.ir_table = + af9015_ir_table_mygictv; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_mygictv); + break; + case AF9015_REMOTE_DIGITTRADE_DVB_T: + props->rc_key_map = + af9015_rc_keys_digittrade; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_digittrade); + af9015_config.ir_table = + af9015_ir_table_digittrade; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_digittrade); + break; + case AF9015_REMOTE_AVERMEDIA_KS: + props->rc_key_map = + af9015_rc_keys_avermedia; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_avermedia); + af9015_config.ir_table = + af9015_ir_table_avermedia_ks; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_avermedia_ks); + break; + } + } else { + switch (le16_to_cpu(udev->descriptor.idVendor)) { + case USB_VID_LEADTEK: + props->rc_key_map = + af9015_rc_keys_leadtek; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_leadtek); + af9015_config.ir_table = + af9015_ir_table_leadtek; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_leadtek); + break; + case USB_VID_VISIONPLUS: + props->rc_key_map = + af9015_rc_keys_twinhan; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_twinhan); + af9015_config.ir_table = + af9015_ir_table_twinhan; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_twinhan); + break; + case USB_VID_KWORLD_2: + /* TODO: use correct rc keys */ + props->rc_key_map = + af9015_rc_keys_twinhan; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_twinhan); + af9015_config.ir_table = af9015_ir_table_kworld; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_kworld); + break; + /* Check USB manufacturer and product strings and try + to determine correct remote in case of chip vendor + reference IDs are used. */ + case USB_VID_AFATECH: + { + char manufacturer[10]; + memset(manufacturer, 0, sizeof(manufacturer)); + usb_string(udev, udev->descriptor.iManufacturer, + manufacturer, sizeof(manufacturer)); + if (!strcmp("Geniatech", manufacturer)) { + /* iManufacturer 1 Geniatech + iProduct 2 AF9015 */ + props->rc_key_map = + af9015_rc_keys_mygictv; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_mygictv); + af9015_config.ir_table = + af9015_ir_table_mygictv; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_mygictv); + } else if (!strcmp("MSI", manufacturer)) { + /* iManufacturer 1 MSI + iProduct 2 MSI K-VOX */ + props->rc_key_map = + af9015_rc_keys_msi; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_msi); + af9015_config.ir_table = + af9015_ir_table_msi; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_msi); + } else if (udev->descriptor.idProduct == + cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { + props->rc_key_map = + af9015_rc_keys_trekstor; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_trekstor); + af9015_config.ir_table = + af9015_ir_table_trekstor; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_trekstor); + } + break; + } + case USB_VID_AVERMEDIA: + props->rc_key_map = + af9015_rc_keys_avermedia; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_avermedia); + af9015_config.ir_table = + af9015_ir_table_avermedia; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_avermedia); + break; + case USB_VID_MSI_2: + props->rc_key_map = + af9015_rc_keys_msi_digivox_iii; + props->rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii); + af9015_config.ir_table = + af9015_ir_table_msi_digivox_iii; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_msi_digivox_iii); + break; + } + } +} + static int af9015_read_config(struct usb_device *udev) { int ret; u8 val, i, offset = 0; struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; - char manufacturer[10]; /* IR remote controller */ req.addr = AF9015_EEPROM_IR_MODE; @@ -759,153 +913,8 @@ static int af9015_read_config(struct usb_device *udev) if (val == AF9015_IR_MODE_DISABLED) { af9015_properties[i].rc_key_map = NULL; af9015_properties[i].rc_key_map_size = 0; - } else if (dvb_usb_af9015_remote) { - /* load remote defined as module param */ - switch (dvb_usb_af9015_remote) { - case AF9015_REMOTE_A_LINK_DTU_M: - af9015_properties[i].rc_key_map = - af9015_rc_keys_a_link; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_a_link); - af9015_config.ir_table = af9015_ir_table_a_link; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_a_link); - break; - case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: - af9015_properties[i].rc_key_map = - af9015_rc_keys_msi; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_msi); - af9015_config.ir_table = af9015_ir_table_msi; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_msi); - break; - case AF9015_REMOTE_MYGICTV_U718: - af9015_properties[i].rc_key_map = - af9015_rc_keys_mygictv; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_mygictv); - af9015_config.ir_table = - af9015_ir_table_mygictv; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_mygictv); - break; - case AF9015_REMOTE_DIGITTRADE_DVB_T: - af9015_properties[i].rc_key_map = - af9015_rc_keys_digittrade; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_digittrade); - af9015_config.ir_table = - af9015_ir_table_digittrade; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_digittrade); - break; - case AF9015_REMOTE_AVERMEDIA_KS: - af9015_properties[i].rc_key_map = - af9015_rc_keys_avermedia; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_avermedia); - af9015_config.ir_table = - af9015_ir_table_avermedia_ks; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_avermedia_ks); - break; - } - } else { - switch (le16_to_cpu(udev->descriptor.idVendor)) { - case USB_VID_LEADTEK: - af9015_properties[i].rc_key_map = - af9015_rc_keys_leadtek; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_leadtek); - af9015_config.ir_table = - af9015_ir_table_leadtek; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_leadtek); - break; - case USB_VID_VISIONPLUS: - af9015_properties[i].rc_key_map = - af9015_rc_keys_twinhan; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_twinhan); - af9015_config.ir_table = - af9015_ir_table_twinhan; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_twinhan); - break; - case USB_VID_KWORLD_2: - /* TODO: use correct rc keys */ - af9015_properties[i].rc_key_map = - af9015_rc_keys_twinhan; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_twinhan); - af9015_config.ir_table = af9015_ir_table_kworld; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_kworld); - break; - /* Check USB manufacturer and product strings and try - to determine correct remote in case of chip vendor - reference IDs are used. */ - case USB_VID_AFATECH: - memset(manufacturer, 0, sizeof(manufacturer)); - usb_string(udev, udev->descriptor.iManufacturer, - manufacturer, sizeof(manufacturer)); - if (!strcmp("Geniatech", manufacturer)) { - /* iManufacturer 1 Geniatech - iProduct 2 AF9015 */ - af9015_properties[i].rc_key_map = - af9015_rc_keys_mygictv; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_mygictv); - af9015_config.ir_table = - af9015_ir_table_mygictv; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_mygictv); - } else if (!strcmp("MSI", manufacturer)) { - /* iManufacturer 1 MSI - iProduct 2 MSI K-VOX */ - af9015_properties[i].rc_key_map = - af9015_rc_keys_msi; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_msi); - af9015_config.ir_table = - af9015_ir_table_msi; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_msi); - } else if (udev->descriptor.idProduct == - cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { - af9015_properties[i].rc_key_map = - af9015_rc_keys_trekstor; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_trekstor); - af9015_config.ir_table = - af9015_ir_table_trekstor; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_trekstor); - } - break; - case USB_VID_AVERMEDIA: - af9015_properties[i].rc_key_map = - af9015_rc_keys_avermedia; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_avermedia); - af9015_config.ir_table = - af9015_ir_table_avermedia; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_avermedia); - break; - case USB_VID_MSI_2: - af9015_properties[i].rc_key_map = - af9015_rc_keys_msi_digivox_iii; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii); - af9015_config.ir_table = - af9015_ir_table_msi_digivox_iii; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_msi_digivox_iii); - break; - } - } + } else + af9015_set_remote_config(udev, &af9015_properties[i]); } /* TS mode - one or two receivers */ -- cgit v1.2.3 From 26c3b8b060b3a06f912e5c50bc8ef6ed96195458 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 22 Jan 2010 12:10:54 -0300 Subject: V4L/DVB: media: dvb/af9015, refactor remote setting Add af9015_setup structure to hold (right now only remote) setup of distinct receivers. Add af9015_setup_match for matching ids against tables. This is for easier matching different kind of ids against tables to obtain setups. Currently module parameters and usb vendor ids are switched into and matched against tables. Hashes will follow. Signed-off-by: Jiri Slaby Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 222 +++++++++++++++---------------------- 1 file changed, 89 insertions(+), 133 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 9a799d2e879..03ba2fdee83 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -732,98 +732,80 @@ error: return ret; } +struct af9015_setup { + unsigned int id; + struct dvb_usb_rc_key *rc_key_map; + unsigned int rc_key_map_size; + u8 *ir_table; + unsigned int ir_table_size; +}; + +static const struct af9015_setup *af9015_setup_match(unsigned int id, + const struct af9015_setup *table) +{ + for (; table->rc_key_map; table++) + if (table->id == id) + return table; + return NULL; +} + +static const struct af9015_setup af9015_setup_modparam[] = { + { AF9015_REMOTE_A_LINK_DTU_M, + af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), + af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, + { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, + af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), + af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, + { AF9015_REMOTE_MYGICTV_U718, + af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv), + af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, + { AF9015_REMOTE_DIGITTRADE_DVB_T, + af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade), + af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, + { AF9015_REMOTE_AVERMEDIA_KS, + af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia), + af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) }, + { } +}; + +/* don't add new entries here anymore, use hashes instead */ +static const struct af9015_setup af9015_setup_usbids[] = { + { USB_VID_LEADTEK, + af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek), + af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, + { USB_VID_VISIONPLUS, + af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan), + af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, + { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ + af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan), + af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, + { USB_VID_AVERMEDIA, + af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia), + af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, + { USB_VID_MSI_2, + af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii), + af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) }, + { } +}; + static void af9015_set_remote_config(struct usb_device *udev, struct dvb_usb_device_properties *props) { + const struct af9015_setup *table = NULL; + if (dvb_usb_af9015_remote) { /* load remote defined as module param */ - switch (dvb_usb_af9015_remote) { - case AF9015_REMOTE_A_LINK_DTU_M: - props->rc_key_map = - af9015_rc_keys_a_link; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_a_link); - af9015_config.ir_table = af9015_ir_table_a_link; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_a_link); - break; - case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: - props->rc_key_map = - af9015_rc_keys_msi; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_msi); - af9015_config.ir_table = af9015_ir_table_msi; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_msi); - break; - case AF9015_REMOTE_MYGICTV_U718: - props->rc_key_map = - af9015_rc_keys_mygictv; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_mygictv); - af9015_config.ir_table = - af9015_ir_table_mygictv; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_mygictv); - break; - case AF9015_REMOTE_DIGITTRADE_DVB_T: - props->rc_key_map = - af9015_rc_keys_digittrade; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_digittrade); - af9015_config.ir_table = - af9015_ir_table_digittrade; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_digittrade); - break; - case AF9015_REMOTE_AVERMEDIA_KS: - props->rc_key_map = - af9015_rc_keys_avermedia; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_avermedia); - af9015_config.ir_table = - af9015_ir_table_avermedia_ks; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_avermedia_ks); - break; - } + table = af9015_setup_match(dvb_usb_af9015_remote, + af9015_setup_modparam); } else { - switch (le16_to_cpu(udev->descriptor.idVendor)) { - case USB_VID_LEADTEK: - props->rc_key_map = - af9015_rc_keys_leadtek; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_leadtek); - af9015_config.ir_table = - af9015_ir_table_leadtek; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_leadtek); - break; - case USB_VID_VISIONPLUS: - props->rc_key_map = - af9015_rc_keys_twinhan; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_twinhan); - af9015_config.ir_table = - af9015_ir_table_twinhan; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_twinhan); - break; - case USB_VID_KWORLD_2: - /* TODO: use correct rc keys */ - props->rc_key_map = - af9015_rc_keys_twinhan; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_twinhan); - af9015_config.ir_table = af9015_ir_table_kworld; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_kworld); - break; - /* Check USB manufacturer and product strings and try - to determine correct remote in case of chip vendor - reference IDs are used. */ - case USB_VID_AFATECH: - { + u16 vendor = le16_to_cpu(udev->descriptor.idVendor); + + if (vendor == USB_VID_AFATECH) { + /* Check USB manufacturer and product strings and try + to determine correct remote in case of chip vendor + reference IDs are used. + DO NOT ADD ANYTHING NEW HERE. Use hashes instead. + */ char manufacturer[10]; memset(manufacturer, 0, sizeof(manufacturer)); usb_string(udev, udev->descriptor.iManufacturer, @@ -831,59 +813,33 @@ static void af9015_set_remote_config(struct usb_device *udev, if (!strcmp("Geniatech", manufacturer)) { /* iManufacturer 1 Geniatech iProduct 2 AF9015 */ - props->rc_key_map = - af9015_rc_keys_mygictv; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_mygictv); - af9015_config.ir_table = - af9015_ir_table_mygictv; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_mygictv); + table = af9015_setup_match( + AF9015_REMOTE_MYGICTV_U718, + af9015_setup_modparam); } else if (!strcmp("MSI", manufacturer)) { /* iManufacturer 1 MSI iProduct 2 MSI K-VOX */ - props->rc_key_map = - af9015_rc_keys_msi; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_msi); - af9015_config.ir_table = - af9015_ir_table_msi; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_msi); + table = af9015_setup_match( + AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, + af9015_setup_modparam); } else if (udev->descriptor.idProduct == cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { - props->rc_key_map = - af9015_rc_keys_trekstor; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_trekstor); - af9015_config.ir_table = - af9015_ir_table_trekstor; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_trekstor); + table = &(const struct af9015_setup){ 0, + af9015_rc_keys_trekstor, + ARRAY_SIZE(af9015_rc_keys_trekstor), + af9015_ir_table_trekstor, + ARRAY_SIZE(af9015_ir_table_trekstor) + }; } - break; - } - case USB_VID_AVERMEDIA: - props->rc_key_map = - af9015_rc_keys_avermedia; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_avermedia); - af9015_config.ir_table = - af9015_ir_table_avermedia; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_avermedia); - break; - case USB_VID_MSI_2: - props->rc_key_map = - af9015_rc_keys_msi_digivox_iii; - props->rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii); - af9015_config.ir_table = - af9015_ir_table_msi_digivox_iii; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_msi_digivox_iii); - break; - } + } else + table = af9015_setup_match(vendor, af9015_setup_usbids); + } + + if (table) { + props->rc_key_map = table->rc_key_map; + props->rc_key_map_size = table->rc_key_map_size; + af9015_config.ir_table = table->ir_table; + af9015_config.ir_table_size = table->ir_table_size; } } -- cgit v1.2.3 From e3a0cc62c80a997512295d8f714ee09fafbb4c99 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 22 Jan 2010 12:10:55 -0300 Subject: V4L/DVB: media: dvb/af9015, add hashes support So as a final patch, add support for hash and one hash entry for MSI digi vox mini II: iManufacturer 1 Afatech iProduct 2 DVB-T 2 iSerial 3 010101010600001 It is now handled with proper IR and key map tables. Signed-off-by: Jiri Slaby Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 03ba2fdee83..47ab2e92c6a 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -788,6 +788,13 @@ static const struct af9015_setup af9015_setup_usbids[] = { { } }; +static const struct af9015_setup af9015_setup_hashes[] = { + { 0xb8feb708, + af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), + af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, + { } +}; + static void af9015_set_remote_config(struct usb_device *udev, struct dvb_usb_device_properties *props) { @@ -800,7 +807,10 @@ static void af9015_set_remote_config(struct usb_device *udev, } else { u16 vendor = le16_to_cpu(udev->descriptor.idVendor); - if (vendor == USB_VID_AFATECH) { + table = af9015_setup_match(af9015_config.eeprom_sum, + af9015_setup_hashes); + + if (!table && vendor == USB_VID_AFATECH) { /* Check USB manufacturer and product strings and try to determine correct remote in case of chip vendor reference IDs are used. @@ -831,7 +841,7 @@ static void af9015_set_remote_config(struct usb_device *udev, ARRAY_SIZE(af9015_ir_table_trekstor) }; } - } else + } else if (!table) table = af9015_setup_match(vendor, af9015_setup_usbids); } -- cgit v1.2.3 From dae52d009fc950b5c209260d50fcc000f5becd3c Mon Sep 17 00:00:00 2001 From: Matthias Benesch Date: Fri, 18 Dec 2009 22:13:26 -0300 Subject: V4L/DVB: ngene: Initial check-in Add Micronas nGene PCIe bridge driver. The source code was provided by Micronas / Ralph Metzler, and has been reformatted to comply with Linux Codingstyle. Signed-off-by: Matthias Benesch Signed-off-by: Ralph Metzler Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 4062 ++++++++++++++++++++++++++++++++ drivers/media/dvb/ngene/ngene-ioctls.h | 216 ++ drivers/media/dvb/ngene/ngene-snd.c | 421 ++++ drivers/media/dvb/ngene/ngene-v4l2.c | 1937 +++++++++++++++ drivers/media/dvb/ngene/ngene.h | 948 ++++++++ 5 files changed, 7584 insertions(+) create mode 100644 drivers/media/dvb/ngene/ngene-core.c create mode 100644 drivers/media/dvb/ngene/ngene-ioctls.h create mode 100644 drivers/media/dvb/ngene/ngene-snd.c create mode 100644 drivers/media/dvb/ngene/ngene-v4l2.c create mode 100644 drivers/media/dvb/ngene/ngene.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c new file mode 100644 index 00000000000..744a232bd10 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -0,0 +1,4062 @@ +/* + * ngene.c: nGene PCIe bridge driver + * + * Copyright (C) 2005-2007 Micronas + * + * Copyright (C) 2008-2009 Ralph Metzler + * Modifications for new nGene firmware, + * support for EEPROM-copying, + * support for new dual DVB-S2 card prototype + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ngene.h" + +#ifdef NGENE_COMMAND_API +#include "ngene-ioctls.h" +#endif + +#define FW_INC 1 +#ifdef FW_INC +#include "ngene_fw_15.h" +#include "ngene_fw_16.h" +#include "ngene_fw_17.h" + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static int load_firmware; +module_param(load_firmware, int, 0444); +MODULE_PARM_DESC(load_firmware, "Try to load firmware from file."); +#endif + +static int copy_eeprom; +module_param(copy_eeprom, int, 0444); +MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); + +static int ngene_fw_debug; +module_param(ngene_fw_debug, int, 0444); +MODULE_PARM_DESC(ngene_fw_debug, "Debug firmware."); + +static int debug; +module_param(debug, int, 0444); +MODULE_PARM_DESC(debug, "Print debugging information."); + +#define dprintk if (debug) printk + +#define DEVICE_NAME "ngene" + +#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) +#define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) +#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) +#define ngreadl(adr) readl(dev->iomem + (adr)) +#define ngreadb(adr) readb(dev->iomem + (adr)) +#define ngcpyto(adr, src, count) memcpy_toio((char *) \ + (dev->iomem + (adr)), (src), (count)) +#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \ + (dev->iomem + (adr)), (count)) + +/****************************************************************************/ +/* Functions with missing kernel exports ************************************/ +/****************************************************************************/ + +/* yeah, let's throw out all exports which are not used in kernel ... */ + +void my_dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) +{ + rbuf->pread = rbuf->pwrite; + rbuf->error = 0; +} + +/****************************************************************************/ +/* nGene interrupt handler **************************************************/ +/****************************************************************************/ + +static void event_tasklet(unsigned long data) +{ + struct ngene *dev = (struct ngene *)data; + + while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) { + struct EVENT_BUFFER Event = + dev->EventQueue[dev->EventQueueReadIndex]; + dev->EventQueueReadIndex = + (dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1); + + if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify)) + dev->TxEventNotify(dev, Event.TimeStamp); + if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) + dev->RxEventNotify(dev, Event.TimeStamp, + Event.RXCharacter); + } +} + +static void demux_tasklet(unsigned long data) +{ + struct ngene_channel *chan = (struct ngene_channel *)data; + struct SBufferHeader *Cur = chan->nextBuffer; + + spin_lock_irq(&chan->state_lock); + + while (Cur->ngeneBuffer.SR.Flags & 0x80) { + if (chan->mode & NGENE_IO_TSOUT) { + u32 Flags = chan->DataFormatFlags; + if (Cur->ngeneBuffer.SR.Flags & 0x20) + Flags |= BEF_OVERFLOW; + if (chan->pBufferExchange) { + if (!chan->pBufferExchange(chan, + Cur->Buffer1, + chan->Capture1Length, + Cur->ngeneBuffer.SR. + Clock, Flags)) { + /* + We didn't get data + Clear in service flag to make sure we + get called on next interrupt again. + leave fill/empty (0x80) flag alone + to avoid hardware running out of + buffers during startup, we hold only + in run state ( the source may be late + delivering data ) + */ + + if (chan->HWState == HWSTATE_RUN) { + Cur->ngeneBuffer.SR.Flags &= + ~0x40; + break; + /* Stop proccessing stream */ + } + } else { + /* We got a valid buffer, + so switch to run state */ + chan->HWState = HWSTATE_RUN; + } + } else { + printk(KERN_ERR DEVICE_NAME ": OOPS\n"); + if (chan->HWState == HWSTATE_RUN) { + Cur->ngeneBuffer.SR.Flags &= ~0x40; + break; /* Stop proccessing stream */ + } + } + if (chan->AudioDTOUpdated) { + printk(KERN_INFO DEVICE_NAME + ": Update AudioDTO = %d\n", + chan->AudioDTOValue); + Cur->ngeneBuffer.SR.DTOUpdate = + chan->AudioDTOValue; + chan->AudioDTOUpdated = 0; + } + } else { + if (chan->HWState == HWSTATE_RUN) { + u32 Flags = 0; + if (Cur->ngeneBuffer.SR.Flags & 0x01) + Flags |= BEF_EVEN_FIELD; + if (Cur->ngeneBuffer.SR.Flags & 0x20) + Flags |= BEF_OVERFLOW; + if (chan->pBufferExchange) + chan->pBufferExchange(chan, + Cur->Buffer1, + chan-> + Capture1Length, + Cur->ngeneBuffer. + SR.Clock, Flags); + if (chan->pBufferExchange2) + chan->pBufferExchange2(chan, + Cur->Buffer2, + chan-> + Capture2Length, + Cur->ngeneBuffer. + SR.Clock, Flags); + } else if (chan->HWState != HWSTATE_STOP) + chan->HWState = HWSTATE_RUN; + } + Cur->ngeneBuffer.SR.Flags = 0x00; + Cur = Cur->Next; + } + chan->nextBuffer = Cur; + + spin_unlock_irq(&chan->state_lock); +} + +static irqreturn_t irq_handler(int irq, void *dev_id) +{ + struct ngene *dev = (struct ngene *)dev_id; + u32 icounts = 0; + irqreturn_t rc = IRQ_NONE; + u32 i = MAX_STREAM; + u8 *tmpCmdDoneByte; + + if (dev->BootFirmware) { + icounts = ngreadl(NGENE_INT_COUNTS); + if (icounts != dev->icounts) { + ngwritel(0, FORCE_NMI); + dev->cmd_done = 1; + wake_up(&dev->cmd_wq); + dev->icounts = icounts; + rc = IRQ_HANDLED; + } + return rc; + } + + ngwritel(0, FORCE_NMI); + + spin_lock(&dev->cmd_lock); + tmpCmdDoneByte = dev->CmdDoneByte; + if (tmpCmdDoneByte && + (*tmpCmdDoneByte || + (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) { + dev->CmdDoneByte = NULL; + dev->cmd_done = 1; + wake_up(&dev->cmd_wq); + rc = IRQ_HANDLED; + } + spin_unlock(&dev->cmd_lock); + + if (dev->EventBuffer->EventStatus & 0x80) { + u8 nextWriteIndex = + (dev->EventQueueWriteIndex + 1) & + (EVENT_QUEUE_SIZE - 1); + if (nextWriteIndex != dev->EventQueueReadIndex) { + dev->EventQueue[dev->EventQueueWriteIndex] = + *(dev->EventBuffer); + dev->EventQueueWriteIndex = nextWriteIndex; + } else { + printk(KERN_ERR DEVICE_NAME ": event overflow\n"); + dev->EventQueueOverflowCount += 1; + dev->EventQueueOverflowFlag = 1; + } + dev->EventBuffer->EventStatus &= ~0x80; + tasklet_schedule(&dev->event_tasklet); + rc = IRQ_HANDLED; + } + + while (i > 0) { + i--; + spin_lock(&dev->channel[i].state_lock); + /* if (dev->channel[i].State>=KSSTATE_RUN) { */ + if (dev->channel[i].nextBuffer) { + if ((dev->channel[i].nextBuffer-> + ngeneBuffer.SR.Flags & 0xC0) == 0x80) { + dev->channel[i].nextBuffer-> + ngeneBuffer.SR.Flags |= 0x40; + tasklet_schedule( + &dev->channel[i].demux_tasklet); + rc = IRQ_HANDLED; + } + } + spin_unlock(&dev->channel[i].state_lock); + } + + return rc; +} + +/****************************************************************************/ +/* nGene command interface **************************************************/ +/****************************************************************************/ + +static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) +{ + int ret; + u8 *tmpCmdDoneByte; + + dev->cmd_done = 0; + + if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) { + dev->BootFirmware = 1; + dev->icounts = ngreadl(NGENE_INT_COUNTS); + ngwritel(0, NGENE_COMMAND); + ngwritel(0, NGENE_COMMAND_HI); + ngwritel(0, NGENE_STATUS); + ngwritel(0, NGENE_STATUS_HI); + ngwritel(0, NGENE_EVENT); + ngwritel(0, NGENE_EVENT_HI); + } else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) { + u64 fwio = dev->PAFWInterfaceBuffer; + + ngwritel(fwio & 0xffffffff, NGENE_COMMAND); + ngwritel(fwio >> 32, NGENE_COMMAND_HI); + ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS); + ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI); + ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT); + ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI); + } + + memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2); + + if (dev->BootFirmware) + ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2); + + spin_lock_irq(&dev->cmd_lock); + tmpCmdDoneByte = dev->ngenetohost + com->out_len; + if (!com->out_len) + tmpCmdDoneByte++; + *tmpCmdDoneByte = 0; + dev->ngenetohost[0] = 0; + dev->ngenetohost[1] = 0; + dev->CmdDoneByte = tmpCmdDoneByte; + spin_unlock_irq(&dev->cmd_lock); + + /* Notify 8051. */ + ngwritel(1, FORCE_INT); + + ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); + if (!ret) { + /*ngwritel(0, FORCE_NMI);*/ + + printk(KERN_ERR DEVICE_NAME + ": Command timeout cmd=%02x prev=%02x\n", + com->cmd.hdr.Opcode, dev->prev_cmd); + return -1; + } + if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) + dev->BootFirmware = 0; + + dev->prev_cmd = com->cmd.hdr.Opcode; + msleep(10); + + if (!com->out_len) + return 0; + + memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len); + + return 0; +} + +static int ngene_command(struct ngene *dev, struct ngene_command *com) +{ + int result; + + down(&dev->cmd_mutex); + result = ngene_command_mutex(dev, com); + up(&dev->cmd_mutex); + return result; +} + +int ngene_command_nop(struct ngene *dev) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_NOP; + com.cmd.hdr.Length = 0; + com.in_len = 0; + com.out_len = 0; + + return ngene_command(dev, &com); +} + +int ngene_command_i2c_read(struct ngene *dev, u8 adr, + u8 *out, u8 outlen, u8 *in, u8 inlen, int flag) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_I2C_READ; + com.cmd.hdr.Length = outlen + 3; + com.cmd.I2CRead.Device = adr << 1; + memcpy(com.cmd.I2CRead.Data, out, outlen); + com.cmd.I2CRead.Data[outlen] = inlen; + com.cmd.I2CRead.Data[outlen + 1] = 0; + com.in_len = outlen + 3; + com.out_len = inlen + 1; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + if ((com.cmd.raw8[0] >> 1) != adr) + return -EIO; + + if (flag) + memcpy(in, com.cmd.raw8, inlen + 1); + else + memcpy(in, com.cmd.raw8 + 1, inlen); + return 0; +} + +int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen) +{ + struct ngene_command com; + + + com.cmd.hdr.Opcode = CMD_I2C_WRITE; + com.cmd.hdr.Length = outlen + 1; + com.cmd.I2CRead.Device = adr << 1; + memcpy(com.cmd.I2CRead.Data, out, outlen); + com.in_len = outlen + 1; + com.out_len = 1; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + if (com.cmd.raw8[0] == 1) + return -EIO; + + return 0; +} + +static int ngene_command_load_firmware(struct ngene *dev, + u8 *ngene_fw, u32 size) +{ +#define FIRSTCHUNK (1024) + u32 cleft; + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE; + com.cmd.hdr.Length = 0; + com.in_len = 0; + com.out_len = 0; + + ngene_command(dev, &com); + + cleft = (size + 3) & ~3; + if (cleft > FIRSTCHUNK) { + ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK, + cleft - FIRSTCHUNK); + cleft = FIRSTCHUNK; + } + ngene_fw[FW_DEBUG_DEFAULT - PROGRAM_SRAM] = ngene_fw_debug; + ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft); + + memset(&com, 0, sizeof(struct ngene_command)); + com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH; + com.cmd.hdr.Length = 4; + com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA; + com.cmd.FWLoadFinish.Length = (unsigned short)cleft; + com.in_len = 4; + com.out_len = 0; + + return ngene_command(dev, &com); +} + +int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; + com.cmd.hdr.Length = 1; + com.cmd.SfrIramRead.address = adr; + com.in_len = 1; + com.out_len = 2; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + *data = com.cmd.raw8[1]; + return 0; +} + +int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; + com.cmd.hdr.Length = 2; + com.cmd.SfrIramWrite.address = adr; + com.cmd.SfrIramWrite.data = data; + com.in_len = 2; + com.out_len = 1; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + return 0; +} + +static int ngene_command_config_uart(struct ngene *dev, u8 config, + tx_cb_t *tx_cb, rx_cb_t *rx_cb) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; + com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; + com.cmd.ConfigureUart.UartControl = config; + com.in_len = sizeof(struct FW_CONFIGURE_UART); + com.out_len = 0; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + dev->TxEventNotify = tx_cb; + dev->RxEventNotify = rx_cb; + + dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); + + return 0; +} + +static void tx_cb(struct ngene *dev, u32 ts) +{ + dev->tx_busy = 0; + wake_up_interruptible(&dev->tx_wq); +} + +static void rx_cb(struct ngene *dev, u32 ts, u8 c) +{ + int rp = dev->uart_rp; + int nwp, wp = dev->uart_wp; + + /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ + nwp = (wp + 1) % (UART_RBUF_LEN); + if (nwp == rp) + return; + dev->uart_rbuf[wp] = c; + dev->uart_wp = nwp; + wake_up_interruptible(&dev->rx_wq); +} + +static int ngene_command_config_buf(struct ngene *dev, u8 config) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER; + com.cmd.hdr.Length = 1; + com.cmd.ConfigureBuffers.config = config; + com.in_len = 1; + com.out_len = 0; + + if (ngene_command(dev, &com) < 0) + return -EIO; + return 0; +} + +static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER; + com.cmd.hdr.Length = 6; + memcpy(&com.cmd.ConfigureBuffers.config, config, 6); + com.in_len = 6; + com.out_len = 0; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + return 0; +} + +static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN; + com.cmd.hdr.Length = 1; + com.cmd.SetGpioPin.select = select | (level << 7); + com.in_len = 1; + com.out_len = 0; + + return ngene_command(dev, &com); +} + +/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! + Also better set bootdelay to 1 in nvram or less. */ +static void ngene_reset_decypher(struct ngene *dev) +{ + printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); + ngene_command_gpio_set(dev, 4, 0); + msleep(1); + ngene_command_gpio_set(dev, 4, 1); + msleep(2000); +} + +/* + 02000640 is sample on rising edge. + 02000740 is sample on falling edge. + 02000040 is ignore "valid" signal + + 0: FD_CTL1 Bit 7,6 must be 0,1 + 7 disable(fw controlled) + 6 0-AUX,1-TS + 5 0-par,1-ser + 4 0-lsb/1-msb + 3,2 reserved + 1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both + 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge + 2: FD_STA is read-only. 0-sync + 3: FD_INSYNC is number of 47s to trigger "in sync". + 4: FD_OUTSYNC is number of 47s to trigger "out of sync". + 5: FD_MAXBYTE1 is low-order of bytes per packet. + 6: FD_MAXBYTE2 is high-order of bytes per packet. + 7: Top byte is unused. +*/ + +/****************************************************************************/ + +static u8 TSFeatureDecoderSetup[8 * 4] = { + 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, + 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ + 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ + 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ +}; + +/* Set NGENE I2S Config to 16 bit packed */ +static u8 I2SConfiguration[] = { + 0x00, 0x10, 0x00, 0x00, + 0x80, 0x10, 0x00, 0x00, +}; + +static u8 SPDIFConfiguration[10] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* Set NGENE I2S Config to transport stream compatible mode */ + +static u8 TS_I2SConfiguration[4] = { 0x3E, 0x1A, 0x00, 0x00 }; /*3e 18 00 00 ?*/ + +static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x20, 0x00, 0x00 }; + +static u8 ITUDecoderSetup[4][16] = { + {0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20, /* SDTV */ + 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00}, + {0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, + {0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00, /* HDTV 1080i50 */ + 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, + {0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, /* HDTV 1080i60 */ + 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, +}; + +/* + * 50 48 60 gleich + * 27p50 9f 00 22 80 42 69 18 ... + * 27p60 93 00 22 80 82 69 1c ... + */ + +/* Maxbyte to 1144 (for raw data) */ +static u8 ITUFeatureDecoderSetup[8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00 +}; + +static void FillTSBuffer(void *Buffer, int Length, u32 Flags) +{ + u32 *ptr = Buffer; + + memset(Buffer, Length, 0xff); + while (Length > 0) { + if (Flags & DF_SWAP32) + *ptr = 0x471FFF10; + else + *ptr = 0x10FF1F47; + ptr += (188 / 4); + Length -= 188; + } +} + +static void clear_tsin(struct ngene_channel *chan) +{ + struct SBufferHeader *Cur = chan->nextBuffer; + + do { + memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); + Cur = Cur->Next; + } while (Cur != chan->nextBuffer); +} + +static void flush_buffers(struct ngene_channel *chan) +{ + u8 val; + + do { + msleep(1); + spin_lock_irq(&chan->state_lock); + val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80; + spin_unlock_irq(&chan->state_lock); + } while (val); +} + +static void clear_buffers(struct ngene_channel *chan) +{ + struct SBufferHeader *Cur = chan->nextBuffer; + + do { + memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); + if (chan->mode & NGENE_IO_TSOUT) + FillTSBuffer(Cur->Buffer1, + chan->Capture1Length, + chan->DataFormatFlags); + Cur = Cur->Next; + } while (Cur != chan->nextBuffer); + + if (chan->mode & NGENE_IO_TSOUT) { + chan->nextBuffer->ngeneBuffer.SR.DTOUpdate = + chan->AudioDTOValue; + chan->AudioDTOUpdated = 0; + + Cur = chan->TSIdleBuffer.Head; + + do { + memset(&Cur->ngeneBuffer.SR, 0, + sizeof(Cur->ngeneBuffer.SR)); + FillTSBuffer(Cur->Buffer1, + chan->Capture1Length, + chan->DataFormatFlags); + Cur = Cur->Next; + } while (Cur != chan->TSIdleBuffer.Head); + } +} + +int ngene_command_stream_control(struct ngene *dev, u8 stream, u8 control, + u8 mode, u8 flags) +{ + struct ngene_channel *chan = &dev->channel[stream]; + struct ngene_command com; + u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300); + u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500); + u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); + u16 BsSDO = 0x9B00; + + /* down(&dev->stream_mutex); */ + while (down_trylock(&dev->stream_mutex)) { + printk(KERN_INFO DEVICE_NAME ": SC locked\n"); + msleep(1); + } + memset(&com, 0, sizeof(com)); + com.cmd.hdr.Opcode = CMD_CONTROL; + com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; + com.cmd.StreamControl.Stream = stream | (control ? 8 : 0); + if (chan->mode & NGENE_IO_TSOUT) + com.cmd.StreamControl.Stream |= 0x07; + com.cmd.StreamControl.Control = control | + (flags & SFLAG_ORDER_LUMA_CHROMA); + com.cmd.StreamControl.Mode = mode; + com.in_len = sizeof(struct FW_STREAM_CONTROL); + com.out_len = 0; + + printk(KERN_INFO DEVICE_NAME ": Stream=%02x, Control=%02x, Mode=%02x\n", + com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control, + com.cmd.StreamControl.Mode); + chan->Mode = mode; + + if (!(control & 0x80)) { + spin_lock_irq(&chan->state_lock); + if (chan->State == KSSTATE_RUN) { + chan->State = KSSTATE_ACQUIRE; + chan->HWState = HWSTATE_STOP; + spin_unlock_irq(&chan->state_lock); + if (ngene_command(dev, &com) < 0) { + up(&dev->stream_mutex); + return -1; + } + /* clear_buffers(chan); */ + flush_buffers(chan); + up(&dev->stream_mutex); + return 0; + } + spin_unlock_irq(&chan->state_lock); + up(&dev->stream_mutex); + return 0; + } + + if (mode & SMODE_AUDIO_CAPTURE) { + com.cmd.StreamControl.CaptureBlockCount = + chan->Capture1Length / AUDIO_BLOCK_SIZE; + com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; + } else if (mode & SMODE_TRANSPORT_STREAM) { + com.cmd.StreamControl.CaptureBlockCount = + chan->Capture1Length / TS_BLOCK_SIZE; + com.cmd.StreamControl.MaxLinesPerField = + chan->Capture1Length / TS_BLOCK_SIZE; + com.cmd.StreamControl.Buffer_Address = + chan->TSRingBuffer.PAHead; + if (chan->mode & NGENE_IO_TSOUT) { + com.cmd.StreamControl.BytesPerVBILine = + chan->Capture1Length / TS_BLOCK_SIZE; + com.cmd.StreamControl.Stream |= 0x07; + } + } else { + com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine; + com.cmd.StreamControl.MaxLinesPerField = chan->nLines; + com.cmd.StreamControl.MinLinesPerField = 100; + com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; + + if (mode & SMODE_VBI_CAPTURE) { + com.cmd.StreamControl.MaxVBILinesPerField = + chan->nVBILines; + com.cmd.StreamControl.MinVBILinesPerField = 0; + com.cmd.StreamControl.BytesPerVBILine = + chan->nBytesPerVBILine; + } + if (flags & SFLAG_COLORBAR) + com.cmd.StreamControl.Stream |= 0x04; + } + + spin_lock_irq(&chan->state_lock); + if (mode & SMODE_AUDIO_CAPTURE) { + chan->nextBuffer = chan->RingBuffer.Head; + if (mode & SMODE_AUDIO_SPDIF) { + com.cmd.StreamControl.SetupDataLen = + sizeof(SPDIFConfiguration); + com.cmd.StreamControl.SetupDataAddr = BsSPI; + memcpy(com.cmd.StreamControl.SetupData, + SPDIFConfiguration, sizeof(SPDIFConfiguration)); + } else { + com.cmd.StreamControl.SetupDataLen = 4; + com.cmd.StreamControl.SetupDataAddr = BsSDI; + memcpy(com.cmd.StreamControl.SetupData, + I2SConfiguration + + 4 * dev->card_info->i2s[stream], 4); + } + } else if (mode & SMODE_TRANSPORT_STREAM) { + chan->nextBuffer = chan->TSRingBuffer.Head; + if (stream >= STREAM_AUDIOIN1) { + if (chan->mode & NGENE_IO_TSOUT) { + com.cmd.StreamControl.SetupDataLen = + sizeof(TS_I2SOutConfiguration); + com.cmd.StreamControl.SetupDataAddr = BsSDO; + memcpy(com.cmd.StreamControl.SetupData, + TS_I2SOutConfiguration, + sizeof(TS_I2SOutConfiguration)); + } else { + com.cmd.StreamControl.SetupDataLen = + sizeof(TS_I2SConfiguration); + com.cmd.StreamControl.SetupDataAddr = BsSDI; + memcpy(com.cmd.StreamControl.SetupData, + TS_I2SConfiguration, + sizeof(TS_I2SConfiguration)); + } + } else { + com.cmd.StreamControl.SetupDataLen = 8; + com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10; + memcpy(com.cmd.StreamControl.SetupData, + TSFeatureDecoderSetup + + 8 * dev->card_info->tsf[stream], 8); + } + } else { + chan->nextBuffer = chan->RingBuffer.Head; + com.cmd.StreamControl.SetupDataLen = + 16 + sizeof(ITUFeatureDecoderSetup); + com.cmd.StreamControl.SetupDataAddr = BsUVI; + memcpy(com.cmd.StreamControl.SetupData, + ITUDecoderSetup[chan->itumode], 16); + memcpy(com.cmd.StreamControl.SetupData + 16, + ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup)); + } + clear_buffers(chan); + chan->State = KSSTATE_RUN; + if (mode & SMODE_TRANSPORT_STREAM) + chan->HWState = HWSTATE_RUN; + else + chan->HWState = HWSTATE_STARTUP; + spin_unlock_irq(&chan->state_lock); + + if (ngene_command(dev, &com) < 0) { + up(&dev->stream_mutex); + return -1; + } + up(&dev->stream_mutex); + return 0; +} + +int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, + u16 lines, u16 bpl, u16 vblines, u16 vbibpl) +{ + if (!(mode & SMODE_TRANSPORT_STREAM)) + return -EINVAL; + + if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) + return -EINVAL; + + if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) + return -EINVAL; + + if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) + return -EINVAL; + + return ngene_command_stream_control(dev, stream, control, mode, 0); +} + +/****************************************************************************/ +/* I2C **********************************************************************/ +/****************************************************************************/ + +static void ngene_i2c_set_bus(struct ngene *dev, int bus) +{ + if (!(dev->card_info->i2c_access & 2)) + return; + if (dev->i2c_current_bus == bus) + return; + + switch (bus) { + case 0: + ngene_command_gpio_set(dev, 3, 0); + ngene_command_gpio_set(dev, 2, 1); + break; + + case 1: + ngene_command_gpio_set(dev, 2, 0); + ngene_command_gpio_set(dev, 3, 1); + break; + } + dev->i2c_current_bus = bus; +} + +static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, + struct i2c_msg msg[], int num) +{ + struct ngene_channel *chan = + (struct ngene_channel *)i2c_get_adapdata(adapter); + struct ngene *dev = chan->dev; + + down(&dev->i2c_switch_mutex); + ngene_i2c_set_bus(dev, chan->number); + + if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD)) + if (!ngene_command_i2c_read(dev, msg[0].addr, + msg[0].buf, msg[0].len, + msg[1].buf, msg[1].len, 0)) + goto done; + + if (num == 1 && !(msg[0].flags & I2C_M_RD)) + if (!ngene_command_i2c_write(dev, msg[0].addr, + msg[0].buf, msg[0].len)) + goto done; + if (num == 1 && (msg[0].flags & I2C_M_RD)) + if (!ngene_command_i2c_read(dev, msg[0].addr, 0, 0, + msg[0].buf, msg[0].len, 0)) + goto done; + + up(&dev->i2c_switch_mutex); + return -EIO; + +done: + up(&dev->i2c_switch_mutex); + return num; +} + + +static int ngene_i2c_algo_control(struct i2c_adapter *adap, + unsigned int cmd, unsigned long arg) +{ + struct ngene_channel *chan = + (struct ngene_channel *)i2c_get_adapdata(adap); + + switch (cmd) { + case IOCTL_MIC_TUN_RDY: + chan->tun_rdy = 1; + if (chan->dec_rdy == 1) + chan->tun_dec_rdy = 1; + break; + + case IOCTL_MIC_DEC_RDY: + chan->dec_rdy = 1; + if (chan->tun_rdy == 1) + chan->tun_dec_rdy = 1; + break; + + case IOCTL_MIC_TUN_DETECT: + { + int *palorbtsc = (int *)arg; + *palorbtsc = chan->dev->card_info->ntsc; + break; + } + + default: + break; + } + return 0; +} + +static u32 ngene_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +struct i2c_algorithm ngene_i2c_algo = { + .master_xfer = ngene_i2c_master_xfer, + .functionality = ngene_i2c_functionality, +}; + +static int ngene_i2c_attach(struct i2c_client *client) +{ + return 0; +} + +static int ngene_i2c_detach(struct i2c_client *client) +{ + return 0; +} + +static int ngene_i2c_init(struct ngene *dev, int dev_nr) +{ + struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); + + i2c_set_adapdata(adap, &(dev->channel[dev_nr])); +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + adap->class = I2C_ADAP_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; +#else + adap->class = I2C_CLASS_TV_ANALOG; +#endif + + strcpy(adap->name, "nGene"); + + adap->id = I2C_HW_SAA7146; + adap->client_register = ngene_i2c_attach; + adap->client_unregister = ngene_i2c_detach; + adap->algo = &ngene_i2c_algo; + adap->algo_data = (void *)&(dev->channel[dev_nr]); + + mutex_init(&adap->bus_lock); + return i2c_add_adapter(adap); +} + +int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) +{ + u8 m[1] = {data}; + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; + + if (i2c_transfer(adapter, &msg, 1) != 1) { + printk(KERN_ERR DEVICE_NAME + ": Failed to write to I2C adr %02x!\n", adr); + return -1; + } + return 0; +} + +static int i2c_write_register(struct i2c_adapter *adapter, + u8 adr, u8 reg, u8 data) +{ + u8 m[2] = {reg, data}; + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; + + if (i2c_transfer(adapter, &msg, 1) != 1) { + printk(KERN_ERR DEVICE_NAME + ": Failed to write to I2C register %02x@%02x!\n", + reg, adr); + return -1; + } + return 0; +} + +static int i2c_write_read(struct i2c_adapter *adapter, + u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) +{ + struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, + .buf = w, .len = wlen}, + {.addr = adr, .flags = I2C_M_RD, + .buf = r, .len = rlen} }; + + if (i2c_transfer(adapter, msgs, 2) != 2) { + printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); + return -1; + } + return 0; +} + +static int test_dec_i2c(struct i2c_adapter *adapter, int reg) +{ + u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; + u8 data2[256]; + int i; + + memset(data2, 0, 256); + i2c_write_read(adapter, 0x66, data, 2, data2, 4); + for (i = 0; i < 4; i++) + printk("%02x ", data2[i]); + printk("\n"); + + return 0; +} + + +/****************************************************************************/ +/* EEPROM TAGS **************************************************************/ +/****************************************************************************/ + +#define MICNG_EE_START 0x0100 +#define MICNG_EE_END 0x0FF0 + +#define MICNG_EETAG_END0 0x0000 +#define MICNG_EETAG_END1 0xFFFF + +/* 0x0001 - 0x000F reserved for housekeeping */ +/* 0xFFFF - 0xFFFE reserved for housekeeping */ + +/* Micronas assigned tags + EEProm tags for hardware support */ + +#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ +#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ + +#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ +#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ + +/* Tag range for OEMs */ + +#define MICNG_EETAG_OEM_FIRST 0xC000 +#define MICNG_EETAG_OEM_LAST 0xFFEF + +static int i2c_write_eeprom(struct i2c_adapter *adapter, + u8 adr, u16 reg, u8 data) +{ + u8 m[3] = {(reg >> 8), (reg & 0xff), data}; + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, + .len = sizeof(m)}; + + if (i2c_transfer(adapter, &msg, 1) != 1) { + dprintk(KERN_DEBUG DEVICE_NAME ": Error writing EEPROM!\n"); + return -EIO; + } + return 0; +} + +static int i2c_read_eeprom(struct i2c_adapter *adapter, + u8 adr, u16 reg, u8 *data, int len) +{ + u8 msg[2] = {(reg >> 8), (reg & 0xff)}; + struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, + .buf = msg, .len = 2 }, + {.addr = adr, .flags = I2C_M_RD, + .buf = data, .len = len} }; + + if (i2c_transfer(adapter, msgs, 2) != 2) { + dprintk(KERN_DEBUG DEVICE_NAME ": Error reading EEPROM\n"); + return -EIO; + } + return 0; +} + +static int ReadEEProm(struct i2c_adapter *adapter, + u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) +{ + int status = 0; + u16 Addr = MICNG_EE_START, Length, tag = 0; + u8 EETag[3]; + + while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { + if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) + return -1; + tag = (EETag[0] << 8) | EETag[1]; + if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) + return -1; + if (tag == Tag) + break; + Addr += sizeof(u16) + 1 + EETag[2]; + } + if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { + printk(KERN_ERR DEVICE_NAME + ": Reached EOEE @ Tag = %04x Length = %3d\n", + tag, EETag[2]); + return -1; + } + Length = EETag[2]; + if (Length > MaxLen) + Length = (u16) MaxLen; + if (Length > 0) { + Addr += sizeof(u16) + 1; + status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); + if (!status) { + *pLength = EETag[2]; + if (Length < EETag[2]) + ; /*status=STATUS_BUFFER_OVERFLOW; */ + } + } + return status; +} + +static int WriteEEProm(struct i2c_adapter *adapter, + u16 Tag, u32 Length, u8 *data) +{ + int status = 0; + u16 Addr = MICNG_EE_START; + u8 EETag[3]; + u16 tag = 0; + int retry, i; + + while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { + if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) + return -1; + tag = (EETag[0] << 8) | EETag[1]; + if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) + return -1; + if (tag == Tag) + break; + Addr += sizeof(u16) + 1 + EETag[2]; + } + if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { + printk(KERN_ERR DEVICE_NAME + ": Reached EOEE @ Tag = %04x Length = %3d\n", + tag, EETag[2]); + return -1; + } + + if (Length > EETag[2]) + return -EINVAL; + /* Note: We write the data one byte at a time to avoid + issues with page sizes. (which are different for + each manufacture and eeprom size) + */ + Addr += sizeof(u16) + 1; + for (i = 0; i < Length; i++, Addr++) { + status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); + + if (status) + break; + + /* Poll for finishing write cycle */ + retry = 10; + while (retry) { + u8 Tmp; + + msleep(50); + status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); + if (status) + break; + if (Tmp != data[i]) + printk(KERN_ERR DEVICE_NAME + "eeprom write error\n"); + retry -= 1; + } + if (status) { + printk(KERN_ERR DEVICE_NAME + ": Timeout polling eeprom\n"); + break; + } + } + return status; +} + +static void i2c_init_eeprom(struct i2c_adapter *adapter) +{ + u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, + 0x10, 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + int i; + + for (i = 0; i < sizeof(tags); i++) + i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); +} + +static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) +{ + int stat; + u8 buf[2]; + u32 len = 0; + + stat = ReadEEProm(adapter, tag, 2, buf, &len); + if (stat) + return stat; + if (len != 2) + return -EINVAL; + + *data = (buf[0] << 8) | buf[1]; + return 0; +} + +static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) +{ + int stat; + u8 buf[2]; + + buf[0] = data >> 8; + buf[1] = data & 0xff; + stat = WriteEEProm(adapter, tag, 2, buf); + if (stat) + return stat; + return 0; +} + +static int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) +{ + u8 buf[64]; + int i; + + if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { + printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); + return -1; + } + for (i = 0; i < sizeof(buf); i++) { + if (!(i & 15)) + printk("\n"); + printk("%02x ", buf[i]); + } + printk("\n"); + + return 0; +} + +static int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) +{ + u8 buf[64]; + int i; + + if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { + printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); + return -1; + } + buf[36] = 0xc3; + buf[39] = 0xab; + for (i = 0; i < sizeof(buf); i++) { + i2c_write_eeprom(adapter, adr2, i, buf[i]); + msleep(10); + } + return 0; +} + + +/****************************************************************************/ +/* COMMAND API interface ****************************************************/ +/****************************************************************************/ + +#ifdef NGENE_COMMAND_API + +static int command_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + int err = 0; + + switch (cmd) { + case IOCTL_MIC_NO_OP: + err = ngene_command_nop(dev); + break; + + case IOCTL_MIC_DOWNLOAD_FIRMWARE: + break; + + case IOCTL_MIC_I2C_READ: + { + MIC_I2C_READ *msg = parg; + + err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, + msg->OutData, msg->OutLength, + msg->OutData, msg->InLength, 1); + break; + } + + case IOCTL_MIC_I2C_WRITE: + { + MIC_I2C_WRITE *msg = parg; + + err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, + msg->Data, msg->Length); + break; + } + + case IOCTL_MIC_TEST_GETMEM: + { + MIC_MEM *m = parg; + + if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) + return -EINVAL; + + /* WARNING, only use this on x86, + other archs may not swallow this */ + err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); + break; + } + + case IOCTL_MIC_TEST_SETMEM: + { + MIC_MEM *m = parg; + + if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) + return -EINVAL; + + err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); + break; + } + + case IOCTL_MIC_SFR_READ: + { + MIC_IMEM *m = parg; + + err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); + break; + } + + case IOCTL_MIC_SFR_WRITE: + { + MIC_IMEM *m = parg; + + err = ngene_command_imem_write(dev, m->Address, m->Data, 1); + break; + } + + case IOCTL_MIC_IRAM_READ: + { + MIC_IMEM *m = parg; + + err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); + break; + } + + case IOCTL_MIC_IRAM_WRITE: + { + MIC_IMEM *m = parg; + + err = ngene_command_imem_write(dev, m->Address, m->Data, 0); + break; + } + + case IOCTL_MIC_STREAM_CONTROL: + { + MIC_STREAM_CONTROL *m = parg; + + err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, + m->nLines, m->nBytesPerLine, + m->nVBILines, m->nBytesPerVBILine); + break; + } + + default: + err = -EINVAL; + break; + } + return err; +} + +static int command_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void *parg = (void *)arg, *pbuf = NULL; + char buf[64]; + int res = -EFAULT; + + if (_IOC_DIR(cmd) & _IOC_WRITE) { + parg = buf; + if (_IOC_SIZE(cmd) > sizeof(buf)) { + pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (!pbuf) + return -ENOMEM; + parg = pbuf; + } + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto error; + } + res = command_do_ioctl(inode, file, cmd, parg); + if (res < 0) + goto error; + if (_IOC_DIR(cmd) & _IOC_READ) + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + res = -EFAULT; +error: + kfree(pbuf); + return res; +} + +struct page *ngene_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return 0; +} + +static int ngene_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long off = vma->vm_pgoff << PAGE_SHIFT; + unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; + unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; + + if (size > psize) + return -EINVAL; + + if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, + vma->vm_page_prot)) + return -EAGAIN; + return 0; +} + +static int write_uart(struct ngene *dev, u8 *data, int len) +{ + struct ngene_command com; + + com.cmd.hdr.Opcode = CMD_WRITE_UART; + com.cmd.hdr.Length = len; + memcpy(com.cmd.WriteUart.Data, data, len); + com.cmd.WriteUart.Data[len] = 0; + com.cmd.WriteUart.Data[len + 1] = 0; + com.in_len = len; + com.out_len = 0; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + return 0; +} + +static int send_cli(struct ngene *dev, char *cmd) +{ + /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ + return write_uart(dev, cmd, strlen(cmd)); +} + +static int send_cli_val(struct ngene *dev, char *cmd, u32 val) +{ + char s[32]; + + snprintf(s, 32, "%s %d\n", cmd, val); + /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ + return write_uart(dev, s, strlen(s)); +} + +static int ngene_command_write_uart_user(struct ngene *dev, + const u8 *data, int len) +{ + struct ngene_command com; + + dev->tx_busy = 1; + com.cmd.hdr.Opcode = CMD_WRITE_UART; + com.cmd.hdr.Length = len; + + if (copy_from_user(com.cmd.WriteUart.Data, data, len)) + return -EFAULT; + com.in_len = len; + com.out_len = 0; + + if (ngene_command(dev, &com) < 0) + return -EIO; + + return 0; +} + +static ssize_t uart_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + int len, ret = 0; + size_t left = count; + + while (left) { + len = left; + if (len > 250) + len = 250; + ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); + if (ret < 0) + return ret; + ngene_command_write_uart_user(dev, buf, len); + left -= len; + buf += len; + } + return count; +} + +static ssize_t ts_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + + if (wait_event_interruptible(dev->tsout_rbuf.queue, + dvb_ringbuffer_free + (&dev->tsout_rbuf) >= count) < 0) + return 0; + + dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); + + return count; +} + +static ssize_t uart_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + int left; + int wp, rp, avail, len; + + if (!dev->uart_rbuf) + return -EINVAL; + if (count > 128) + count = 128; + left = count; + while (left) { + if (wait_event_interruptible(dev->rx_wq, + dev->uart_wp != dev->uart_rp) < 0) + return -EAGAIN; + wp = dev->uart_wp; + rp = dev->uart_rp; + avail = (wp - rp); + + if (avail < 0) + avail += UART_RBUF_LEN; + if (avail > left) + avail = left; + if (wp < rp) { + len = UART_RBUF_LEN - rp; + if (len > avail) + len = avail; + if (copy_to_user(buf, dev->uart_rbuf + rp, len)) + return -EFAULT; + if (len < avail) + if (copy_to_user(buf + len, dev->uart_rbuf, + avail - len)) + return -EFAULT; + } else { + if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) + return -EFAULT; + } + dev->uart_rp = (rp + avail) % UART_RBUF_LEN; + left -= avail; + buf += avail; + } + return count; +} + +static const struct file_operations command_fops = { + .owner = THIS_MODULE, + .read = uart_read, + .write = ts_write, + .ioctl = command_ioctl, + .open = dvb_generic_open, + .release = dvb_generic_release, + .poll = 0, + .mmap = ngene_mmap, +}; + +static struct dvb_device dvbdev_command = { + .priv = 0, + .readers = -1, + .writers = -1, + .users = -1, + .fops = &command_fops, +}; + +#endif + +/****************************************************************************/ +/* DVB functions and API interface ******************************************/ +/****************************************************************************/ + +static void swap_buffer(u32 *p, u32 len) +{ + while (len) { + *p = swab32(*p); + p++; + len -= 4; + } +} + +static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) +{ + struct ngene_channel *chan = priv; + struct ngene *dev = chan->dev; + + if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { + dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); + wake_up_interruptible(&dev->ain_rbuf.queue); + } else + printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); + + return 0; +} + +static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) +{ + + struct ngene_channel *chan = priv; + struct ngene *dev = chan->dev; + + if (len >= 1920 * 1080) + len = 1920 * 1080; + if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { + dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); + wake_up_interruptible(&dev->vin_rbuf.queue); + } else { + ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ + } + return 0; +} + +static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) +{ + struct ngene_channel *chan = priv; + + + dvb_dmx_swfilter(&chan->demux, buf, len); + return 0; +} + +u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 }; + +static void *tsout_exchange(void *priv, void *buf, u32 len, + u32 clock, u32 flags) +{ + struct ngene_channel *chan = priv; + struct ngene *dev = chan->dev; + u32 alen; + + alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); + alen -= alen % 188; + + if (alen < len) + FillTSBuffer(buf + alen, len - alen, flags); + else + alen = len; + dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); + if (flags & DF_SWAP32) + swap_buffer((u32 *)buf, alen); + wake_up_interruptible(&dev->tsout_rbuf.queue); + return buf; +} + +static void set_dto(struct ngene_channel *chan, u32 rate) +{ + u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ + + val = ((val >> 25) + 1) >> 1; + chan->AudioDTOValue = (u32) val; + /* chan->AudioDTOUpdated=1; */ + /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ +} + +static void set_transfer(struct ngene_channel *chan, int state) +{ + u8 control = 0, mode = 0, flags = 0; + struct ngene *dev = chan->dev; + int ret; + + /* + if (chan->running) + return; + */ + + /* + printk(KERN_INFO DEVICE_NAME ": st %d\n", state); + msleep(100); + */ + + if (state) { + if (chan->running) { + printk(KERN_INFO DEVICE_NAME ": already running\n"); + return; + } + } else { + if (!chan->running) { + printk(KERN_INFO DEVICE_NAME ": already stopped\n"); + return; + } + } + + if (dev->card_info->switch_ctrl) + dev->card_info->switch_ctrl(chan, 1, state ^ 1); + + if (state) { + spin_lock_irq(&chan->state_lock); + + /* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", + ngreadl(0x9310)); */ + my_dvb_ringbuffer_flush(&dev->tsout_rbuf); + control = 0x80; + if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { + chan->Capture1Length = 512 * 188; + mode = SMODE_TRANSPORT_STREAM; + } + if (chan->mode & NGENE_IO_TSOUT) { + chan->pBufferExchange = tsout_exchange; + /* 0x66666666 = 50MHz *2^33 /250MHz */ + chan->AudioDTOValue = 0x66666666; + /* set_dto(chan, 38810700+1000); */ + /* set_dto(chan, 19392658); */ + } + if (chan->mode & NGENE_IO_TSIN) + chan->pBufferExchange = tsin_exchange; + /* ngwritel(0, 0x9310); */ + spin_unlock_irq(&chan->state_lock); + } else + ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", + ngreadl(0x9310)); */ + + ret = ngene_command_stream_control(dev, chan->number, + control, mode, flags); + if (!ret) + chan->running = state; + else + printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n", + state); + if (!state) { + spin_lock_irq(&chan->state_lock); + chan->pBufferExchange = 0; + my_dvb_ringbuffer_flush(&dev->tsout_rbuf); + spin_unlock_irq(&chan->state_lock); + } +} + +static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ngene_channel *chan = dvbdmx->priv; + struct ngene *dev = chan->dev; + + if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { + switch (dvbdmxfeed->pes_type) { + case DMX_TS_PES_VIDEO: + send_cli_val(dev, "vpid", dvbdmxfeed->pid); + send_cli(dev, "res 1080i50\n"); + /* send_cli(dev, "vdec mpeg2\n"); */ + break; + + case DMX_TS_PES_AUDIO: + send_cli_val(dev, "apid", dvbdmxfeed->pid); + send_cli(dev, "start\n"); + break; + + case DMX_TS_PES_PCR: + send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); + break; + + default: + break; + } + + } + + if (chan->users == 0) { + set_transfer(chan, 1); + /* msleep(10); */ + } + + return ++chan->users; +} + +static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ngene_channel *chan = dvbdmx->priv; + struct ngene *dev = chan->dev; + + if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { + switch (dvbdmxfeed->pes_type) { + case DMX_TS_PES_VIDEO: + send_cli(dev, "stop\n"); + break; + + case DMX_TS_PES_AUDIO: + break; + + case DMX_TS_PES_PCR: + break; + + default: + break; + } + + } + + if (--chan->users) + return chan->users; + + set_transfer(chan, 0); + + return 0; +} + +static int write_demod(struct i2c_adapter *adapter, u8 adr, u16 reg, u16 data) +{ + u8 mm[5] = { 0x10, (reg >> 8) & 0xff, reg & 0xff, + (data >> 8) & 0xff, data & 0xff}; + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = mm, .len = 5 }; + + if (i2c_transfer(adapter, &msg, 1) != 1) { + printk(KERN_ERR DEVICE_NAME ": error in write_demod\n"); + return -1; + } + return 0; +} + + +static int ngene_drxd_pll_set(struct ngene_channel *chan, + u8 *pll, u8 *aux, u8 plladr) +{ + struct i2c_adapter *adap = &chan->i2c_adapter; + struct i2c_msg msg_pll = {.addr = plladr, .flags = 0, .buf = pll, + .len = 4}; + struct i2c_msg msg_aux = {.addr = plladr, .flags = 0, .buf = aux, + .len = 2}; + int err = 0; + + if (chan->dev->card_info->i2c_access & 1) + down(&chan->dev->pll_mutex); + + chan->fe->ops.i2c_gate_ctrl(chan->fe, 1); + err = i2c_transfer(adap, &msg_pll, 1); + if (err != 1) + goto error; + if (aux) + err = i2c_transfer(adap, &msg_aux, 1); +error: + chan->fe->ops.i2c_gate_ctrl(chan->fe, 0); + if (chan->dev->card_info->i2c_access & 1) + up(&chan->dev->pll_mutex); + return err; +} + +static int ngene_pll_set_th_dtt7520x(void *priv, void *priv_params, + u8 plladr, u8 dadr, s32 *off) +{ + struct dvb_frontend_parameters *params = priv_params; + struct ngene_channel *chan = priv; + + u32 freq = params->frequency; + u8 pll[4], aux[2]; + u8 c1, c2; + u32 div; + + if (freq < 185000000 || freq > 900000000) + return -EINVAL; + + if (freq < 465000000) + c2 = 0x12; + else + c2 = 0x18; + + if (freq < 305000000) + c1 = 0xb4; + else if (freq < 405000000) + c1 = 0xbc; + else if (freq < 445000000) + c1 = 0xf4; + else if (freq < 465000000) + c1 = 0xfc; + else if (freq < 735000000) + c1 = 0xbc; + else if (freq < 835000000) + c1 = 0xf4; + else + c1 = 0xfc; + + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) + c2 ^= 0x10; + + div = (freq + 36000000 + 166667 / 2) / 166667; + *off = ((s32) div) * 166667 - (s32) freq - 36000000; + + pll[0] = (div >> 8) & 0x7f; + pll[1] = div & 0xff; + pll[2] = c1; + pll[3] = c2; + + aux[0] = (c1 & 0xc7) | 0x98; + aux[1] = 0x30; + + return ngene_drxd_pll_set(chan, pll, aux, plladr); +} + +static int ngene_pll_set_mt_3x0823(void *priv, + void *priv_params, + u8 plladr, u8 dadr, s32 *off) +{ + struct dvb_frontend_parameters *params = priv_params; + struct ngene_channel *chan = priv; + struct i2c_adapter *adap = &chan->i2c_adapter; + u32 freq = params->frequency; + u8 pll[4]; + u8 aux[2]; + u8 c1, c2; + u32 div; + + if (freq < 47125000 || freq > 855250000) + return -EINVAL; + else if (freq < 120000000) { + c1 = 0xcc; + c2 = 0x01; + } else if (freq < 155500000) { + c1 = 0xfc; + c2 = 0x01; + } else if (freq < 300000000) { + c1 = 0xbc; + c2 = 0x02; + } else if (freq < 467000000) { + c1 = 0xcc; + c2 = 0x02; + } else { + c1 = 0xcc; + c2 = 0x04; + } + + if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) + c2 |= 0x08; + +#define INTERFREQ (36000000) + + div = (freq + INTERFREQ + 166667 / 2) / 166667; + + *off = ((s32) div) * 166667 - (s32) freq - INTERFREQ; + + pll[0] = (div >> 8) & 0x7f; + pll[1] = div & 0xff; + pll[2] = c1; + pll[3] = c2; + + aux[0] = (c1 & 0xc7) | 0x98; + aux[1] = 0x20; + + write_demod(adap, dadr, 0x1007, 0xc27); + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_7_MHZ: + write_demod(adap, dadr, 0x0020, 0x103); + break; + case BANDWIDTH_AUTO: + case BANDWIDTH_8_MHZ: + write_demod(adap, dadr, 0x0020, 0x003); + break; + case BANDWIDTH_6_MHZ: + write_demod(adap, dadr, 0x0020, 0x002); + /*write_demod(adap, dadr, 0x1022, 397);*/ + break; + } + + return ngene_drxd_pll_set(chan, pll, aux, plladr); + +} + +static s16 osc_deviation(void *priv, s16 deviation, int flag) +{ + struct ngene_channel *chan = priv; + struct i2c_adapter *adap = &chan->i2c_adapter; + u16 data = 0; + + if (flag) { + data = (u16) deviation; + printk(KERN_INFO DEVICE_NAME ": write deviation %d\n", + deviation); + eeprom_write_ushort(adap, 0x1000 + chan->number, data); + } else { + if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) + data = 0; + printk(KERN_INFO DEVICE_NAME ": read deviation %d\n", + (s16) data); + } + + return (s16) data; +} + +static int write_to_decoder(struct dvb_demux_feed *feed, + const u8 *buf, size_t len) +{ + struct dvb_demux *dvbdmx = feed->demux; + struct ngene_channel *chan = dvbdmx->priv; + struct ngene *dev = chan->dev; + + if (wait_event_interruptible(dev->tsout_rbuf.queue, + dvb_ringbuffer_free + (&dev->tsout_rbuf) >= len) < 0) + return 0; + + dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); + + return len; +} + +static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, + int (*start_feed)(struct dvb_demux_feed *), + int (*stop_feed)(struct dvb_demux_feed *), + void *priv) +{ + dvbdemux->priv = priv; + + dvbdemux->filternum = 256; + dvbdemux->feednum = 256; + dvbdemux->start_feed = start_feed; + dvbdemux->stop_feed = stop_feed; + dvbdemux->write_to_decoder = 0; + dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | + DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING); + return dvb_dmx_init(dvbdemux); +} + +static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, + struct dvb_demux *dvbdemux, + struct dmx_frontend *hw_frontend, + struct dmx_frontend *mem_frontend, + struct dvb_adapter *dvb_adapter) +{ + int ret; + + dmxdev->filternum = 256; + dmxdev->demux = &dvbdemux->dmx; + dmxdev->capabilities = 0; + ret = dvb_dmxdev_init(dmxdev, dvb_adapter); + if (ret < 0) + return ret; + + hw_frontend->source = DMX_FRONTEND_0; + dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); + mem_frontend->source = DMX_MEMORY_FE; + dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); + return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); +} + +/****************************************************************************/ +/* Decypher firmware loading ************************************************/ +/****************************************************************************/ + +#define DECYPHER_FW "decypher.fw" + +static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) +{ + while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) + msleep(1); + + + dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); + + return len; +} + +u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; + +int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) +{ + struct ngene_channel *chan = &dev->channel[4]; + u32 len = 180, cc = 0; + u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; + + set_transfer(chan, 1); + msleep(100); + while (size) { + len = 180; + if (len > size) + len = size; + buf[3] = 0x10 | (cc & 0x0f); + buf[4] = (cc >> 8); + buf[5] = cc & 0xff; + buf[6] = len; + + dec_ts_send(dev, buf, 8); + dec_ts_send(dev, fw, len); + if (len < 180) + dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); + cc++; + size -= len; + fw += len; + } + for (len = 0; len < 512; len++) + dec_ts_send(dev, dec_fw_fill_ts, 188); + while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) + msleep(10); + msleep(100); + set_transfer(chan, 0); + return 0; +} + +int dec_fw_boot(struct ngene *dev) +{ + u32 size; + const struct firmware *fw = NULL; + u8 *dec_fw; + char *fw_name; + int err, version; + + if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { + printk(KERN_ERR DEVICE_NAME + ": %s not found. Check hotplug directory.\n", + DECYPHER_FW); + return -1; + } + printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", + DECYPHER_FW); + + size = fw->size; + dec_fw = fw->data; + dec_fw_send(dev, dec_fw, size); + release_firmware(fw); + return 0; +} + +/****************************************************************************/ +/* nGene hardware init and release functions ********************************/ +/****************************************************************************/ + +void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) +{ + struct SBufferHeader *Cur = rb->Head; + u32 j; + + if (!Cur) + return; + + for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) { + if (Cur->Buffer1) + pci_free_consistent(dev->pci_dev, + rb->Buffer1Length, + Cur->Buffer1, + Cur->scList1->Address); + + if (Cur->Buffer2) + pci_free_consistent(dev->pci_dev, + rb->Buffer2Length, + Cur->Buffer2, + Cur->scList2->Address); + } + + if (rb->SCListMem) + pci_free_consistent(dev->pci_dev, rb->SCListMemSize, + rb->SCListMem, rb->PASCListMem); + + pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead); +} + +void free_idlebuffer(struct ngene *dev, + struct SRingBufferDescriptor *rb, + struct SRingBufferDescriptor *tb) +{ + int j; + struct SBufferHeader *Cur = tb->Head; + + if (!rb->Head) + return; + free_ringbuffer(dev, rb); + for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) { + Cur->Buffer2 = 0; + Cur->scList2 = 0; + Cur->ngeneBuffer.Address_of_first_entry_2 = 0; + Cur->ngeneBuffer.Number_of_entries_2 = 0; + } +} + +void free_common_buffers(struct ngene *dev) +{ + u32 i; + struct ngene_channel *chan; + + for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { + chan = &dev->channel[i]; + free_idlebuffer(dev, &chan->TSIdleBuffer, &chan->TSRingBuffer); + free_ringbuffer(dev, &chan->RingBuffer); + free_ringbuffer(dev, &chan->TSRingBuffer); + } + + if (dev->OverflowBuffer) + pci_free_consistent(dev->pci_dev, + OVERFLOW_BUFFER_SIZE, + dev->OverflowBuffer, dev->PAOverflowBuffer); + + if (dev->FWInterfaceBuffer) + pci_free_consistent(dev->pci_dev, + 4096, + dev->FWInterfaceBuffer, + dev->PAFWInterfaceBuffer); +} + +/****************************************************************************/ +/* Ring buffer handling *****************************************************/ +/****************************************************************************/ + +int create_ring_buffer(struct pci_dev *pci_dev, + struct SRingBufferDescriptor *descr, u32 NumBuffers) +{ + dma_addr_t tmp; + struct SBufferHeader *Head; + u32 i; + u32 MemSize = SIZEOF_SBufferHeader * NumBuffers; + u64 PARingBufferHead; + u64 PARingBufferCur; + u64 PARingBufferNext; + struct SBufferHeader *Cur, *Next; + + descr->Head = 0; + descr->MemSize = 0; + descr->PAHead = 0; + descr->NumBuffers = 0; + + if (MemSize < 4096) + MemSize = 4096; + + Head = pci_alloc_consistent(pci_dev, MemSize, &tmp); + PARingBufferHead = tmp; + + if (!Head) + return -ENOMEM; + + memset(Head, 0, MemSize); + + PARingBufferCur = PARingBufferHead; + Cur = Head; + + for (i = 0; i < NumBuffers - 1; i++) { + Next = (struct SBufferHeader *) + (((u8 *) Cur) + SIZEOF_SBufferHeader); + PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader; + Cur->Next = Next; + Cur->ngeneBuffer.Next = PARingBufferNext; + Cur = Next; + PARingBufferCur = PARingBufferNext; + } + /* Last Buffer points back to first one */ + Cur->Next = Head; + Cur->ngeneBuffer.Next = PARingBufferHead; + + descr->Head = Head; + descr->MemSize = MemSize; + descr->PAHead = PARingBufferHead; + descr->NumBuffers = NumBuffers; + + return 0; +} + +static int AllocateRingBuffers(struct pci_dev *pci_dev, + dma_addr_t of, + struct SRingBufferDescriptor *pRingBuffer, + u32 Buffer1Length, u32 Buffer2Length) +{ + dma_addr_t tmp; + u32 i, j; + int status = 0; + u32 SCListMemSize = pRingBuffer->NumBuffers + * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) : + NUM_SCATTER_GATHER_ENTRIES) + * sizeof(struct HW_SCATTER_GATHER_ELEMENT); + + u64 PASCListMem; + PHW_SCATTER_GATHER_ELEMENT SCListEntry; + u64 PASCListEntry; + struct SBufferHeader *Cur; + void *SCListMem; + + if (SCListMemSize < 4096) + SCListMemSize = 4096; + + SCListMem = pci_alloc_consistent(pci_dev, SCListMemSize, &tmp); + + PASCListMem = tmp; + if (SCListMem == NULL) + return -ENOMEM; + + memset(SCListMem, 0, SCListMemSize); + + pRingBuffer->SCListMem = SCListMem; + pRingBuffer->PASCListMem = PASCListMem; + pRingBuffer->SCListMemSize = SCListMemSize; + pRingBuffer->Buffer1Length = Buffer1Length; + pRingBuffer->Buffer2Length = Buffer2Length; + + SCListEntry = (PHW_SCATTER_GATHER_ELEMENT) SCListMem; + PASCListEntry = PASCListMem; + Cur = pRingBuffer->Head; + + for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) { + u64 PABuffer; + + void *Buffer = pci_alloc_consistent(pci_dev, Buffer1Length, + &tmp); + PABuffer = tmp; + + if (Buffer == NULL) + return -ENOMEM; + + Cur->Buffer1 = Buffer; + + SCListEntry->Address = PABuffer; + SCListEntry->Length = Buffer1Length; + + Cur->scList1 = SCListEntry; + Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry; + Cur->ngeneBuffer.Number_of_entries_1 = + NUM_SCATTER_GATHER_ENTRIES; + + SCListEntry += 1; + PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); + +#if NUM_SCATTER_GATHER_ENTRIES > 1 + for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) { + SCListEntry->Address = of; + SCListEntry->Length = OVERFLOW_BUFFER_SIZE; + SCListEntry += 1; + PASCListEntry += + sizeof(struct HW_SCATTER_GATHER_ELEMENT); + } +#endif + + if (!Buffer2Length) + continue; + + Buffer = pci_alloc_consistent(pci_dev, Buffer2Length, &tmp); + PABuffer = tmp; + + if (Buffer == NULL) + return -ENOMEM; + + Cur->Buffer2 = Buffer; + + SCListEntry->Address = PABuffer; + SCListEntry->Length = Buffer2Length; + + Cur->scList2 = SCListEntry; + Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry; + Cur->ngeneBuffer.Number_of_entries_2 = + NUM_SCATTER_GATHER_ENTRIES; + + SCListEntry += 1; + PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); + +#if NUM_SCATTER_GATHER_ENTRIES > 1 + for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) { + SCListEntry->Address = of; + SCListEntry->Length = OVERFLOW_BUFFER_SIZE; + SCListEntry += 1; + PASCListEntry += + sizeof(struct HW_SCATTER_GATHER_ELEMENT); + } +#endif + + } + + return status; +} + +static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, + struct SRingBufferDescriptor *pRingBuffer) +{ + int status = 0; + + /* Copy pointer to scatter gather list in TSRingbuffer + structure for buffer 2 + Load number of buffer + */ + u32 n = pRingBuffer->NumBuffers; + + /* Point to first buffer entry */ + struct SBufferHeader *Cur = pRingBuffer->Head; + int i; + /* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */ + for (i = 0; i < n; i++) { + Cur->Buffer2 = pIdleBuffer->Head->Buffer1; + Cur->scList2 = pIdleBuffer->Head->scList1; + Cur->ngeneBuffer.Address_of_first_entry_2 = + pIdleBuffer->Head->ngeneBuffer. + Address_of_first_entry_1; + Cur->ngeneBuffer.Number_of_entries_2 = + pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1; + Cur = Cur->Next; + } + return status; +} + +static u32 RingBufferSizes[MAX_STREAM] = { + RING_SIZE_VIDEO, + RING_SIZE_VIDEO, + RING_SIZE_AUDIO, + RING_SIZE_AUDIO, + RING_SIZE_AUDIO, +}; + +static u32 Buffer1Sizes[MAX_STREAM] = { + MAX_VIDEO_BUFFER_SIZE, + MAX_VIDEO_BUFFER_SIZE, + MAX_AUDIO_BUFFER_SIZE, + MAX_AUDIO_BUFFER_SIZE, + MAX_AUDIO_BUFFER_SIZE +}; + +static u32 Buffer2Sizes[MAX_STREAM] = { + MAX_VBI_BUFFER_SIZE, + MAX_VBI_BUFFER_SIZE, + 0, + 0, + 0 +}; + +static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, + struct SRingBufferDescriptor *rbuf, + u32 entries, u32 size1, u32 size2) +{ + if (create_ring_buffer(pci_dev, rbuf, entries) < 0) + return -ENOMEM; + + if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) + return -ENOMEM; + + return 0; +} + +static int channel_allocate_buffers(struct ngene_channel *chan) +{ + struct ngene *dev = chan->dev; + int type = dev->card_info->io_type[chan->number]; + int status; + + chan->State = KSSTATE_STOP; + + if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { + status = create_ring_buffer(dev->pci_dev, + &chan->RingBuffer, + RingBufferSizes[chan->number]); + if (status < 0) + return -ENOMEM; + + if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { + status = AllocateRingBuffers(dev->pci_dev, + dev->PAOverflowBuffer, + &chan->RingBuffer, + Buffer1Sizes[chan->number], + Buffer2Sizes[chan-> + number]); + if (status < 0) + return -ENOMEM; + } else if (type & NGENE_IO_HDTV) { + status = AllocateRingBuffers(dev->pci_dev, + dev->PAOverflowBuffer, + &chan->RingBuffer, + MAX_HDTV_BUFFER_SIZE, 0); + if (status < 0) + return -ENOMEM; + } + } + + if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { + + status = create_ring_buffer(dev->pci_dev, + &chan->TSRingBuffer, RING_SIZE_TS); + if (status < 0) + return -ENOMEM; + + status = AllocateRingBuffers(dev->pci_dev, + dev->PAOverflowBuffer, + &chan->TSRingBuffer, + MAX_TS_BUFFER_SIZE, 0); + if (status) + return -ENOMEM; + } + + if (type & NGENE_IO_TSOUT) { + status = create_ring_buffer(dev->pci_dev, + &chan->TSIdleBuffer, 1); + if (status < 0) + return -ENOMEM; + status = AllocateRingBuffers(dev->pci_dev, + dev->PAOverflowBuffer, + &chan->TSIdleBuffer, + MAX_TS_BUFFER_SIZE, 0); + if (status) + return -ENOMEM; + FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); + } + return 0; +} + +static int AllocCommonBuffers(struct ngene *dev) +{ + int status = 0, i; + + dev->FWInterfaceBuffer = pci_alloc_consistent(dev->pci_dev, 4096, + &dev->PAFWInterfaceBuffer); + if (!dev->FWInterfaceBuffer) + return -ENOMEM; + dev->hosttongene = dev->FWInterfaceBuffer; + dev->ngenetohost = dev->FWInterfaceBuffer + 256; + dev->EventBuffer = dev->FWInterfaceBuffer + 512; + + dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev, + OVERFLOW_BUFFER_SIZE, + &dev->PAOverflowBuffer); + if (!dev->OverflowBuffer) + return -ENOMEM; + memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE); + + for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { + int type = dev->card_info->io_type[i]; + + dev->channel[i].State = KSSTATE_STOP; + + if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { + status = create_ring_buffer(dev->pci_dev, + &dev->channel[i].RingBuffer, + RingBufferSizes[i]); + if (status < 0) + break; + + if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { + status = AllocateRingBuffers(dev->pci_dev, + dev-> + PAOverflowBuffer, + &dev->channel[i]. + RingBuffer, + Buffer1Sizes[i], + Buffer2Sizes[i]); + if (status < 0) + break; + } else if (type & NGENE_IO_HDTV) { + status = AllocateRingBuffers(dev->pci_dev, + dev-> + PAOverflowBuffer, + &dev->channel[i]. + RingBuffer, + MAX_HDTV_BUFFER_SIZE, + 0); + if (status < 0) + break; + } + } + + if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { + + status = create_ring_buffer(dev->pci_dev, + &dev->channel[i]. + TSRingBuffer, RING_SIZE_TS); + if (status < 0) + break; + + status = AllocateRingBuffers(dev->pci_dev, + dev->PAOverflowBuffer, + &dev->channel[i]. + TSRingBuffer, + MAX_TS_BUFFER_SIZE, 0); + if (status) + break; + } + + if (type & NGENE_IO_TSOUT) { + status = create_ring_buffer(dev->pci_dev, + &dev->channel[i]. + TSIdleBuffer, 1); + if (status < 0) + break; + status = AllocateRingBuffers(dev->pci_dev, + dev->PAOverflowBuffer, + &dev->channel[i]. + TSIdleBuffer, + MAX_TS_BUFFER_SIZE, 0); + if (status) + break; + FillTSIdleBuffer(&dev->channel[i].TSIdleBuffer, + &dev->channel[i].TSRingBuffer); + } + } + return status; +} + +static void ngene_release_buffers(struct ngene *dev) +{ + if (dev->iomem) + iounmap(dev->iomem); + free_common_buffers(dev); + vfree(dev->tsout_buf); + vfree(dev->ain_buf); + vfree(dev->vin_buf); + vfree(dev); +} + +static int ngene_get_buffers(struct ngene *dev) +{ + if (AllocCommonBuffers(dev)) + return -ENOMEM; + if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) { + dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE); + if (!dev->tsout_buf) + return -ENOMEM; + dvb_ringbuffer_init(&dev->tsout_rbuf, + dev->tsout_buf, TSOUT_BUF_SIZE); + } + if (dev->card_info->io_type[2] & NGENE_IO_AIN) { + dev->ain_buf = vmalloc(AIN_BUF_SIZE); + if (!dev->ain_buf) + return -ENOMEM; + dvb_ringbuffer_init(&dev->ain_rbuf, dev->ain_buf, AIN_BUF_SIZE); + } + if (dev->card_info->io_type[0] & NGENE_IO_HDTV) { + dev->vin_buf = vmalloc(VIN_BUF_SIZE); + if (!dev->vin_buf) + return -ENOMEM; + dvb_ringbuffer_init(&dev->vin_rbuf, dev->vin_buf, VIN_BUF_SIZE); + } + dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0), + pci_resource_len(dev->pci_dev, 0)); + if (!dev->iomem) + return -ENOMEM; + + return 0; +} + +static void ngene_init(struct ngene *dev) +{ + int i; + + tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev); + + memset_io(dev->iomem + 0xc000, 0x00, 0x220); + memset_io(dev->iomem + 0xc400, 0x00, 0x100); + + for (i = 0; i < MAX_STREAM; i++) { + dev->channel[i].dev = dev; + dev->channel[i].number = i; + } + + dev->fw_interface_version = 0; + + ngwritel(0, NGENE_INT_ENABLE); + + dev->icounts = ngreadl(NGENE_INT_COUNTS); + + dev->device_version = ngreadl(DEV_VER) & 0x0f; + printk(KERN_INFO DEVICE_NAME ": Device version %d\n", + dev->device_version); +} + +static int ngene_load_firm(struct ngene *dev) +{ + u32 size; + const struct firmware *fw = NULL; + u8 *ngene_fw; + char *fw_name; + int err, version; + + version = dev->card_info->fw_version; + + switch (version) { + default: + case 15: + version = 15; + ngene_fw = FW15; + size = sizeof(FW15); + fw_name = "ngene_15.fw"; + break; + case 16: + ngene_fw = FW16; + size = sizeof(FW16); + fw_name = "ngene_16.fw"; + break; + case 17: + ngene_fw = FW17; + size = sizeof(FW17); + fw_name = "ngene_17.fw"; + break; + } +#ifdef FW_INC + if (load_firmware && + request_firmware(&fw, fw_name, &dev->pci_dev->dev) >= 0) { + printk(KERN_INFO DEVICE_NAME + ": Loading firmware file %s.\n", fw_name); + size = fw->size; + ngene_fw = fw->data; + } else + printk(KERN_INFO DEVICE_NAME + ": Loading built-in firmware version %d.\n", version); + err = ngene_command_load_firmware(dev, ngene_fw, size); + + if (fw) + release_firmware(fw); +#else + if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) { + printk(KERN_ERR DEVICE_NAME + ": Could not load firmware file %s. \n", fw_name); + printk(KERN_INFO DEVICE_NAME + ": Copy %s to your hotplug directory!\n", fw_name); + return -1; + } + printk(KERN_INFO DEVICE_NAME ": Loading firmware file %s.\n", fw_name); + size = fw->size; + ngene_fw = fw->data; + err = ngene_command_load_firmware(dev, ngene_fw, size); + release_firmware(fw); +#endif + return err; +} + +static void ngene_stop(struct ngene *dev) +{ + down(&dev->cmd_mutex); + i2c_del_adapter(&(dev->channel[0].i2c_adapter)); + i2c_del_adapter(&(dev->channel[1].i2c_adapter)); + ngwritel(0, NGENE_INT_ENABLE); + ngwritel(0, NGENE_COMMAND); + ngwritel(0, NGENE_COMMAND_HI); + ngwritel(0, NGENE_STATUS); + ngwritel(0, NGENE_STATUS_HI); + ngwritel(0, NGENE_EVENT); + ngwritel(0, NGENE_EVENT_HI); + free_irq(dev->pci_dev->irq, dev); +} + +static int ngene_start(struct ngene *dev) +{ + int stat; + int i; + + pci_set_master(dev->pci_dev); + ngene_init(dev); + + stat = request_irq(dev->pci_dev->irq, irq_handler, + IRQF_SHARED, "nGene", + (void *)dev); + if (stat < 0) + return stat; + + init_waitqueue_head(&dev->cmd_wq); + init_waitqueue_head(&dev->tx_wq); + init_waitqueue_head(&dev->rx_wq); + sema_init(&dev->cmd_mutex, 1); + sema_init(&dev->stream_mutex, 1); + sema_init(&dev->pll_mutex, 1); + sema_init(&dev->i2c_switch_mutex, 1); + spin_lock_init(&dev->cmd_lock); + for (i = 0; i < MAX_STREAM; i++) + spin_lock_init(&dev->channel[i].state_lock); + ngwritel(1, TIMESTAMPS); + + ngwritel(1, NGENE_INT_ENABLE); + + stat = ngene_load_firm(dev); + if (stat < 0) + goto fail; + + stat = ngene_i2c_init(dev, 0); + if (stat < 0) + goto fail; + + stat = ngene_i2c_init(dev, 1); + if (stat < 0) + goto fail; + + if (dev->card_info->fw_version == 17) { + u8 hdtv_config[6] = + {6144 / 64, 0, 0, 2048 / 64, 2048 / 64, 2048 / 64}; + u8 tsin4_config[6] = + {3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; + u8 ts5_config[6] = + {2048 / 64, 2048 / 64, 0, 2048 / 64, 2048 / 64, + 2048 / 64}; + u8 default_config[6] = + {4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0}; + u8 *bconf = default_config; + + if (dev->card_info->io_type[3] == NGENE_IO_TSIN) + bconf = tsin4_config; + if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { + bconf = hdtv_config; + ngene_reset_decypher(dev); + } + printk(KERN_INFO DEVICE_NAME ": FW 17 buffer config\n"); + stat = ngene_command_config_free_buf(dev, bconf); + } else { + int bconf = BUFFER_CONFIG_4422; + + if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { + bconf = BUFFER_CONFIG_8022; + ngene_reset_decypher(dev); + } + if (dev->card_info->io_type[3] == NGENE_IO_TSIN) + bconf = BUFFER_CONFIG_3333; + stat = ngene_command_config_buf(dev, bconf); + } + + if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { + ngene_command_config_uart(dev, 0xc1, tx_cb, rx_cb); + test_dec_i2c(&dev->channel[0].i2c_adapter, 0); + test_dec_i2c(&dev->channel[0].i2c_adapter, 1); + } + + return stat; +fail: + ngwritel(0, NGENE_INT_ENABLE); + free_irq(dev->pci_dev->irq, dev); + return stat; +} + +/****************************************************************************/ +/* DVB audio/video device functions *****************************************/ +/****************************************************************************/ + +static ssize_t audio_write(struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + int left; + int avail; + + left = count; + while (left) { + if (wait_event_interruptible( + dev->ain_rbuf.queue, + dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) + return -EAGAIN; + avail = dvb_ringbuffer_avail(&dev->ain_rbuf); + if (avail > left) + avail = left; + dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); + left -= avail; + buf += avail; + } + return count; +} + +static int audio_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + struct ngene_channel *chan2 = &chan->dev->channel[2]; + int ret; + + ret = dvb_generic_open(inode, file); + if (ret < 0) + return ret; + my_dvb_ringbuffer_flush(&dev->ain_rbuf); + + chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; + chan2->pBufferExchange = ain_exchange; + ngene_command_stream_control(chan2->dev, chan2->number, 0x80, + SMODE_AUDIO_CAPTURE, 0); + return ret; +} + +static int audio_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + struct ngene_channel *chan2 = &chan->dev->channel[2]; + + ngene_command_stream_control(dev, 2, 0, 0, 0); + chan2->pBufferExchange = 0; + + return dvb_generic_release(inode, file); +} + +static const struct file_operations audio_fops = { + .owner = THIS_MODULE, + .read = audio_read, + .write = audio_write, + .open = audio_open, + .release = audio_release, +}; + +static struct dvb_device dvbdev_audio = { + .priv = 0, + .readers = -1, + .writers = 1, + .users = 1, + .fops = &audio_fops, +}; + +static int video_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + struct ngene_channel *chan0 = &chan->dev->channel[0]; + int ret; + + ret = dvb_generic_open(inode, file); + if (ret < 0) + return ret; + if ((file->f_flags & O_ACCMODE) != O_RDONLY) + return ret; + my_dvb_ringbuffer_flush(&dev->vin_rbuf); + + chan0->nBytesPerLine = 1920 * 2; + chan0->nLines = 540; + chan0->Capture1Length = 1920 * 2 * 540; + chan0->pBufferExchange = vcap_exchange; + chan0->itumode = 2; + ngene_command_stream_control(chan0->dev, chan0->number, + 0x80, SMODE_VIDEO_CAPTURE, 0); + return ret; +} + +static int video_release(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + struct ngene_channel *chan0 = &chan->dev->channel[0]; + + ngene_command_stream_control(dev, 0, 0, 0, 0); + chan0->pBufferExchange = 0; + + return dvb_generic_release(inode, file); +} + +static ssize_t video_write(struct file *file, + const char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + int left, avail; + + left = count; + while (left) { + if (wait_event_interruptible( + dev->vin_rbuf.queue, + dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) + return -EAGAIN; + avail = dvb_ringbuffer_avail(&dev->vin_rbuf); + if (avail > left) + avail = left; + dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); + left -= avail; + buf += avail; + } + return count; +} + +/* Why is this not exported from dvb_core ?!?! */ + +static int dvb_usercopy2(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *)arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + err = func(inode, file, cmd, parg); + if (err == -ENOIOCTLCMD) + err = -EINVAL; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + kfree(mbuf); + return err; +} + +static int video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) +{ + struct dvb_device *dvbdev = file->private_data; + struct ngene_channel *chan = dvbdev->priv; + struct ngene *dev = chan->dev; + int ret = 0; + unsigned long arg = (unsigned long)parg; + + switch (cmd) { + case VIDEO_SET_STREAMTYPE: + switch (arg) { + case VIDEO_CAP_MPEG2: + /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ + send_cli(dev, "vdec mpeg2\n"); + break; + case VIDEO_CAP_AVC: + /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ + send_cli(dev, "vdec h264\n"); + break; + case VIDEO_CAP_VC1: + /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ + send_cli(dev, "vdec vc1\n"); + break; + default: + ret = -EINVAL; + break; + } + break; + default: + ret = -ENOIOCTLCMD; + return -EINVAL; + } + return ret; +} + +static int video_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); +} + +static const struct file_operations video_fops = { + .owner = THIS_MODULE, + .read = video_read, + .write = video_write, + .open = video_open, + .release = video_release, + .ioctl = video_ioctl, +}; + +static struct dvb_device dvbdev_video = { + .priv = 0, + .readers = -1, + .writers = 1, + .users = -1, + .fops = &video_fops, +}; + +/****************************************************************************/ +/* LNBH21 *******************************************************************/ +/****************************************************************************/ + +static int lnbh21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct ngene_channel *chan = + *(struct ngene_channel **) fe->demodulator_priv; + + switch (voltage) { + case SEC_VOLTAGE_OFF: + chan->lnbh &= 0xf3; + break; + case SEC_VOLTAGE_13: + chan->lnbh |= 0x04; + chan->lnbh &= ~0x08; + break; + case SEC_VOLTAGE_18: + chan->lnbh |= 0x0c; + break; + default: + return -EINVAL; + }; + chan->lnbh |= 0x10; + return i2c_write(&chan->i2c_adapter, + chan->dev->card_info->lnb[chan->number], chan->lnbh); +} + +static int lnbh21_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct ngene_channel *chan = + *(struct ngene_channel **)fe->demodulator_priv; + + switch (tone) { + case SEC_TONE_ON: + chan->lnbh |= 0x20; + break; + case SEC_TONE_OFF: + chan->lnbh &= 0xdf; + break; + default: + return -EINVAL; + } + return i2c_write(&chan->i2c_adapter, + chan->dev->card_info->lnb[chan->number], chan->lnbh); +} + +/****************************************************************************/ +/* Switch control (I2C gates, etc.) *****************************************/ +/****************************************************************************/ + +static int avf_output(struct ngene_channel *chan, int state) +{ + if (chan->dev->card_info->avf[chan->number]) + i2c_write_register(&chan->i2c_adapter, + chan->dev->card_info->avf[chan->number], + 0xf2, state ? 0x89 : 0x80); + return 0; +} + +/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ + +static int exp_set(struct ngene *dev) +{ + return i2c_write(&dev->channel[0].i2c_adapter, + dev->card_info->exp, dev->exp_val); +} + +static int exp_init(struct ngene *dev) +{ + if (!dev->card_info->exp) + return 0; + dev->exp_val = dev->card_info->exp_init; + return exp_set(dev); +} + +static int exp_set_bit(struct ngene *dev, int bit, int val) +{ + if (val) + set_bit(bit, &dev->exp_val); + else + clear_bit(bit, &dev->exp_val); + return exp_set(dev); +} + +static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) +{ + switch (type) { + case 0: /* I2C tuner gate on/off */ + return exp_set_bit(chan->dev, 4 + chan->number, val); + case 1: /* Stream: 0=TS 1=ITU */ + avf_output(chan, val); + return exp_set_bit(chan->dev, 6 + chan->number, val); + case 2: /* Input: 0=digital 1=analog antenna input */ + exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); + exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); + break; + } + return 0; +} + +static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) +{ + switch (type) { + case 0: /* I2C tuner gate on/off */ + return exp_set_bit(chan->dev, 4 + chan->number, val); + case 1: /* Stream: 0=TS 1=ITU */ + avf_output(chan, val); + return exp_set_bit(chan->dev, 6 + chan->number, val); + case 2: /* Input: 0=digital 1=analog antenna input */ + exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); + exp_set_bit(chan->dev, 1 + chan->number * 2, 0); + break; + } + return 0; +} + +static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + /* Well, just abuse sec :-) */ + struct ngene_channel *chan = fe->sec_priv; + struct ngene *dev = chan->dev; + + return dev->card_info->switch_ctrl(chan, 0, enable); +} + +static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) +{ + switch (type) { + case 0: /* I2C tuner gate on/off */ + if (chan->number > 1) + return -EINVAL; + return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); + case 1: /* Stream: 0=TS 1=ITU */ + avf_output(chan, val); + return 0; + } + return 0; +} + +static int viper_reset_xc(struct dvb_frontend *fe) +{ + struct ngene_channel *chan = fe->sec_priv; + struct ngene *dev = chan->dev; + + printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); + + if (chan->number > 1) + return -EINVAL; + + ngene_command_gpio_set(dev, 3 + chan->number, 0); + msleep(150); + ngene_command_gpio_set(dev, 3 + chan->number, 1); + return 0; +} + +static int python_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct ngene_channel *chan = fe->sec_priv; + struct ngene *dev = chan->dev; + + if (chan->number == 0) + return ngene_command_gpio_set(dev, 3, enable); + if (chan->number == 1) + return ngene_command_gpio_set(dev, 4, enable); + return -EINVAL; +} + +/****************************************************************************/ +/* Demod/tuner attachment ***************************************************/ +/****************************************************************************/ + +static int tuner_attach_mt2060(struct ngene_channel *chan) +{ + struct ngene *dev = chan->dev; + void *tconf = dev->card_info->tuner_config[chan->number]; + u8 drxa = dev->card_info->demoda[chan->number]; + struct dvb_frontend *fe = chan->fe, *fe2; + + fe->sec_priv = chan; + fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; + + dev->card_info->gate_ctrl(fe, 1); + fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); + dev->card_info->gate_ctrl(fe, 0); + + i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); + write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); + write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); + write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); + + return fe2 ? 0 : -ENODEV; +} + +static int tuner_attach_xc3028(struct ngene_channel *chan) +{ + struct ngene *dev = chan->dev; + void *tconf = dev->card_info->tuner_config[chan->number]; + struct dvb_frontend *fe = chan->fe, *fe2; + + fe->sec_priv = chan; + fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; + + dev->card_info->gate_ctrl(fe, 1); + fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); + dev->card_info->gate_ctrl(fe, 0); + + /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ + + return fe2 ? 0 : -ENODEV; +} + +static int demod_attach_drxd(struct ngene_channel *chan) +{ + void *feconf = chan->dev->card_info->fe_config[chan->number]; + + chan->fe = drxd_attach(feconf, + chan, &chan->i2c_adapter, + &chan->dev->pci_dev->dev); + return (chan->fe) ? 0 : -ENODEV; +} + +static int demod_attach_drxh(struct ngene_channel *chan) +{ + void *feconf = chan->dev->card_info->fe_config[chan->number]; + + chan->fe = drxh_attach(feconf, chan, + &chan->i2c_adapter, &chan->dev->pci_dev->dev); + return (chan->fe) ? 0 : -ENODEV; +} + +static int demod_attach_stb0899(struct ngene_channel *chan) +{ + void *feconf = chan->dev->card_info->fe_config[chan->number]; + + chan->fe = stb0899_attach(feconf, + chan, &chan->i2c_adapter, + &chan->dev->pci_dev->dev); + if (chan->fe) { + chan->set_tone = chan->fe->ops.set_tone; + chan->fe->ops.set_tone = lnbh21_set_tone; + chan->fe->ops.set_voltage = lnbh21_set_voltage; + } + + return (chan->fe) ? 0 : -ENODEV; +} + +static int demod_attach_stv0900(struct ngene_channel *chan) +{ + void *feconf = chan->dev->card_info->fe_config[chan->number]; + + chan->fe = stv0900_attach(feconf, + chan, &chan->i2c_adapter, + &chan->dev->pci_dev->dev); + + if (chan->fe) { + chan->set_tone = chan->fe->ops.set_tone; + chan->fe->ops.set_tone = lnbh21_set_tone; + chan->fe->ops.set_voltage = lnbh21_set_voltage; + } + + return (chan->fe) ? 0 : -ENODEV; +} + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +static void release_channel(struct ngene_channel *chan) +{ + struct dvb_demux *dvbdemux = &chan->demux; + struct ngene *dev = chan->dev; + struct ngene_info *ni = dev->card_info; + int io = ni->io_type[chan->number]; + + tasklet_kill(&chan->demux_tasklet); + + if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { +#ifdef NGENE_COMMAND_API + if (chan->command_dev) + dvb_unregister_device(chan->command_dev); +#endif + if (chan->audio_dev) + dvb_unregister_device(chan->audio_dev); + if (chan->video_dev) + dvb_unregister_device(chan->video_dev); + if (chan->fe) { + dvb_unregister_frontend(chan->fe); + /*dvb_frontend_detach(chan->fe); */ + chan->fe = 0; + } + dvbdemux->dmx.close(&dvbdemux->dmx); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, + &chan->hw_frontend); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, + &chan->mem_frontend); + dvb_dmxdev_release(&chan->dmxdev); + dvb_dmx_release(&chan->demux); +#ifndef ONE_ADAPTER + dvb_unregister_adapter(&chan->dvb_adapter); +#endif + } + + if (io & (NGENE_IO_AIN)) { + ngene_snd_exit(chan); + kfree(chan->soundbuffer); + } +} + +static int init_channel(struct ngene_channel *chan) +{ + int ret = 0, nr = chan->number; + struct dvb_adapter *adapter = 0; + struct dvb_demux *dvbdemux = &chan->demux; + struct ngene *dev = chan->dev; + struct ngene_info *ni = dev->card_info; + int io = ni->io_type[nr]; + + tasklet_init(&chan->demux_tasklet, demux_tasklet, (unsigned long)chan); + chan->users = 0; + chan->type = io; + chan->mode = chan->type; /* for now only one mode */ + + if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { + if (nr >= STREAM_AUDIOIN1) + chan->DataFormatFlags = DF_SWAP32; + + if (io & NGENE_IO_TSOUT) + dec_fw_boot(dev); + +#ifdef ONE_ADAPTER + adapter = &chan->dev->dvb_adapter; +#else + ret = dvb_register_adapter(&chan->dvb_adapter, "nGene", + THIS_MODULE, + &chan->dev->pci_dev->dev); + if (ret < 0) + return ret; + adapter = &chan->dvb_adapter; +#endif + ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", + ngene_start_feed, + ngene_stop_feed, chan); + ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux, + &chan->hw_frontend, + &chan->mem_frontend, adapter); + if (io & NGENE_IO_TSOUT) { + dvbdemux->write_to_decoder = write_to_decoder; + dvb_register_device(adapter, &chan->audio_dev, + &dvbdev_audio, (void *)chan, + DVB_DEVICE_AUDIO); + dvb_register_device(adapter, &chan->video_dev, + &dvbdev_video, (void *)chan, + DVB_DEVICE_VIDEO); + + } +#ifdef NGENE_COMMAND_API + dvb_register_device(adapter, &chan->command_dev, + &dvbdev_command, (void *)chan, + DVB_DEVICE_SEC); +#endif + } + + if (io & NGENE_IO_TSIN) { + chan->fe = NULL; + if (ni->demod_attach[nr]) + ni->demod_attach[nr](chan); + if (chan->fe) { + if (dvb_register_frontend(adapter, chan->fe) < 0) { + if (chan->fe->ops.release) + chan->fe->ops.release(chan->fe); + chan->fe = NULL; + } + } + if (chan->fe && ni->tuner_attach[nr]) + if (ni->tuner_attach[nr] (chan) < 0) { + printk(KERN_ERR DEVICE_NAME + ": Tuner attach failed on channel %d!\n", + nr); + } + } + + if (io & (NGENE_IO_AIN)) { + ngene_snd_init(chan); +#ifdef NGENE_V4L + spin_lock_init(&chan->s_lock); + init_MUTEX(&chan->reslock); + INIT_LIST_HEAD(&chan->capture); +#endif + + chan->soundbuffer = kmalloc(MAX_AUDIO_BUFFER_SIZE, GFP_KERNEL); + if (!chan->soundbuffer) + return -ENOMEM; + memset(chan->soundbuffer, 0, MAX_AUDIO_BUFFER_SIZE); + } + return ret; +} + +static int init_channels(struct ngene *dev) +{ + int i, j; + + for (i = 0; i < MAX_STREAM; i++) { + if (init_channel(&dev->channel[i]) < 0) { + for (j = 0; j < i; j++) + release_channel(&dev->channel[j]); + return -1; + } + } + return 0; +} + +/****************************************************************************/ +/* device probe/remove calls ************************************************/ +/****************************************************************************/ + +static void __devexit ngene_remove(struct pci_dev *pdev) +{ + struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); + int i; + + tasklet_kill(&dev->event_tasklet); + for (i = 0; i < MAX_STREAM; i++) + release_channel(&dev->channel[i]); +#ifdef ONE_ADAPTER + dvb_unregister_adapter(&dev->dvb_adapter); +#endif + ngene_stop(dev); + ngene_release_buffers(dev); + pci_set_drvdata(pdev, 0); + pci_disable_device(pdev); +} + +static int __devinit ngene_probe(struct pci_dev *pci_dev, + const struct pci_device_id *id) +{ + struct ngene *dev; + int stat = 0; + + if (pci_enable_device(pci_dev) < 0) + return -ENODEV; + + dev = vmalloc(sizeof(struct ngene)); + if (dev == NULL) + return -ENOMEM; + memset(dev, 0, sizeof(struct ngene)); + + dev->pci_dev = pci_dev; + dev->card_info = (struct ngene_info *)id->driver_data; + printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name); + + pci_set_drvdata(pci_dev, dev); + + /* Alloc buffers and start nGene */ + stat = ngene_get_buffers(dev); + if (stat < 0) + goto fail1; + stat = ngene_start(dev); + if (stat < 0) + goto fail1; + + dev->i2c_current_bus = -1; + exp_init(dev); + + /* Disable analog TV decoder chips if present */ + if (copy_eeprom) { + i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); + i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); + } + /*i2c_check_eeprom(&dev->i2c_adapter);*/ + + /* Register DVB adapters and devices for both channels */ +#ifdef ONE_ADAPTER + if (dvb_register_adapter(&dev->dvb_adapter, "nGene", THIS_MODULE, + &dev->pci_dev->dev, adapter_nr) < 0) + goto fail2; +#endif + if (init_channels(dev) < 0) + goto fail2; + + return 0; + +fail2: + ngene_stop(dev); +fail1: + ngene_release_buffers(dev); + pci_set_drvdata(pci_dev, 0); + return stat; +} + +/****************************************************************************/ +/* Card configs *************************************************************/ +/****************************************************************************/ + +static struct drxd_config fe_terratec_dvbt_0 = { + .index = 0, + .demod_address = 0x70, + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, + .pll_type = DRXD_PLL_DTT7520X, + .clock = 20000, + .pll_set = ngene_pll_set_th_dtt7520x, + .osc_deviation = osc_deviation, +}; + +static struct drxd_config fe_terratec_dvbt_1 = { + .index = 1, + .demod_address = 0x71, + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, + .pll_type = DRXD_PLL_DTT7520X, + .clock = 20000, + .pll_set = ngene_pll_set_th_dtt7520x, + .osc_deviation = osc_deviation, +}; + +static struct ngene_info ngene_info_terratec = { + .type = NGENE_TERRATEC, + .name = "Terratec Integra/Cinergy2400i Dual DVB-T", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, + .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, + .i2c_access = 1, +}; + +/****************************************************************************/ + +static struct mt2060_config tuner_python_0 = { + .i2c_address = 0x60, + .clock_out = 3, + .input = 0 +}; + +static struct mt2060_config tuner_python_1 = { + .i2c_address = 0x61, + .clock_out = 3, + .input = 1 +}; + +static struct drxd_config fe_python_0 = { + .index = 0, + .demod_address = 0x71, + .demod_revision = 0xb1, + .demoda_address = 0x41, + .clock = 16000, + .osc_deviation = osc_deviation, +}; + +static struct drxd_config fe_python_1 = { + .index = 1, + .demod_address = 0x70, + .demod_revision = 0xb1, + .demoda_address = 0x45, + .clock = 16000, + .osc_deviation = osc_deviation, +}; + +static struct ngene_info ngene_info_python = { + .type = NGENE_PYTHON, + .name = "Micronas MicPython/Hedgehog Dual DVB-T", + .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_AIN, NGENE_IO_AIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, + .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, + .fe_config = {&fe_python_0, &fe_python_1}, + .tuner_config = {&tuner_python_0, &tuner_python_1}, + .avf = {0x43, 0x47}, + .msp = {0x40, 0x42}, + .demoda = {0x41, 0x45}, + .gate_ctrl = python_gate_ctrl, + .switch_ctrl = python_switch_ctrl, +}; + +/****************************************************************************/ + +static struct drxd_config fe_appb_dvbt_0 = { + .index = 0, + .demod_address = 0x71, + .demod_revision = 0xa2, + .demoda_address = 0x41, + .pll_address = 0x63, + .pll_type = DRXD_PLL_MT3X0823, + .clock = 20000, + .pll_set = ngene_pll_set_mt_3x0823, + .osc_deviation = osc_deviation, +}; + +static struct drxd_config fe_appb_dvbt_1 = { + .index = 1, + .demod_address = 0x70, + .demod_revision = 0xa2, + .demoda_address = 0x45, + .pll_address = 0x60, + .pll_type = DRXD_PLL_MT3X0823, + .clock = 20000, + .pll_set = ngene_pll_set_mt_3x0823, + .osc_deviation = osc_deviation, +}; + +static struct ngene_info ngene_info_appboard = { + .type = NGENE_APP, + .name = "Micronas Application Board Dual DVB-T", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, + .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, + .avf = {0x43, 0x47}, +}; + +static struct ngene_info ngene_info_appboard_ntsc = { + .type = NGENE_APP, + .name = "Micronas Application Board Dual DVB-T", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, + .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, + .avf = {0x43, 0x47}, + .ntsc = 1, +}; + +/****************************************************************************/ + +static struct stb0899_config fe_sidewinder_0 = { + .demod_address = 0x68, + .pll_address = 0x63, +}; + +static struct stb0899_config fe_sidewinder_1 = { + .demod_address = 0x6b, + .pll_address = 0x60, +}; + +static struct ngene_info ngene_info_sidewinder = { + .type = NGENE_SIDEWINDER, + .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, + .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, + .lnb = {0x0b, 0x08}, +}; + +/****************************************************************************/ +/* Yet unnamed S2 card with dual DVB-S2 demod */ +/****************************************************************************/ + +static struct stv0900_config fe_s2_0 = { + .addr = 0x68, + .pll = 0x63, + .pll_type = 0, + .nr = 0, +}; + +static struct stv0900_config fe_s2_1 = { + .addr = 0x68, + .pll = 0x60, + .pll_type = 0, + .nr = 1, +}; + +static struct ngene_info ngene_info_s2 = { + .type = NGENE_SIDEWINDER, + .name = "S2", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, + NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, + .fe_config = {&fe_s2_0, &fe_s2_1}, + .lnb = {0x0b, 0x08}, + .tsf = {3, 3}, + .fw_version = 15, +}; + +static struct stv0900_config fe_s2b_0 = { + .addr = 0x68, + .pll = 0x60, + .pll_type = 0x10, + .nr = 0, +}; + +static struct stv0900_config fe_s2b_1 = { + .addr = 0x68, + .pll = 0x63, + .pll_type = 0x10, + .nr = 1, +}; + +static struct ngene_info ngene_info_s2_b = { + .type = NGENE_SIDEWINDER, + .name = "S2 V2", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, + NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, + .fe_config = {&fe_s2b_0, &fe_s2b_1}, + .lnb = {0x0b, 0x08}, + .tsf = {3, 3}, + .fw_version = 17, +}; + +/****************************************************************************/ + +static struct xc3028_config tuner_viper_0 = { + .adr = 0x61, + .reset = viper_reset_xc +}; + +static struct xc3028_config tuner_viper_1 = { + .adr = 0x64, + .reset = viper_reset_xc +}; + +static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; + +static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; + +static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; + +static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; + +static struct ngene_info ngene_info_viper_v1 = { + .type = NGENE_VIPER, + .name = "Micronas MicViper Dual ATSC DRXH", + .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_AIN, NGENE_IO_AIN}, + .demod_attach = {demod_attach_drxh, demod_attach_drxh}, + .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, + .tuner_config = {&tuner_viper_0, &tuner_viper_1}, + .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, + .avf = {0x43, 0x47}, + .msp = {0x40, 0x42}, + .exp = 0x20, + .exp_init = 0xf5, + .gate_ctrl = viper_gate_ctrl, + .switch_ctrl = viper_switch_ctrl, + .tsf = {2, 2}, +}; + +static struct ngene_info ngene_info_viper_v2 = { + .type = NGENE_VIPER, + .name = "Micronas MicViper Dual ATSC DRXL", + .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_AIN, NGENE_IO_AIN}, + .demod_attach = {demod_attach_drxh, demod_attach_drxh}, + .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, + .tuner_config = {&tuner_viper_0, &tuner_viper_1}, + .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, + .avf = {0x43, 0x47}, + .msp = {0x40, 0x42}, + .exp = 0x38, + .exp_init = 0xf5, + .gate_ctrl = viper_gate_ctrl, + .switch_ctrl = viper_switch_ctrl, + .tsf = {2, 2}, +}; + +/****************************************************************************/ + +static struct ngene_info ngene_info_vbox_v1 = { + .type = NGENE_VBOX_V1, + .name = "VBox Cat's Eye 164E", + .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_AIN, NGENE_IO_AIN}, + .demod_attach = {demod_attach_drxh, demod_attach_drxh}, + .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, + .tuner_config = {&tuner_viper_0, &tuner_viper_1}, + .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, + .avf = {0x43, 0x47}, + .msp = {0x40, 0x42}, + .exp = 0x20, + .exp_init = 0xf5, + .gate_ctrl = viper_gate_ctrl, + .switch_ctrl = viper_switch_ctrl, + .tsf = {2, 2}, +}; + +/****************************************************************************/ + +static struct ngene_info ngene_info_vbox_v2 = { + .type = NGENE_VBOX_V2, + .name = "VBox Cat's Eye 164E", + .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_TSIN | NGENE_IO_TV, + NGENE_IO_AIN, NGENE_IO_AIN}, + .demod_attach = {demod_attach_drxh, demod_attach_drxh}, + .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, + .tuner_config = {&tuner_viper_0, &tuner_viper_1}, + .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, + .avf = {0x43, 0x47}, + .msp = {0x40, 0x42}, + .exp = 0x20, + .exp_init = 0xf5, + .gate_ctrl = viper_gate_ctrl, + .switch_ctrl = viper_switch_ctrl2, + .tsf = {2, 2}, +}; + +/****************************************************************************/ + +static struct ngene_info ngene_info_racer = { + .type = NGENE_RACER, + .name = "Micronas MicRacer HDTV Decoder Card", + .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, + NGENE_IO_AIN, NGENE_IO_NONE, + NGENE_IO_TSOUT}, + .i2s = {0, 0, 1, 0}, + .fw_version = 17, +}; + + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +#define NGENE_ID(_subvend, _subdev, _driverdata) { \ + .vendor = NGENE_VID, .device = NGENE_PID, \ + .subvendor = _subvend, .subdevice = _subdev, \ + .driver_data = (unsigned long) &_driverdata } + +/****************************************************************************/ + +static const struct pci_device_id ngene_id_tbl[] __devinitdata = { + NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), + NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), + NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), + NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), + NGENE_ID(0x153b, 0x1167, ngene_info_terratec), + NGENE_ID(0x18c3, 0x0030, ngene_info_python), + NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), + NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), + NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), + NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), + NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), + NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), + NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), + NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), + NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), + {0} +}; + +/****************************************************************************/ +/* Init/Exit ****************************************************************/ +/****************************************************************************/ + +static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, + enum pci_channel_state state) +{ + printk(KERN_ERR DEVICE_NAME ": PCI error\n"); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + if (state == pci_channel_io_frozen) + return PCI_ERS_RESULT_NEED_RESET; + return PCI_ERS_RESULT_CAN_RECOVER; +} + +static pci_ers_result_t ngene_link_reset(struct pci_dev *dev) +{ + printk(KERN_INFO DEVICE_NAME ": link reset\n"); + return 0; +} + +static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) +{ + printk(KERN_INFO DEVICE_NAME ": slot reset\n"); + return 0; +} + +static void ngene_resume(struct pci_dev *dev) +{ + printk(KERN_INFO DEVICE_NAME ": resume\n"); +} + +static struct pci_error_handlers ngene_errors = { + .error_detected = ngene_error_detected, + .link_reset = ngene_link_reset, + .slot_reset = ngene_slot_reset, + .resume = ngene_resume, +}; + +static struct pci_driver ngene_pci_driver = { + .name = "ngene", + .id_table = ngene_id_tbl, + .probe = ngene_probe, + .remove = ngene_remove, + .err_handler = &ngene_errors, +}; + +static __init int module_init_ngene(void) +{ + printk(KERN_INFO + "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n"); + return pci_register_driver(&ngene_pci_driver); +} + +static __exit void module_exit_ngene(void) +{ + pci_unregister_driver(&ngene_pci_driver); +} + +module_init(module_init_ngene); +module_exit(module_exit_ngene); + +MODULE_DESCRIPTION("nGene"); +MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/ngene/ngene-ioctls.h b/drivers/media/dvb/ngene/ngene-ioctls.h new file mode 100644 index 00000000000..4aa2f64a531 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-ioctls.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2006-2007 Micronas + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _NGENE_IOCTLS_H_ +#define _NGENE_IOCTLS_H_ + +#include +#include + +#define NGENE_MAGIC 'n' + +typedef struct { + unsigned char I2CAddress; + unsigned char OutLength; /* bytes to write first */ + unsigned char InLength; /* bytes to read */ + unsigned char OutData[256]; /* output data */ + unsigned char InData[256]; /* input data */ +} MIC_I2C_READ, *PMIC_I2C_READ; + +#define IOCTL_MIC_I2C_READ _IOWR(NGENE_MAGIC, 0x00, MIC_I2C_READ) + + +typedef struct { + unsigned char I2CAddress; + unsigned char Length; + unsigned char Data[250]; +} MIC_I2C_WRITE, *PMIC_I2C_WRITE; + +typedef struct { + unsigned char Length; + unsigned char Data[250]; +} MIC_I2C_CONTINUE_WRITE, *PMIC_I2C_CONTINUE_WRITE; + +#define IOCTL_MIC_I2C_WRITE _IOW(NGENE_MAGIC, 0x01, \ + MIC_I2C_WRITE) +#define IOCTL_MIC_I2C_WRITE_NOSTOP _IOW(NGENE_MAGIC, 0x0c, \ + MIC_I2C_WRITE) +#define IOCTL_MIC_I2C_CONTINUE_WRITE_NOSTOP _IOW(NGENE_MAGIC, 0x0d, \ + MIC_I2C_CONTINUE_WRITE) +#define IOCTL_MIC_I2C_CONTINUE_WRITE _IOW(NGENE_MAGIC, 0x0e, \ + MIC_I2C_CONTINUE_WRITE) + +typedef struct { + unsigned char ModeSelect; /* see bellow */ + unsigned char OutLength; /* bytes to write first */ + unsigned char InLength; /* bytes to read */ + unsigned char OutData[250]; /* output data */ +} MIC_SPI_READ, *PMIC_SPI_READ; + +#define IOCTL_MIC_SPI_READ _IOWR(NGENE_MAGIC, 0x02, MIC_SPI_READ) + +typedef struct { + unsigned char ModeSelect; /* see below */ + unsigned char Length; + unsigned char Data[250]; +} MIC_SPI_WRITE, *PMIC_SPI_WRITE; + +#define IOCTL_MIC_SPI_WRITE _IOW(NGENE_MAGIC, 0x03, MIC_SPI_READ) + +#define IOCTL_MIC_DOWNLOAD_FIRMWARE _IOW(NGENE_MAGIC, 0x06, unsigned char) + +#define IOCTL_MIC_NO_OP _IO(NGENE_MAGIC, 0x18) + +#define IOCTL_MIC_TUN_RDY _IO(NGENE_MAGIC, 0x07) +#define IOCTL_MIC_DEC_SRATE _IOW(NGENE_MAGIC, 0x0a, int) +#define IOCTL_MIC_DEC_RDY _IO(NGENE_MAGIC, 0x09) +#define IOCTL_MIC_DEC_FREESYNC _IOW(NGENE_MAGIC, 0x08, int) +#define IOCTL_MIC_TUN_DETECT _IOWR(NGENE_MAGIC, 0x0b, int) + +typedef struct { + unsigned char Stream; /* < UVI1, UVI2, or TVOUT */ + unsigned char Control; + unsigned char Mode; + unsigned short nLines; + unsigned short nBytesPerLine; + unsigned short nVBILines; + unsigned short nBytesPerVBILine; +} MIC_STREAM_CONTROL, *PMIC_STREAM_CONTROL; + +enum MIC_STREAM_CONTROL_MODE_BITS { + MSC_MODE_LOOPBACK = 0x80, + MSC_MODE_AVLOOP = 0x40, + MSC_MODE_AUDIO_SPDIF = 0x20, + MSC_MODE_AVSYNC = 0x10, + MSC_MODE_TRANSPORT_STREAM = 0x08, + MSC_MODE_AUDIO_CAPTURE = 0x04, + MSC_MODE_VBI_CAPTURE = 0x02, + MSC_MODE_VIDEO_CAPTURE = 0x01 +}; + +#define IOCTL_MIC_STREAM_CONTROL _IOW(NGENE_MAGIC, 0x22, MIC_STREAM_CONTROL) + +typedef struct { + unsigned char Stream; /* < UVI1, UVI2 */ + unsigned int Rate; /* < Rate in 100nsec to release the buffers + to the stream filters */ +} MIC_SIMULATE_CONTROL, *PMIC_SIMULATE_CONTROL; + +#define IOCTL_MIC_SIMULATE_CONTROL _IOW(NGENE_MAGIC, 0x23, \ + MIC_SIMULATE_CONTROL) + +/* + * IOCTL definitions for the test driver + * + * NOTE: the test driver also supports following IOCTL defined above: + * IOCTL_MIC_NO_OP: + * IOCTL_MIC_RECEIVE_BUFFER: + * IOCTL_MIC_STREAM_CONTROL: + * IOCTL_MIC_I2C_READ: + * IOCTL_MIC_I2C_WRITE: + * + * + * VI2C access to NGene memory (read) + * + * GETMEM in : ULONG start offset + * out : read data (length defined by size of output buffer) + * SETMEM in : ULONG start offset followed by data to be written + * (length defined by size of input buffer) + */ + +typedef struct { + __u32 Start; + __u32 Length; + __u8 *Data; +} MIC_MEM; + +#define IOCTL_MIC_TEST_GETMEM _IOWR(NGENE_MAGIC, 0x90, MIC_MEM) +#define IOCTL_MIC_TEST_SETMEM _IOW(NGENE_MAGIC, 0x91, MIC_MEM) + +typedef struct { + __u8 Address; + __u8 Data; +} MIC_IMEM; + +#define IOCTL_MIC_SFR_READ _IOWR(NGENE_MAGIC, 0xa2, MIC_IMEM) +#define IOCTL_MIC_SFR_WRITE _IOWR(NGENE_MAGIC, 0xa3, MIC_IMEM) + +#define IOCTL_MIC_IRAM_READ _IOWR(NGENE_MAGIC, 0xa4, MIC_IMEM) +#define IOCTL_MIC_IRAM_WRITE _IOWR(NGENE_MAGIC, 0xa5, MIC_IMEM) + +/* + * Set Ngene gpio bit + */ +typedef struct { + unsigned char Select; + unsigned char Level; +} MIC_SET_GPIO_PIN, *PMIC_SET_GPIO_PIN; + +#define IOCTL_MIC_SET_GPIO_PIN _IOWR(NGENE_MAGIC, 0xa6, MIC_SET_GPIO_PIN) + +/* + * Uart ioctls: + * These are implemented in the test driver. + * + * Enable UART + * + * In: 1 byte containing baud rate: 0 = 19200, 1 = 9600, 2 = 4800, 3 = 2400 + * Out: nothing + */ +#define IOCTL_MIC_UART_ENABLE _IOW(NGENE_MAGIC, 0xa9, unsigned char) + +/* + * Enable UART + * + * In: nothing + * Out: nothing + */ +#define IOCTL_MIC_UART_DISABLE _IO(NGENE_MAGIC, 0xAA) + +/* + * Write UART + * + * In: data to write + * Out: nothing + * Note: Call returns immediatly, data are send out asynchrounsly + */ +#define IOCTL_MIC_UART_WRITE _IOW(NGENE_MAGIC, 0xAB, unsigned char) + +/* + * Read UART + * + * In: nothing + * Out: Data read (since last call) + * Note: Call returns immediatly + */ +#define IOCTL_MIC_UART_READ _IOR(NGENE_MAGIC, 0xAC, unsigned char) + +/* + * UART Status + * + * In: nothing + * Out: Byte 0 : Transmitter busy, + * Byte 1 : Nbr of characters available for read. + * Note: Call returns immediatly + */ +#define IOCTL_MIC_UART_STATUS _IOR(NGENE_MAGIC, 0xAD, unsigned char) + +#endif diff --git a/drivers/media/dvb/ngene/ngene-snd.c b/drivers/media/dvb/ngene/ngene-snd.c new file mode 100644 index 00000000000..1ca343236ff --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-snd.c @@ -0,0 +1,421 @@ +/* + * ngene_snd.c: nGene PCIe bridge driver ALSA support + * + * Copyright (C) 2005-2007 Micronas + * + * Based on the initial ALSA support port by Thomas Eschbach. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include + +#include "ngene.h" +#include "ngene-ioctls.h" + +static int sound_dev; + +/* sound module parameters (see "Module Parameters") */ +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; + +/****************************************************************************/ +/* PCM Sound Funktions ******************************************************/ +/****************************************************************************/ + +static struct snd_pcm_hardware snd_mychip_capture_hw = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 + | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 + | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), + .rate_min = 11025, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 16384, + .period_bytes_min = 8192, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 2, +}; + +/* open callback */ +static int snd_mychip_capture_open(struct snd_pcm_substream *substream) +{ + + struct mychip *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw = snd_mychip_capture_hw; + chip->substream = substream; + return 0; +} + +/* close callback */ +static int snd_mychip_capture_close(struct snd_pcm_substream *substream) +{ + struct mychip *chip = snd_pcm_substream_chip(substream); + chip->substream = NULL; + return 0; + +} + +/* hw_params callback */ +static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct mychip *chip = snd_pcm_substream_chip(substream); + struct ngene_channel *chan = chip->chan; + if (chan->soundbuffisallocated == 0) { + chan->soundbuffisallocated = 1; + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + } + return 0; +} + +/* hw_free callback */ +static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct mychip *chip = snd_pcm_substream_chip(substream); + struct ngene_channel *chan = chip->chan; + int retval = 0; + if (chan->soundbuffisallocated == 1) { + chan->soundbuffisallocated = 0; + retval = snd_pcm_lib_free_pages(substream); + } + return retval; +} + +/* prepare callback */ +static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream) +{ + + struct mychip *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct ngene_channel *chan = chip->chan; + struct ngene_channel *ch = &chan->dev->channel[chan->number - 2]; + struct i2c_adapter *adap = &ch->i2c_adapter; + + if (ch->soundstreamon == 1) + ;/*ngene_command_stream_control_sound(chan->dev, chan->number, + 0x00, 0x00);*/ + i2c_clients_command(adap, IOCTL_MIC_DEC_SRATE, &(runtime->rate)); + mdelay(80); + if (ch->soundstreamon == 1) + ;/*ngene_command_stream_control_sound(chan->dev, chan->number, + 0x80, 0x04);*/ + + return 0; +} + +/* trigger callback */ +static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct mychip *chip = snd_pcm_substream_chip(substream); + struct ngene_channel *chan = chip->chan; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* do something to start the PCM engine */ + chan->sndbuffflag = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + /* do something to stop the PCM engine */ + chip->substream = NULL; + chan->sndbuffflag = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +/* pointer callback */ +static snd_pcm_uframes_t +snd_mychip_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct mychip *chip = snd_pcm_substream_chip(substream); + struct ngene_channel *chan = chip->chan; + unsigned int current_ptr; + + if (chan->sndbuffflag == 0) { + current_ptr = (unsigned int) + bytes_to_frames(substream->runtime, 0); + } else { + current_ptr = (unsigned int) + bytes_to_frames(substream->runtime, 8192); + } + return current_ptr; +} + +/*copy sound buffer to pcm middel layer*/ +static int snd_capture_copy(struct snd_pcm_substream *substream, int channel, + snd_pcm_uframes_t pos, void *dst, + snd_pcm_uframes_t count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct mychip *chip = snd_pcm_substream_chip(substream); + struct ngene_channel *chan = chip->chan; + + memcpy(dst, chan->soundbuffer, frames_to_bytes(runtime, count)); + return 0; +} + +static int snd_pcm_capture_silence(struct snd_pcm_substream *substream, + int channel, + snd_pcm_uframes_t pos, + snd_pcm_uframes_t count) +{ + /* + struct snd_pcm_runtime *runtime = substream->runtime; + struct mychip *chip = snd_pcm_substream_chip(substream); + struct ngene_channel *chan = chip->chan; + */ + return 0; +} + +/* operators */ +static struct snd_pcm_ops snd_mychip_capture_ops = { + .open = snd_mychip_capture_open, + .close = snd_mychip_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_mychip_pcm_hw_params, + .hw_free = snd_mychip_pcm_hw_free, + .prepare = snd_mychip_pcm_prepare, + .trigger = snd_mychip_pcm_trigger, + .pointer = snd_mychip_pcm_pointer, + .copy = snd_capture_copy, + .silence = snd_pcm_capture_silence, +}; + +static void mychip_pcm_free(struct snd_pcm *pcm) +{ + pcm->private_data = NULL; +} + +/* create a pcm device */ +static int snd_mychip_new_pcm(struct mychip *chip, struct ngene_channel *chan) +{ + struct snd_pcm *pcm; + int err; + char gro[10]; + sprintf(gro, "PCM%d", chan->number); + + err = snd_pcm_new(chip->card, gro, 0, 0, 1, &pcm); + if (err < 0) + return err; + + pcm->private_data = chip; + pcm->private_free = mychip_pcm_free; + + sprintf(pcm->name, "MyPCM_%d", chan->number); + + chip->pcm = pcm; + /* set operators */ + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops); + /* pre-allocation of buffers */ + + err = snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data( + GFP_KERNEL), + 0, 16 * 1024); + + return 0; +} + +#define ngene_VOLUME(xname, xindex, addr) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ + .info = snd_volume_info, \ + .get = snd_volume_get, .put = snd_volume_put, \ + .private_value = addr } + +static int snd_volume_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *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_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct mychip *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_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct mychip *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 ngene_CAPSRC(xname, xindex, addr) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ + .info = snd_capsrc_info, \ + .get = snd_capsrc_get, .put = snd_capsrc_put, \ + .private_value = addr } + +static int snd_capsrc_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *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_capsrc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct mychip *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_capsrc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct mychip *chip = snd_kcontrol_chip(kcontrol); + int change, addr = kcontrol->private_value; + int left, right; + + 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; + + spin_unlock_irq(&chip->mixer_lock); + + if (change) + printk(KERN_INFO "snd_capsrc_put change\n"); + return 0; +} + +static struct snd_kcontrol_new snd_controls[] = { + ngene_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), + ngene_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), +}; + +static int snd_card_new_mixer(struct mychip *chip) +{ + struct snd_card *card = chip->card; + unsigned int idx; + int err; + + strcpy(card->mixername, "NgeneMixer"); + + for (idx = 0; idx < ARRAY_SIZE(snd_controls); idx++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_controls[idx], chip)); + if (err < 0) + return err; + } + return 0; +} + +int ngene_snd_init(struct ngene_channel *chan) +{ + struct snd_card *card; + struct mychip *chip; + int err; + + if (sound_dev >= SNDRV_CARDS) + return -ENODEV; + if (!enable[sound_dev]) { + sound_dev++; + return -ENOENT; + } + card = snd_card_new(index[sound_dev], id[sound_dev], + THIS_MODULE, sizeof(struct mychip)); + if (card == NULL) + return -ENOMEM; + + chip = card->private_data; + chip->card = card; + chip->irq = -1; + + sprintf(card->shortname, "MyChip%d%d", chan->dev->nr, chan->number); + sprintf(card->shortname, "Myown%d%d", chan->dev->nr, chan->number); + sprintf(card->longname, "My first Own Chip on Card Nr.%d is %d", + chan->dev->nr, chan->number); + + spin_lock_init(&chip->lock); + spin_lock_init(&chip->mixer_lock); + + snd_card_new_mixer(chip); + + snd_mychip_new_pcm(chip, chan); + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return err; + } + chan->soundcard = card; + chan->mychip = chip; + chip->chan = chan; + sound_dev++; + return 0; +} + +int ngene_snd_exit(struct ngene_channel *chan) +{ + snd_card_free(chan->soundcard); + return 0; +} diff --git a/drivers/media/dvb/ngene/ngene-v4l2.c b/drivers/media/dvb/ngene/ngene-v4l2.c new file mode 100644 index 00000000000..c0a9147c44a --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-v4l2.c @@ -0,0 +1,1937 @@ +/* + * ngene_v4l2.c: nGene PCIe bridge driver V4L2 support + * + * Copyright (C) 2005-2007 Micronas + * + * Based on the initial V4L2 support port by Thomas Eschbach. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ngene.h" +#include "ngene-ioctls.h" + +/****************************************************************************/ + +static unsigned int gbuffers = 8; +static unsigned int gbufsize = 0x208000; + +enum km_type ngene_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +#define V4L2_STD_NTSC_M_KOREA ((v4l2_std_id)0x00004000) +#define V4L2_STD_SECAM_L1 ((v4l2_std_id)0x00008000) + +static inline void *my_video_get_drvdata(struct video_device *vd) +{ + return dev_get_drvdata(vd->dev); +} + +static inline void my_video_set_drvdata(struct video_device *vd, void *d) +{ + dev_set_drvdata(vd->dev, d); +} + +static struct ngene_tvnorm ngene_tvnorms_hd[] = { + { + .v4l2_id = V4L2_STD_PAL_BG, + .name = "1080i50", + .swidth = 1920, + .sheight = 1080, + .tuner_norm = 1, + .soundstd = 1, + } +}; + +static struct ngene_tvnorm ngene_tvnorms_sd[] = { + /* PAL-BDGHI */ + /* max. active video is actually 922, but 924 is divisible by 4 & 3!*/ + /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ + { + .v4l2_id = V4L2_STD_PAL_BG, + .name = "PAL-BG", + .swidth = 720, + .sheight = 576, + .tuner_norm = 1, + .soundstd = 1, + }, { + .v4l2_id = V4L2_STD_PAL_DK, + .name = "PAL-DK", + .swidth = 720, + .sheight = 576, + .tuner_norm = 2, + .soundstd = 2, + }, { + .v4l2_id = V4L2_STD_PAL_H, + .name = "PAL-H", + .swidth = 720, + .sheight = 576, + .tuner_norm = 0, + .soundstd = 1, + }, { + .v4l2_id = V4L2_STD_PAL_I, + .name = "PAL-I", + .swidth = 720, + .sheight = 576, + .tuner_norm = 4, + .soundstd = 4, + }, { + .v4l2_id = V4L2_STD_PAL_M, + .name = "PAL_M", + .swidth = 720, + .sheight = 5760, + .tuner_norm = 7, + .soundstd = 5, + }, { + .v4l2_id = V4L2_STD_NTSC_M, + .name = "NTSC_M", + .swidth = 720, + .sheight = 480, + .tuner_norm = 7, + .soundstd = 5, + }, { + .v4l2_id = V4L2_STD_NTSC_M_JP, + .name = "NTSC_M_JP", + .swidth = 720, + .sheight = 480, + .tuner_norm = 7, + .soundstd = 6, + }, { + .v4l2_id = V4L2_STD_PAL_N, + .name = "PAL-N", + .swidth = 720, + .sheight = 576, + .tuner_norm = 7, + .soundstd = 5, + }, { + .v4l2_id = V4L2_STD_SECAM_B, + .name = "SECAM_B", + .swidth = 720, + .sheight = 576, + .tuner_norm = 1, + .soundstd = 1, + }, { + .v4l2_id = V4L2_STD_SECAM_D, + .name = "SECAM_D", + .swidth = 720, + .sheight = 576, + .tuner_norm = 2, + .soundstd = 2, + }, { + .v4l2_id = V4L2_STD_SECAM_G, + .name = "SECAM_G", + .swidth = 720, + .sheight = 576, + .tuner_norm = 3, + .soundstd = 1, + }, { + .v4l2_id = V4L2_STD_SECAM_H, + .name = "SECAM_H", + .swidth = 720, + .sheight = 576, + .tuner_norm = 3, + .soundstd = 1, + }, { + .v4l2_id = V4L2_STD_SECAM_K, + .name = "SECAM_K", + .swidth = 720, + .sheight = 576, + .tuner_norm = 2, + .soundstd = 2, + }, { + .v4l2_id = V4L2_STD_SECAM_K1, + .name = "SECAM_K1", + .swidth = 720, + .sheight = 576, + .tuner_norm = 2, + .soundstd = 2, + }, { + .v4l2_id = V4L2_STD_SECAM_L, + .name = "SECAM_L", + .swidth = 720, + .sheight = 576, + .tuner_norm = 5, + .soundstd = 3, + }, { + .v4l2_id = V4L2_STD_NTSC_M_KOREA, + .name = "NTSC_M_KOREA", + .swidth = 720, + .sheight = 480, + .tuner_norm = 7, + .soundstd = 7, + }, { + .v4l2_id = V4L2_STD_SECAM_L1, + .name = "SECAM_L1", + .swidth = 720, + .sheight = 576, + .tuner_norm = 6, + .soundstd = 3, + } + +}; + +static const int NGENE_TVNORMS = ARRAY_SIZE(ngene_tvnorms_sd); + +static u8 BlackLine[1440] = { + /* 0x80, */ 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0x80, +}; + +#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 1) + +static const struct v4l2_queryctrl no_ctl = { + .name = "no_ctl", + .flags = V4L2_CTRL_FLAG_DISABLED, +}; + +static const struct v4l2_queryctrl ngene_ctls[] = { + /* --- video --- */ + { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = -127, + .maximum = 127, + .step = 1, + .default_value = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 63, + .step = 1, + .default_value = 30, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 4094, + .step = 1, + .default_value = 2000, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = -2047, + .maximum = 2047, + .step = 1, + .default_value = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + /* --- audio --- */ + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, { + .id = V4L2_CID_PRIVATE_SHARPNESS, + .name = "sharpness", + .minimum = 0, + .maximum = 100, + .step = 1, + .default_value = 50, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + +}; + +static const int NGENE_CTLS = ARRAY_SIZE(ngene_ctls); + +static const struct ngene_format ngene_formats[] = { + { + .name = "4:2:2, packed, YUYV", + .palette = -1, + .fourcc = V4L2_PIX_FMT_YUYV, + .format = V4L2_PIX_FMT_YUYV, + .palette = VIDEO_PALETTE_YUYV, + .depth = 16, + .flags = 0x02,/* FORMAT_FLAGS_PACKED, */ + } +}; + +static const unsigned int NGENE_FORMATS = ARRAY_SIZE(ngene_formats); + +/****************************************************************************/ + +static struct videobuf_queue *ngene_queue(struct ngene_vopen *vopen) +{ + struct videobuf_queue *q = NULL; + + switch (vopen->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + q = &vopen->vbuf_q; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + q = &vopen->vbi; + break; + default: + break; + } + return q; +} + +static int ngene_resource(struct ngene_vopen *vopen) +{ + int res = 0; + + switch (vopen->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + res = RESOURCE_VIDEO; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + res = RESOURCE_VBI; + break; + default: + break; + } + return res; +} + +static int ngene_try_fmt(struct ngene_vopen *vopen, struct ngene_channel *chan, + struct v4l2_format *f) +{ + switch (f->type) { + + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + { + const struct ngene_format *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; + int maxLinesPerField; + + fmt = ngene_formats; + if (NULL == fmt) + return -EINVAL; + + /* fixup format */ + maxw = chan->tvnorms[chan->tvnorm].swidth; + maxLinesPerField = chan->tvnorms[chan->tvnorm].sheight; + maxh = maxLinesPerField; + field = f->fmt.pix.field; + + if (V4L2_FIELD_ANY == field) + field = (f->fmt.pix.height > maxh / 2) + ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; + + if (V4L2_FIELD_SEQ_BT == field) + field = V4L2_FIELD_SEQ_TB; + + /* update data for the application */ + f->fmt.pix.field = field; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + f->fmt.pix.width &= ~0x03; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; + } + + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return -EINVAL; + + case V4L2_BUF_TYPE_VBI_CAPTURE: + return 0; + + default: + return -EINVAL; + } +} + +/****************************************************************************/ +/* Analog driver stuff ******************************************************/ +/****************************************************************************/ + +static int check_alloc_res(struct ngene_channel *channel, + struct ngene_vopen *vopen, int bit) +{ + if (vopen->resources & bit) + /* have it already allocated */ + return 1; + + /* is it free? */ + down(&channel->reslock); + if (channel->resources & bit) { + /* no, someone else uses it */ + up(&channel->reslock); + return 0; + } + /* it's free, grab it */ + vopen->resources |= bit; + channel->resources |= bit; + up(&channel->reslock); + return 1; +} + +static int check_res(struct ngene_vopen *vopen, int bit) +{ + return vopen->resources & bit; +} + +static int locked_res(struct ngene_channel *chan, int bit) +{ + return chan->resources & bit; +} + +static void free_res(struct ngene_channel *channel, + struct ngene_vopen *vopen, int bits) +{ + down(&channel->reslock); + vopen->resources &= ~bits; + channel->resources &= ~bits; + up(&channel->reslock); +} + +/****************************************************************************/ +/* MISC HELPERS *************************************************************/ +/****************************************************************************/ + +static int ngene_g_fmt(struct ngene_vopen *vopen, struct v4l2_format *f) +{ + if (!vopen->fmt) + vopen->fmt = ngene_formats; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); + f->fmt.pix.width = vopen->width; + f->fmt.pix.height = vopen->height; + f->fmt.pix.field = vopen->vbuf_q.field; + f->fmt.pix.pixelformat = vopen->fmt->fourcc; + f->fmt.pix.bytesperline = (f->fmt.pix.width * 16) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + return 0; + + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + memset(&f->fmt.win, 0, sizeof(struct v4l2_window)); + return 0; + f->fmt.win.w = vopen->ov.w; + f->fmt.win.field = vopen->ov.field; + return 0; + + case V4L2_BUF_TYPE_VBI_CAPTURE: + return -EINVAL; + + default: + return -EINVAL; + } +} + +static int ngene_switch_type(struct ngene_vopen *vopen, enum v4l2_buf_type type) +{ + struct videobuf_queue *q = ngene_queue(vopen); + int res = ngene_resource(vopen); + + if (check_res(vopen, res)) + return -EBUSY; + if (videobuf_queue_is_busy(q)) + return -EBUSY; + vopen->type = type; + return 0; +} + +static int ngene_s_fmt(struct ngene_vopen *vopen, struct ngene_channel *chan, + struct v4l2_format *f) +{ + int retval; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + { + const struct ngene_format *fmt; + retval = ngene_try_fmt(vopen, chan, f); + if (0 != retval) + return retval; + + retval = ngene_switch_type(vopen, f->type); + if (0 != retval) + return retval; + fmt = ngene_formats; + + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) + return -EINVAL; + /* update our state informations */ + mutex_lock(&vopen->vbuf_q.lock); + vopen->fmt = fmt; + vopen->vbuf_q.field = f->fmt.pix.field; + vopen->vbuf_q.last = V4L2_FIELD_INTERLACED; + vopen->width = f->fmt.pix.width; + vopen->height = f->fmt.pix.height; + chan->init.fmt = fmt; + chan->init.width = f->fmt.pix.width; + chan->init.height = f->fmt.pix.height; + mutex_unlock(&vopen->vbuf_q.lock); + + return 0; + } + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return -EINVAL; + case V4L2_BUF_TYPE_VBI_CAPTURE: + return -EINVAL; + default: + return -EINVAL; + } +} + +/****************************************************************************/ +/* SG support ***************************************************************/ +/****************************************************************************/ + +static inline enum km_type ngene_kmap_type(int out) +{ + return ngene_km_types[(in_softirq() ? 2 : 0) + out]; +} + +static inline void *ngene_kmap(struct page *page, int out) +{ + return kmap_atomic(page, ngene_kmap_type(out)); +} + +static inline void ngene_kunmap(void *vaddr, int out) +{ + kunmap_atomic(vaddr, ngene_kmap_type(out)); +} + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & + (PAGE_CACHE_SIZE - 1)) + nbytes <= PAGE_CACHE_SIZE) + return walk->data; + else + return walk->data; +} + +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + walk->page = sg->page; + walk->len_this_segment = sg->length; + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = ngene_kmap(walk->page, out) + walk->offset; +} + +static void scatterwalk_pagedone(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virtual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } else { + scatterwalk_start(walk, sg_next(walk->sg)); + } + } +} + +void scatterwalk_done(struct scatter_walk *walk, int out, int more) +{ + ngene_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatterwalk_pagedone(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +int scatterwalk_copychunks(struct scatter_walk *walk, size_t nbytes, int out) +{ + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} + +static void *vid_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) +{ + struct ngene_channel *chan = priv; + struct ngene_buffer *item; + int wstrich, hstrich; + u8 *odd, *even; + u32 bpl = chan->tvnorms[chan->tvnorm].swidth * 2; + + struct scatter_walk walk_out; + const unsigned int bsize = PAGE_SIZE; + unsigned int nbytes; + int rest_of_buffer, ah, rwstrich; + + spin_lock(&chan->s_lock); + + if (list_empty(&chan->capture)) { + chan->evenbuffer = NULL; + goto out; + } + item = list_entry(chan->capture.next, struct ngene_buffer, vb.queue); + + if (chan->tvnorms[chan->tvnorm].sheight == 1080) + buf += 3840; + + odd = buf; + + hstrich = item->vb.height; + if (hstrich > chan->tvnorms[chan->tvnorm].sheight) + hstrich = chan->tvnorms[chan->tvnorm].sheight; + + wstrich = item->vb.width; + if (wstrich > chan->tvnorms[chan->tvnorm].swidth) + wstrich = chan->tvnorms[chan->tvnorm].swidth; + wstrich <<= 1; + + if (flags & BEF_EVEN_FIELD) { + chan->evenbuffer = buf; + if (chan->lastbufferflag) { + chan->lastbufferflag = 0; + if (chan->tvnorms[chan->tvnorm].sheight == 576) { + memcpy(buf + 413280, BlackLine, 1440); + memcpy(buf + 411840, BlackLine, 1440); + } + goto out; + } + } + chan->lastbufferflag = 1; + if (chan->evenbuffer) + even = chan->evenbuffer; + else + even = odd; + if (chan->tvnorms[chan->tvnorm].sheight == 576) { + memcpy(odd + 413280, BlackLine, 1440); + memcpy(odd + 411840, BlackLine, 1440); + } + nbytes = item->vb.dma.sglen * PAGE_SIZE; + scatterwalk_start(&walk_out, item->vb.dma.sglist); + ah = 0; + rwstrich = wstrich; + do { + u8 *dst_p; + + rest_of_buffer = bsize; + scatterwalk_map(&walk_out, 1); + dst_p = scatterwalk_whichbuf(&walk_out, bsize); + nbytes -= bsize; + scatterwalk_copychunks(&walk_out, bsize, 1); + + while (rest_of_buffer > 0 && ah < hstrich) { + if (rest_of_buffer >= rwstrich) { + if (ah % 2 == 0) { + memcpy(walk_out.data + + (bsize - rest_of_buffer), + odd, rwstrich); + odd += bpl - (wstrich - rwstrich); + } else { + memcpy(walk_out.data + + (bsize - rest_of_buffer), + even, rwstrich); + even += bpl - (wstrich - rwstrich); + } + rest_of_buffer -= rwstrich; + ah++; + rwstrich = wstrich; + } else { + if (ah % 2 == 0) { + memcpy(walk_out.data + + (bsize - rest_of_buffer), + odd, rest_of_buffer); + odd += rest_of_buffer; + } else { + memcpy(walk_out.data + + (bsize - rest_of_buffer), + even, rest_of_buffer); + even += rest_of_buffer; + } + rwstrich -= rest_of_buffer; + rest_of_buffer = 0; + } + } + scatterwalk_done(&walk_out, 1, nbytes); + } while (nbytes && ah < hstrich); + + { + struct timeval ts; + do_gettimeofday(&ts); + list_del(&item->vb.queue); + item->vb.state = STATE_DONE; + item->vb.ts = ts; + wake_up(&item->vb.done); + chan->evenbuffer = NULL; + } + +out: + spin_unlock(&chan->s_lock); + return 0; +} + +static void *snd_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) +{ + struct ngene_channel *chan = priv; + struct mychip *mychip = chan->mychip; + + if (chan->audiomute == 0) + memcpy(chan->soundbuffer, (u8 *) buf, MAX_AUDIO_BUFFER_SIZE); + else + memset(chan->soundbuffer, 0, MAX_AUDIO_BUFFER_SIZE); + + if (mychip->substream != NULL) { + if (chan->sndbuffflag == 0) + chan->sndbuffflag = 1; + else + chan->sndbuffflag = 0; + spin_unlock(&mychip->lock); + snd_pcm_period_elapsed(mychip->substream); + spin_lock(&mychip->lock); + } + return 0; +} + +static void set_analog_transfer(struct ngene_channel *chan, int state) +{ + struct ngene_channel *ch; + u8 flags = 0; + + ch = &chan->dev->channel[chan->number + 2]; + /* printk(KERN_INFO "set_analog_transfer %d\n", state); */ + + if (1) { /* chan->tun_dec_rdy == 1){ */ + if (state) { + + chan->Capture1Length = + chan->tvnorms[chan->tvnorm].swidth * + chan->tvnorms[chan->tvnorm].sheight; + if (chan->tvnorms[chan->tvnorm].sheight == 576) + chan->nLines = 287; + else if (chan->tvnorms[chan->tvnorm].sheight == 1080) + chan->nLines = 541; + else + chan->nLines = + chan->tvnorms[chan->tvnorm].sheight / 2; + chan->nBytesPerLine = + chan->tvnorms[chan->tvnorm].swidth * 2; + if (chan->dev->card_info->io_type[chan->number] == + NGENE_IO_HDTV) { + chan->itumode = 2; + flags = SFLAG_ORDER_LUMA_CHROMA; + } else { + chan->itumode = 0; + flags = SFLAG_ORDER_LUMA_CHROMA; + } + chan->pBufferExchange = vid_exchange; + ngene_command_stream_control(chan->dev, chan->number, + 0x80, + SMODE_VIDEO_CAPTURE, + flags); + + ch->Capture1Length = MAX_AUDIO_BUFFER_SIZE; + ch->pBufferExchange = snd_exchange; + ngene_command_stream_control(ch->dev, ch->number, + 0x80, + SMODE_AUDIO_CAPTURE, 0); + ch->soundstreamon = 1; + } else { + ngene_command_stream_control(chan->dev, chan->number, + 0, 0, 0); + ngene_command_stream_control(ch->dev, ch->number, + 0, 0, 0); + ch->soundstreamon = 0; + } + } +} + +static int ngene_analog_start_feed(struct ngene_channel *chan) +{ + int freerunmode = 1; + struct i2c_adapter *adapter = &chan->i2c_adapter; + + if (chan->users == 0 && chan->number < 2) { + chan->evenbuffer = NULL; + chan->users = 1; + i2c_clients_command(adapter, IOCTL_MIC_DEC_FREESYNC, + &freerunmode); + msleep(25); + set_analog_transfer(chan, 1); + msleep(25); + freerunmode = 0; + i2c_clients_command(adapter, IOCTL_MIC_DEC_FREESYNC, + &freerunmode); + } + return chan->users; +} + +static int ngene_analog_stop_feed(struct ngene_channel *chan) +{ + int freerunmode = 1; + struct i2c_adapter *adapter = &chan->i2c_adapter; + if (chan->users == 1 && chan->number < 2) { + chan->users = 0; + i2c_clients_command(adapter, + IOCTL_MIC_DEC_FREESYNC, &freerunmode); + msleep(20); + set_analog_transfer(chan, 0); + } + return 0; +} + +/****************************************************************************/ +/* V4L2 API interface *******************************************************/ +/****************************************************************************/ + +void ngene_dma_free(struct videobuf_queue *q, + struct ngene_channel *chan, struct ngene_buffer *buf) +{ + videobuf_waiton(&buf->vb, 0, 0); + videobuf_dma_unmap(q, &buf->vb.dma); + videobuf_dma_free(&buf->vb.dma); + buf->vb.state = STATE_NEEDS_INIT; +} + +static int ngene_prepare_buffer(struct videobuf_queue *q, + struct ngene_channel *chan, + struct ngene_buffer *buf, + const struct ngene_format *fmt, + unsigned int width, unsigned int height, + enum v4l2_field field) +{ + int rc = 0; + /* check settings */ + if (NULL == fmt) + return -EINVAL; + + if (width < 48 || height < 32) + return -EINVAL; + + buf->vb.size = (width * height * 16 /* fmt->depth */) >> 3; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + /* alloc + fill struct ngene_buffer (if changed) */ + if (buf->vb.width != width || buf->vb.height != height || + buf->vb.field != field || buf->fmt != fmt || + buf->tvnorm != chan->tvnorm) { + + buf->vb.width = width; + buf->vb.height = height; + buf->vb.field = field; + buf->tvnorm = chan->tvnorm; + buf->fmt = fmt; + + ngene_dma_free(q, chan, buf); + } + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + if (buf->vb.field == 0) + buf->vb.field = V4L2_FIELD_INTERLACED; + + if (STATE_NEEDS_INIT == buf->vb.state) { + buf->vb.width = width; + buf->vb.height = height; + buf->vb.field = field; + buf->tvnorm = chan->tvnorm; + buf->fmt = fmt; + + rc = videobuf_iolock(q, &buf->vb, &chan->fbuf); + if (0 != rc) + goto fail; + } + if (!buf->vb.dma.bus_addr) + videobuf_dma_sync(q, &buf->vb.dma); + buf->vb.state = STATE_PREPARED; + return 0; + +fail: + ngene_dma_free(q, chan, buf); + return rc; + +} + +static int buffer_setup(struct videobuf_queue *q, + unsigned int *count, unsigned int *size) +{ + struct ngene_vopen *vopen = q->priv_data; + *size = 2 * vopen->width * vopen->height; + if (0 == *count) + *count = gbuffers; + while (*size * *count > gbuffers * gbufsize) + (*count)--; + q->field = V4L2_FIELD_INTERLACED; + q->last = V4L2_FIELD_INTERLACED; + return 0; +} + +static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); + struct ngene_vopen *vopen = q->priv_data; + return ngene_prepare_buffer(q, vopen->ch, buf, vopen->fmt, + vopen->width, vopen->height, field); +} + +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); + struct ngene_vopen *vopen = q->priv_data; + ngene_dma_free(q, vopen->ch, buf); +} + +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); + struct ngene_vopen *vopen = q->priv_data; + struct ngene_channel *chan = vopen->ch; + + buf->vb.state = STATE_QUEUED; + list_add_tail(&buf->vb.queue, &chan->capture); +} + +static struct videobuf_queue_ops ngene_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +int video_open(struct inode *inode, struct file *flip) +{ + struct ngene_vopen *vopen = NULL; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + struct video_device *vd = video_devdata(flip); + struct ngene_channel *chan = my_video_get_drvdata(vd); + + vopen = kmalloc(sizeof(*vopen), GFP_KERNEL); + if (!vopen) + return -ENOMEM; + memset(vopen, 0, sizeof(*vopen)); + flip->private_data = vopen; + v4l2_prio_open(&chan->prio, &vopen->prio); + vopen->ch = chan; + vopen->picxcount = 0; + vopen->type = type; + videobuf_queue_init(&vopen->vbuf_q, &ngene_video_qops, + chan->dev->pci_dev, &chan->s_lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct ngene_buffer), vopen); + + vopen->ovfmt = ngene_formats; + chan->videousers++; + if (chan->dev->card_info->switch_ctrl) + chan->dev->card_info->switch_ctrl(chan, 2, 1); + return 0; +} + +int video_close(struct inode *inode, struct file *filp) +{ + struct ngene_vopen *vopen = filp->private_data; + struct ngene_channel *chan = vopen->ch; + + chan->videousers--; + if (!chan->videousers) { + if (chan->dev->card_info->switch_ctrl) + chan->dev->card_info->switch_ctrl(chan, 2, 0); + ngene_analog_stop_feed(chan); + } + videobuf_mmap_free(&vopen->vbuf_q); + v4l2_prio_close(&chan->prio, &vopen->prio); + filp->private_data = NULL; + kfree(vopen); + return 0; +} + +/****************************************************************************/ + +static int vid_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) +{ + struct ngene_vopen *vopen = file->private_data; + struct ngene_channel *chan = vopen->ch; + struct ngene *dev = chan->dev; + struct i2c_adapter *adap = &chan->i2c_adapter; + int retval = 0; + int err = 0; + + switch (cmd) { + + case VIDIOC_S_CTRL: + { + struct v4l2_control *c = parg; + + err = v4l2_prio_check(&chan->prio, &vopen->prio); + if (err) + return err; + + if (c->id == V4L2_CID_AUDIO_MUTE) { + if (c->value) + (dev->channel[chan->number + 2]).audiomute = 1; + else + (dev->channel[chan->number + 2]).audiomute = 0; + return 0; + } + if (c->value != V4L2_CID_AUDIO_MUTE) + ngene_analog_stop_feed(chan); + i2c_clients_command(adap, cmd, parg); + return 0; + } + + case VIDIOC_S_TUNER: + { + err = v4l2_prio_check(&chan->prio, &vopen->prio); + if (err != 0) + return err; + i2c_clients_command(adap, cmd, parg); + return 0; + } + + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = parg; + u8 drxa = dev->card_info->demoda[chan->number]; + + if (chan->fe && chan->fe->ops.tuner_ops.set_frequency) + chan->fe->ops.tuner_ops. + set_frequency(chan->fe, f->frequency * 62500); + if (drxa) + ; + } + + case VIDIOC_S_INPUT: + { + err = v4l2_prio_check(&chan->prio, &vopen->prio); + if (err != 0) + return err; + i2c_clients_command(adap, cmd, parg); + return 0; + } + + case VIDIOC_G_STD: + { + v4l2_std_id *id = parg; + *id = chan->tvnorms[chan->tvnorm].v4l2_id; + return 0; + } + + case VIDIOC_S_STD: + { + v4l2_std_id *id = parg; + unsigned int i; + + err = v4l2_prio_check(&chan->prio, &vopen->prio); + if (err != 0) + return err; + ngene_analog_stop_feed(chan); + i2c_clients_command(adap, cmd, parg); + for (i = 0; i < chan->tvnorm_num; i++) + if (*id & chan->tvnorms[i].v4l2_id) + break; + if (i == chan->tvnorm_num) + return -EINVAL; + + chan->tvnorm = i; + mdelay(50); + ngene_analog_start_feed(chan); + return 0; + } + + case VIDIOC_G_FREQUENCY: + case VIDIOC_G_INPUT: + case VIDIOC_S_AUDIO: + case VIDIOC_G_AUDIO: + case VIDIOC_ENUMAUDIO: + case VIDIOC_S_MODULATOR: + case VIDIOC_G_MODULATOR: + case VIDIOC_G_CTRL: + { + i2c_clients_command(adap, cmd, parg); + return 0; + } + + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *tuner = parg; + if (tuner->index != 0) + return -EINVAL; + i2c_clients_command(adap, cmd, parg); + + if (chan->fe && chan->fe->ops.tuner_ops.get_status) { + u32 status; + + chan->fe->ops.tuner_ops.get_status(chan->fe, &status); + tuner->signal = status; + } + return 0; + } + + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *c = parg; + int i; + + if ((c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) && + (c->id < V4L2_CID_PRIVATE_BASE || + c->id >= V4L2_CID_PRIVATE_LASTP1)) + return -EINVAL; + for (i = 0; i < NGENE_CTLS; i++) + if (ngene_ctls[i].id == c->id) + break; + if (i == NGENE_CTLS) { + *c = no_ctl; + return 0; + } + *c = ngene_ctls[i]; + return 0; + } + + case VIDIOC_G_FMT: + { + struct v4l2_format *f = parg; + ngene_g_fmt(vopen, f); + } + + case VIDIOC_S_FMT: + { + struct v4l2_format *f = parg; + + ngene_analog_stop_feed(chan); + return ngene_s_fmt(vopen, chan, f); + } + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = parg; + enum v4l2_buf_type type; + unsigned int i; + int index; + + type = f->type; + if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { + /* vbi + index = f->index; + if (0 != index) + return -EINVAL; + memset(f, 0, sizeof(*f)); + f->index = index; + f->type = type; + f->pixelformat = V4L2_PIX_FMT_GREY; + strcpy(f->description, "vbi data"); */ + return EINVAL; + } + + /* video capture + overlay */ + index = -1; + for (i = 0; i < NGENE_FORMATS; i++) { + if (ngene_formats[i].fourcc != -1) + index++; + if ((unsigned int)index == f->index) + break; + } + if (NGENE_FORMATS == i) + return -EINVAL; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + /* dprintk(KERN_DEBUG + "Video Overlay not supported yet.\n"); */ + return -EINVAL; + break; + default: + return -EINVAL; + } + memset(f, 0, sizeof(*f)); + f->index = index; + f->type = type; + f->pixelformat = ngene_formats[i].fourcc; + strlcpy(f->description, ngene_formats[i].name, + sizeof(f->description)); + return 0; + + } + + case VIDIOC_QUERYSTD: + { + v4l2_std_id *id = parg; + *id = V4L2_STD_625_50 | V4L2_STD_525_60; + return 0; + } + + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *e = parg; + unsigned int index = e->index; + + if (index >= chan->tvnorm_num) + return -EINVAL; + v4l2_video_std_construct(e, chan->tvnorms[e->index].v4l2_id, + chan->tvnorms[e->index].name); + e->index = index; + return 0; + } + + case VIDIOC_QUERYCAP: + { + static char driver[] = {'n', 'G', 'e', 'n', 'e', '\0'}; + static char card[] = {'M', 'k', '4', 'x', 'x', '\0'}; + struct v4l2_capability *cap = parg; + + memset(cap, 0, sizeof(*cap)); + if (dev->nr == 0) + card[3] = '0'; + else + card[3] = '1'; + if (chan->number) + card[4] = 'a'; + else + card[4] = 'b'; + strlcpy(cap->driver, driver, sizeof(cap->driver)); + strlcpy(cap->card, card, sizeof(cap->card)); + cap->bus_info[0] = 0; + cap->version = KERNEL_VERSION(0, 8, 1); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE| + V4L2_CAP_TUNER|V4L2_CAP_AUDIO| + V4L2_CAP_READWRITE|V4L2_CAP_STREAMING; + return 0; + } + + case VIDIOC_ENUMINPUT: + { + static char *inputname[2] = { + "AnalogTuner", + "S-Video" + }; + + struct v4l2_input *i = parg; + unsigned int index; + index = i->index; + + if (index > 1) + return -EINVAL; + + memset(i, 0, sizeof(*i)); + i->index = index; + strlcpy(i->name, inputname[index], sizeof(i->name)); + + i->type = index ? V4L2_INPUT_TYPE_CAMERA : + V4L2_INPUT_TYPE_TUNER; + i->audioset = 0; + i->tuner = 0; + i->std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M; + i->status = 0;/* V4L2_IN_ST_NO_H_LOCK; */ + return 0; + } + + case VIDIOC_G_PARM: + return -EINVAL; + + case VIDIOC_S_PARM: + return -EINVAL; + + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *prio = parg; + *prio = v4l2_prio_max(&chan->prio); + return 0; + } + + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *prio = parg; + return v4l2_prio_change(&chan->prio, &vopen->prio, *prio); + return 0; + } + + case VIDIOC_CROPCAP: + return -EINVAL; + + case VIDIOC_G_CROP: + return -EINVAL; + + case VIDIOC_S_CROP: + return -EINVAL; + + case VIDIOC_G_FBUF: + { + struct v4l2_framebuffer *fb = parg; + + *fb = chan->fbuf; + fb->capability = 0; + if (vopen->ovfmt) + fb->fmt.pixelformat = vopen->ovfmt->fourcc; + return 0; + } + + case VIDIOC_REQBUFS: + return videobuf_reqbufs(ngene_queue(vopen), parg); + + case VIDIOC_QUERYBUF: + return videobuf_querybuf(ngene_queue(vopen), parg); + + case VIDIOC_QBUF: + return videobuf_qbuf(ngene_queue(vopen), parg); + + case VIDIOC_DQBUF: + return videobuf_dqbuf(ngene_queue(vopen), parg, + file->f_flags & O_NONBLOCK); + + case VIDIOC_S_FBUF: + { + /* ngene_analog_stop_feed(chan); */ + struct v4l2_framebuffer *fb = parg; + const struct ngene_format *fmt; + + if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) + return -EPERM; + + /* check args */ + fmt = ngene_formats; /*format_by_fourcc(fb->fmt.pixelformat);*/ + if (NULL == fmt) + return -EINVAL; + + if (0 == (fmt->flags & 0x02 /*FORMAT_FLAGS_PACKED*/)) + return -EINVAL; + + mutex_lock(&vopen->vbuf_q.lock); + retval = -EINVAL; + + if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { + int maxLinesPerField; + + if (fb->fmt.width > + chan->tvnorms[chan->tvnorm].swidth) + goto vopen_unlock_and_return; + maxLinesPerField = chan->tvnorms[chan->tvnorm].sheight; + if (fb->fmt.height > maxLinesPerField) + goto vopen_unlock_and_return; + } + + /* ok, accept it */ + chan->fbuf.base = fb->base; + chan->fbuf.fmt.width = fb->fmt.width; + chan->fbuf.fmt.height = fb->fmt.height; + if (0 != fb->fmt.bytesperline) + chan->fbuf.fmt.bytesperline = fb->fmt.bytesperline; + else + chan->fbuf.fmt.bytesperline = + chan->fbuf.fmt.width * fmt->depth / 8; + + retval = 0; + vopen->ovfmt = fmt; + chan->init.ovfmt = fmt; + +vopen_unlock_and_return: + mutex_unlock(&vopen->vbuf_q.lock); + return retval; + + } + + case VIDIOC_ENUMOUTPUT: + return -EINVAL; + + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = parg; + return ngene_try_fmt(vopen, chan, f); + + } + + case VIDIOC_STREAMON: + { + int res = ngene_resource(vopen); + if (!check_alloc_res(chan, vopen, res)) + return -EBUSY; + ngene_analog_start_feed(chan); + return videobuf_streamon(ngene_queue(vopen)); + } + + case VIDIOC_STREAMOFF: + { + int res = ngene_resource(vopen); + int retval = videobuf_streamoff(ngene_queue(vopen)); + ngene_analog_stop_feed(chan); + if (retval < 0) + return retval; + + free_res(chan, vopen, res); + return 0; + } + + case VIDIOC_OVERLAY: + return -EINVAL; + + case VIDIOCGFBUF: + { + struct video_buffer *vb = parg; + + memset(vb, 0, sizeof(*vb)); + return 0; + } + + default: + err = -EINVAL; + break; + } + return err; +} + +/* +static int vid_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, vid_do_ioctl); +} +*/ +static unsigned int video_fix_command(unsigned int cmd) +{ + switch (cmd) { + } + return cmd; +} + +static int vid_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void *parg = (void *)arg, *pbuf = NULL; + char buf[64]; + int res = -EFAULT; + cmd = video_fix_command(cmd); + + if (_IOC_DIR(cmd) & _IOC_WRITE) { + parg = buf; + if (_IOC_SIZE(cmd) > sizeof(buf)) { + pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (!pbuf) + return -ENOMEM; + parg = pbuf; + } + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto error; + } + res = vid_do_ioctl(inode, file, cmd, parg); + if (res < 0) + goto error; + if (_IOC_DIR(cmd) & _IOC_READ) + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + res = -EFAULT; +error: + kfree(pbuf); + return res; +} + +static int ngene_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct ngene_vopen *vopen = file->private_data; + return videobuf_mmap_mapper(ngene_queue(vopen), vma); +} + +#define MAGIC_BUFFER 0x20040302 +void *my_videobuf_alloc(unsigned int size) +{ + struct videobuf_buffer *vb; + + vb = kmalloc(size, GFP_KERNEL); + if (NULL != vb) { + memset(vb, 0, size); + videobuf_dma_init(&vb->dma); + init_waitqueue_head(&vb->done); + vb->magic = MAGIC_BUFFER; + } + return vb; +} + +static ssize_t driver_read(struct file *file, char *user, + size_t count, loff_t *offset) +{ + char __user *data = user; + struct ngene_channel *chan; + int retval = 0; + struct videobuf_queue *q; + struct ngene_vopen *vopen = file->private_data; + int nonblocking = file->f_flags & O_NONBLOCK; + enum v4l2_field field; + unsigned long flags; + unsigned size, nbufs, bytes; + + if (!vopen) + return 0; + + chan = vopen->ch; + q = &vopen->vbuf_q; + + mutex_lock(&q->lock); + nbufs = 1; + size = 0; + q->ops->buf_setup(q, &nbufs, &size); + + if (NULL == q->read_buf) { + /* need to capture a new frame */ + retval = -ENOMEM; + q->read_buf = my_videobuf_alloc(q->msize); + if (NULL == q->read_buf) + goto done; + + q->read_buf->memory = V4L2_MEMORY_USERPTR; + field = V4L2_FIELD_INTERLACED; + retval = q->ops->buf_prepare(q, q->read_buf, field); + if (0 != retval) { + kfree(q->read_buf); + q->read_buf = NULL; + goto done; + } + + spin_lock_irqsave(q->irqlock, flags); + q->ops->buf_queue(q, q->read_buf); + spin_unlock_irqrestore(q->irqlock, flags); + q->read_off = 0; + } + + ngene_analog_start_feed(chan); + /* wait until capture is done */ + retval = videobuf_waiton(q->read_buf, nonblocking, 1); + if (0 != retval) + goto done; + videobuf_dma_sync(q, &q->read_buf->dma); + + if (STATE_ERROR == q->read_buf->state) { + /* catch I/O errors */ + q->ops->buf_release(q, q->read_buf); + kfree(q->read_buf); + q->read_buf = NULL; + retval = -EIO; + goto done; + } + + /* copy to userspace */ + bytes = count; + if (bytes > q->read_buf->size - q->read_off) + bytes = q->read_buf->size - q->read_off; + retval = -EFAULT; + + if (copy_to_user(data, q->read_buf->dma.vmalloc + q->read_off, bytes)) + goto done; + + retval = bytes; + + q->read_off += bytes; + if (q->read_off == q->read_buf->size) { + /* all data copied, cleanup */ + q->ops->buf_release(q, q->read_buf); + kfree(q->read_buf); + q->read_buf = NULL; + } + +done: + mutex_unlock(&q->lock); + + ngene_analog_stop_feed(chan); + + return retval; +} + +static unsigned int ngene_poll(struct file *file, poll_table *wait) +{ + struct ngene_vopen *vopen = file->private_data; + struct ngene_buffer *buf; + enum v4l2_field field; + + if (check_res(vopen, RESOURCE_VIDEO)) { + /* streaming capture */ + if (list_empty(&vopen->vbuf_q.stream)) + return POLLERR; + buf = list_entry(vopen->vbuf_q.stream.next, + struct ngene_buffer, vb.stream); + } else { + /* read() capture */ + mutex_lock(&vopen->vbuf_q.lock); + if (NULL == vopen->vbuf_q.read_buf) { + /* need to capture a new frame */ + if (locked_res(vopen->ch, RESOURCE_VIDEO)) { + mutex_unlock(&vopen->vbuf_q.lock); + return POLLERR; + } + vopen->vbuf_q.read_buf = + videobuf_alloc(vopen->vbuf_q.msize); + if (NULL == vopen->vbuf_q.read_buf) { + mutex_unlock(&vopen->vbuf_q.lock); + return POLLERR; + } + vopen->vbuf_q.read_buf->memory = V4L2_MEMORY_USERPTR; + field = videobuf_next_field(&vopen->vbuf_q); + if (0 != + vopen->vbuf_q.ops-> + buf_prepare(&vopen->vbuf_q, + vopen->vbuf_q.read_buf, field)) { + mutex_unlock(&vopen->vbuf_q.lock); + return POLLERR; + } + vopen->vbuf_q.ops->buf_queue(&vopen->vbuf_q, + vopen->vbuf_q.read_buf); + vopen->vbuf_q.read_off = 0; + } + mutex_unlock(&vopen->vbuf_q.lock); + buf = (struct ngene_buffer *)vopen->vbuf_q.read_buf; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == STATE_DONE || buf->vb.state == STATE_ERROR) + return POLLIN | POLLRDNORM; + return 0; +} + +static const struct file_operations ngene_fops = { + .owner = THIS_MODULE, + .read = driver_read, + .write = 0, + .open = video_open, + .release = video_close, + .ioctl = vid_ioctl, + .poll = ngene_poll, + .mmap = ngene_mmap, +}; + +static struct video_device ngene_cinfo = { + .name = "analog_Ngene", + .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_SCALES, + .fops = &ngene_fops, + .minor = -1, +}; + +void ngene_v4l2_remove(struct ngene_channel *chan) +{ + video_unregister_device(chan->v4l_dev); +} + +int ngene_v4l2_init(struct ngene_channel *chan) +{ + int ret = 0; + struct video_device *v_dev; + + chan->evenbuffer = NULL; + chan->dma_on = 0; + + v_dev = video_device_alloc(); + *v_dev = ngene_cinfo; + /* v_dev->dev = &(chan->dev->pci_dev->dev); */ + v_dev->release = video_device_release; + v_dev->minor = -1; + video_register_device(v_dev, VFL_TYPE_GRABBER, -1); + snprintf(v_dev->name, sizeof(v_dev->name), "AnalognGene%d", + v_dev->minor); + chan->v4l_dev = v_dev; + chan->minor = v_dev->minor; + printk(KERN_INFO "nGene V4L2 device video%d registered.\n", + v_dev->minor); + + v_dev->dev = &chan->device; + my_video_set_drvdata(chan->v4l_dev, chan); + + v4l2_prio_init(&chan->prio); + + if (chan->dev->card_info->io_type[chan->number] == NGENE_IO_HDTV) { + chan->tvnorms = ngene_tvnorms_hd; + chan->tvnorm_num = 1; + } else { + chan->tvnorms = ngene_tvnorms_sd; + chan->tvnorm_num = NGENE_TVNORMS; + } + chan->tvnorm = 0; + + spin_lock_init(&chan->s_lock); + init_MUTEX(&chan->reslock); + INIT_LIST_HEAD(&chan->capture); + chan->users = 0; + chan->videousers = 0; + chan->init.ov.w.width = 384; + chan->init.ov.w.height = 288; + chan->init.fmt = ngene_formats; + chan->init.width = 384; + chan->init.height = 288; + chan->tun_rdy = 0; + chan->dec_rdy = 0; + chan->tun_dec_rdy = 0; + chan->lastbufferflag = -1; + + if (chan->dev->card_info->avf[chan->number]) + avf4910a_attach(&chan->i2c_adapter, + chan->dev->card_info->avf[chan->number]); + + return ret; +} diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h new file mode 100644 index 00000000000..9b48250fdbf --- /dev/null +++ b/drivers/media/dvb/ngene/ngene.h @@ -0,0 +1,948 @@ +/* + * ngene.h: nGene PCIe bridge driver + * + * Copyright (C) 2005-2007 Micronas + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef _NGENE_H_ +#define _NGENE_H_ + +#define ONE_ADAPTER +#define NGENE_COMMAND_API +/*#define NGENE_V4L*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_ringbuffer.h" +#include "drxd.h" +#include "drxh.h" +#include "xc3028.h" +#include "stb0899.h" +#include "stv0900.h" +#include "mt2060.h" + +#ifdef NGENE_V4L +#include +#include +#include +#endif + +#define NGENE_VID 0x18c3 +#define NGENE_PID 0x0720 + +#ifndef VIDEO_CAP_VC1 +#define VIDEO_CAP_AVC 128 +#define VIDEO_CAP_H264 128 +#define VIDEO_CAP_VC1 256 +#define VIDEO_CAP_WMV9 256 +#define VIDEO_CAP_MPEG4 512 +#endif + +enum STREAM { + STREAM_VIDEOIN1 = 0, /* ITU656 or TS Input */ + STREAM_VIDEOIN2, + STREAM_AUDIOIN1, /* I2S or SPI Input */ + STREAM_AUDIOIN2, + STREAM_AUDIOOUT, + MAX_STREAM +}; + +enum SMODE_BITS { + SMODE_AUDIO_SPDIF = 0x20, + SMODE_AVSYNC = 0x10, + SMODE_TRANSPORT_STREAM = 0x08, + SMODE_AUDIO_CAPTURE = 0x04, + SMODE_VBI_CAPTURE = 0x02, + SMODE_VIDEO_CAPTURE = 0x01 +}; + +enum STREAM_FLAG_BITS { + SFLAG_CHROMA_FORMAT_2COMP = 0x01, /* Chroma Format : 2's complement */ + SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */ + SFLAG_ORDER_LUMA_CHROMA = 0x02, /* Byte order: Y,Cb,Y,Cr */ + SFLAG_ORDER_CHROMA_LUMA = 0x00, /* Byte order: Cb,Y,Cr,Y */ + SFLAG_COLORBAR = 0x04, /* Select colorbar */ +}; + +#define PROGRAM_ROM 0x0000 +#define PROGRAM_SRAM 0x1000 +#define PERIPHERALS0 0x8000 +#define PERIPHERALS1 0x9000 +#define SHARED_BUFFER 0xC000 + +#define HOST_TO_NGENE (SHARED_BUFFER+0x0000) +#define NGENE_TO_HOST (SHARED_BUFFER+0x0100) +#define NGENE_COMMAND (SHARED_BUFFER+0x0200) +#define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204) +#define NGENE_STATUS (SHARED_BUFFER+0x0208) +#define NGENE_STATUS_HI (SHARED_BUFFER+0x020C) +#define NGENE_EVENT (SHARED_BUFFER+0x0210) +#define NGENE_EVENT_HI (SHARED_BUFFER+0x0214) +#define VARIABLES (SHARED_BUFFER+0x0210) + +#define NGENE_INT_COUNTS (SHARED_BUFFER+0x0260) +#define NGENE_INT_ENABLE (SHARED_BUFFER+0x0264) +#define NGENE_VBI_LINE_COUNT (SHARED_BUFFER+0x0268) + +#define BUFFER_GP_XMIT (SHARED_BUFFER+0x0800) +#define BUFFER_GP_RECV (SHARED_BUFFER+0x0900) +#define EEPROM_AREA (SHARED_BUFFER+0x0A00) + +#define SG_V_IN_1 (SHARED_BUFFER+0x0A80) +#define SG_VBI_1 (SHARED_BUFFER+0x0B00) +#define SG_A_IN_1 (SHARED_BUFFER+0x0B80) +#define SG_V_IN_2 (SHARED_BUFFER+0x0C00) +#define SG_VBI_2 (SHARED_BUFFER+0x0C80) +#define SG_A_IN_2 (SHARED_BUFFER+0x0D00) +#define SG_V_OUT (SHARED_BUFFER+0x0D80) +#define SG_A_OUT2 (SHARED_BUFFER+0x0E00) + +#define DATA_A_IN_1 (SHARED_BUFFER+0x0E80) +#define DATA_A_IN_2 (SHARED_BUFFER+0x0F00) +#define DATA_A_OUT (SHARED_BUFFER+0x0F80) +#define DATA_V_IN_1 (SHARED_BUFFER+0x1000) +#define DATA_V_IN_2 (SHARED_BUFFER+0x2000) +#define DATA_V_OUT (SHARED_BUFFER+0x3000) + +#define DATA_FIFO_AREA (SHARED_BUFFER+0x1000) + +#define TIMESTAMPS 0xA000 +#define SCRATCHPAD 0xA080 +#define FORCE_INT 0xA088 +#define FORCE_NMI 0xA090 +#define INT_STATUS 0xA0A0 + +#define DEV_VER 0x9004 + +#define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF) + +struct SG_ADDR { + u64 start; + u64 curr; + u16 curr_ptr; + u16 elements; + u32 pad[3]; +} __attribute__ ((__packed__)); + +struct SHARED_MEMORY { + /* C000 */ + u32 HostToNgene[64]; + + /* C100 */ + u32 NgeneToHost[64]; + + /* C200 */ + u64 NgeneCommand; + u64 NgeneStatus; + u64 NgeneEvent; + + /* C210 */ + u8 pad1[0xc260 - 0xc218]; + + /* C260 */ + u32 IntCounts; + u32 IntEnable; + + /* C268 */ + u8 pad2[0xd000 - 0xc268]; + +} __attribute__ ((__packed__)); + +struct BUFFER_STREAM_RESULTS { + u32 Clock; /* Stream time in 100ns units */ + u16 RemainingLines; /* Remaining lines in this field. + 0 for complete field */ + u8 FieldCount; /* Video field number */ + u8 Flags; /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow, + Bit 0 = FieldID */ + u16 BlockCount; /* Audio block count (unused) */ + u8 Reserved[2]; + u32 DTOUpdate; +} __attribute__ ((__packed__)); + +struct HW_SCATTER_GATHER_ELEMENT { + u64 Address; + u32 Length; + u32 Reserved; +} __attribute__ ((__packed__)); + +struct BUFFER_HEADER { + u64 Next; + struct BUFFER_STREAM_RESULTS SR; + + u32 Number_of_entries_1; + u32 Reserved5; + u64 Address_of_first_entry_1; + + u32 Number_of_entries_2; + u32 Reserved7; + u64 Address_of_first_entry_2; +} __attribute__ ((__packed__)); + +struct EVENT_BUFFER { + u32 TimeStamp; + u8 GPIOStatus; + u8 UARTStatus; + u8 RXCharacter; + u8 EventStatus; + u32 Reserved[2]; +} __attribute__ ((__packed__)); + +typedef struct EVENT_BUFFER *PEVENT_BUFFER; + +/* Firmware commands. */ + +enum OPCODES { + CMD_NOP = 0, + CMD_FWLOAD_PREPARE = 0x01, + CMD_FWLOAD_FINISH = 0x02, + CMD_I2C_READ = 0x03, + CMD_I2C_WRITE = 0x04, + + CMD_I2C_WRITE_NOSTOP = 0x05, + CMD_I2C_CONTINUE_WRITE = 0x06, + CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07, + + CMD_DEBUG_OUTPUT = 0x09, + + CMD_CONTROL = 0x10, + CMD_CONFIGURE_BUFFER = 0x11, + CMD_CONFIGURE_FREE_BUFFER = 0x12, + + CMD_SPI_READ = 0x13, + CMD_SPI_WRITE = 0x14, + + CMD_MEM_READ = 0x20, + CMD_MEM_WRITE = 0x21, + CMD_SFR_READ = 0x22, + CMD_SFR_WRITE = 0x23, + CMD_IRAM_READ = 0x24, + CMD_IRAM_WRITE = 0x25, + CMD_SET_GPIO_PIN = 0x26, + CMD_SET_GPIO_INT = 0x27, + CMD_CONFIGURE_UART = 0x28, + CMD_WRITE_UART = 0x29, + MAX_CMD +}; + +enum RESPONSES { + OK = 0, + ERROR = 1 +}; + +struct FW_HEADER { + u8 Opcode; + u8 Length; +} __attribute__ ((__packed__)); + +struct FW_I2C_WRITE { + struct FW_HEADER hdr; + u8 Device; + u8 Data[250]; +} __attribute__ ((__packed__)); + +struct FW_I2C_CONTINUE_WRITE { + struct FW_HEADER hdr; + u8 Data[250]; +} __attribute__ ((__packed__)); + +struct FW_I2C_READ { + struct FW_HEADER hdr; + u8 Device; + u8 Data[252]; /* followed by two bytes of read data count */ +} __attribute__ ((__packed__)); + +struct FW_SPI_WRITE { + struct FW_HEADER hdr; + u8 ModeSelect; + u8 Data[250]; +} __attribute__ ((__packed__)); + +struct FW_SPI_READ { + struct FW_HEADER hdr; + u8 ModeSelect; + u8 Data[252]; /* followed by two bytes of read data count */ +} __attribute__ ((__packed__)); + +struct FW_FWLOAD_PREPARE { + struct FW_HEADER hdr; +} __attribute__ ((__packed__)); + +struct FW_FWLOAD_FINISH { + struct FW_HEADER hdr; + u16 Address; /* address of final block */ + u16 Length; +} __attribute__ ((__packed__)); + +/* + * Meaning of FW_STREAM_CONTROL::Mode bits: + * Bit 7: Loopback PEXin to PEXout using TVOut channel + * Bit 6: AVLOOP + * Bit 5: Audio select; 0=I2S, 1=SPDIF + * Bit 4: AVSYNC + * Bit 3: Enable transport stream + * Bit 2: Enable audio capture + * Bit 1: Enable ITU-Video VBI capture + * Bit 0: Enable ITU-Video capture + * + * Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL) + * Bit 7: continuous capture + * Bit 6: capture one field + * Bit 5: capture one frame + * Bit 4: unused + * Bit 3: starting field; 0=odd, 1=even + * Bit 2: sample size; 0=8-bit, 1=10-bit + * Bit 1: data format; 0=UYVY, 1=YUY2 + * Bit 0: resets buffer pointers +*/ + +enum FSC_MODE_BITS { + SMODE_LOOPBACK = 0x80, + SMODE_AVLOOP = 0x40, + _SMODE_AUDIO_SPDIF = 0x20, + _SMODE_AVSYNC = 0x10, + _SMODE_TRANSPORT_STREAM = 0x08, + _SMODE_AUDIO_CAPTURE = 0x04, + _SMODE_VBI_CAPTURE = 0x02, + _SMODE_VIDEO_CAPTURE = 0x01 +}; + + +/* Meaning of FW_STREAM_CONTROL::Stream bits: + * Bit 3: Audio sample count: 0 = relative, 1 = absolute + * Bit 2: color bar select; 1=color bars, 0=CV3 decoder + * Bits 1-0: stream select, UVI1, UVI2, TVOUT + */ + +struct FW_STREAM_CONTROL { + struct FW_HEADER hdr; + u8 Stream; /* Stream number (UVI1, UVI2, TVOUT) */ + u8 Control; /* Value written to UVI1_CTL */ + u8 Mode; /* Controls clock source */ + u8 SetupDataLen; /* Length of setup data, MSB=1 write + backwards */ + u16 CaptureBlockCount; /* Blocks (a 256 Bytes) to capture per buffer + for TS and Audio */ + u64 Buffer_Address; /* Address of first buffer header */ + u16 BytesPerVideoLine; + u16 MaxLinesPerField; + u16 MinLinesPerField; + u16 Reserved_1; + u16 BytesPerVBILine; + u16 MaxVBILinesPerField; + u16 MinVBILinesPerField; + u16 SetupDataAddr; /* ngene relative address of setup data */ + u8 SetupData[32]; /* setup data */ +} __attribute__((__packed__)); + +#define AUDIO_BLOCK_SIZE 256 +#define TS_BLOCK_SIZE 256 + +struct FW_MEM_READ { + struct FW_HEADER hdr; + u16 address; +} __attribute__ ((__packed__)); + +struct FW_MEM_WRITE { + struct FW_HEADER hdr; + u16 address; + u8 data; +} __attribute__ ((__packed__)); + +struct FW_SFR_IRAM_READ { + struct FW_HEADER hdr; + u8 address; +} __attribute__ ((__packed__)); + +struct FW_SFR_IRAM_WRITE { + struct FW_HEADER hdr; + u8 address; + u8 data; +} __attribute__ ((__packed__)); + +struct FW_SET_GPIO_PIN { + struct FW_HEADER hdr; + u8 select; +} __attribute__ ((__packed__)); + +struct FW_SET_GPIO_INT { + struct FW_HEADER hdr; + u8 select; +} __attribute__ ((__packed__)); + +struct FW_SET_DEBUGMODE { + struct FW_HEADER hdr; + u8 debug_flags; +} __attribute__ ((__packed__)); + +struct FW_CONFIGURE_BUFFERS { + struct FW_HEADER hdr; + u8 config; +} __attribute__ ((__packed__)); + +enum _BUFFER_CONFIGS { + /* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2 (standard usage) */ + BUFFER_CONFIG_4422 = 0, + /* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2 (4x TS input usage) */ + BUFFER_CONFIG_3333 = 1, + /* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut (HDTV decoder usage) */ + BUFFER_CONFIG_8022 = 2, + BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */ +}; + +struct FW_CONFIGURE_FREE_BUFFERS { + struct FW_HEADER hdr; + u8 UVI1_BufferLength; + u8 UVI2_BufferLength; + u8 TVO_BufferLength; + u8 AUD1_BufferLength; + u8 AUD2_BufferLength; + u8 TVA_BufferLength; +} __attribute__ ((__packed__)); + +struct FW_CONFIGURE_UART { + struct FW_HEADER hdr; + u8 UartControl; +} __attribute__ ((__packed__)); + +enum _UART_CONFIG { + _UART_BAUDRATE_19200 = 0, + _UART_BAUDRATE_9600 = 1, + _UART_BAUDRATE_4800 = 2, + _UART_BAUDRATE_2400 = 3, + _UART_RX_ENABLE = 0x40, + _UART_TX_ENABLE = 0x80, +}; + +struct FW_WRITE_UART { + struct FW_HEADER hdr; + u8 Data[252]; +} __attribute__ ((__packed__)); + + +struct ngene_command { + u32 in_len; + u32 out_len; + union { + u32 raw[64]; + u8 raw8[256]; + struct FW_HEADER hdr; + struct FW_I2C_WRITE I2CWrite; + struct FW_I2C_CONTINUE_WRITE I2CContinueWrite; + struct FW_I2C_READ I2CRead; + struct FW_STREAM_CONTROL StreamControl; + struct FW_FWLOAD_PREPARE FWLoadPrepare; + struct FW_FWLOAD_FINISH FWLoadFinish; + struct FW_MEM_READ MemoryRead; + struct FW_MEM_WRITE MemoryWrite; + struct FW_SFR_IRAM_READ SfrIramRead; + struct FW_SFR_IRAM_WRITE SfrIramWrite; + struct FW_SPI_WRITE SPIWrite; + struct FW_SPI_READ SPIRead; + struct FW_SET_GPIO_PIN SetGpioPin; + struct FW_SET_GPIO_INT SetGpioInt; + struct FW_SET_DEBUGMODE SetDebugMode; + struct FW_CONFIGURE_BUFFERS ConfigureBuffers; + struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers; + struct FW_CONFIGURE_UART ConfigureUart; + struct FW_WRITE_UART WriteUart; + } cmd; +} __attribute__ ((__packed__)); + +#define NGENE_INTERFACE_VERSION 0x103 +#define MAX_VIDEO_BUFFER_SIZE (417792) /* 288*1440 rounded up to next page */ +#define MAX_AUDIO_BUFFER_SIZE (8192) /* Gives room for about 23msec@48KHz */ +#define MAX_VBI_BUFFER_SIZE (28672) /* 1144*18 rounded up to next page */ +#define MAX_TS_BUFFER_SIZE (98304) /* 512*188 rounded up to next page */ +#define MAX_HDTV_BUFFER_SIZE (2080768) /* 541*1920*2 rounded up to next page + Max: (1920x1080i60) */ + +#define OVERFLOW_BUFFER_SIZE (8192) + +#define RING_SIZE_VIDEO 4 +#define RING_SIZE_AUDIO 8 +#define RING_SIZE_TS 8 + +#define NUM_SCATTER_GATHER_ENTRIES 8 + +#define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \ + RING_SIZE_VIDEO * 2) + \ + (MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \ + (MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \ + (RING_SIZE_VIDEO * PAGE_SIZE * 2) + \ + (RING_SIZE_AUDIO * PAGE_SIZE * 2) + \ + (RING_SIZE_TS * PAGE_SIZE * 4) + \ + 8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE) + +#define EVENT_QUEUE_SIZE 16 + +typedef struct HW_SCATTER_GATHER_ELEMENT *PHW_SCATTER_GATHER_ELEMENT; +typedef struct FWRB *PFWRB; + +/* Gathers the current state of a single channel. */ + +struct SBufferHeader { + struct BUFFER_HEADER ngeneBuffer; /* Physical descriptor */ + struct SBufferHeader *Next; + void *Buffer1; + PHW_SCATTER_GATHER_ELEMENT scList1; + void *Buffer2; + PHW_SCATTER_GATHER_ELEMENT scList2; +}; + +/* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */ +#define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63) + +enum HWSTATE { + HWSTATE_STOP, + HWSTATE_STARTUP, + HWSTATE_RUN, + HWSTATE_PAUSE, +}; + +enum KSSTATE { + KSSTATE_STOP, + KSSTATE_ACQUIRE, + KSSTATE_PAUSE, + KSSTATE_RUN, +}; + +struct SRingBufferDescriptor { + struct SBufferHeader *Head; /* Points to first buffer in ring buffer + structure*/ + u64 PAHead; /* Physical address of first buffer */ + u32 MemSize; /* Memory size of allocated ring buffers + (needed for freeing) */ + u32 NumBuffers; /* Number of buffers in the ring */ + u32 Buffer1Length; /* Allocated length of Buffer 1 */ + u32 Buffer2Length; /* Allocated length of Buffer 2 */ + void *SCListMem; /* Memory to hold scatter gather lists for this + ring */ + u64 PASCListMem; /* Physical address .. */ + u32 SCListMemSize; /* Size of this memory */ +}; + +enum STREAMMODEFLAGS { + StreamMode_NONE = 0, /* Stream not used */ + StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */ + StreamMode_TSIN = 2, /* Transport stream input (all) */ + StreamMode_HDTV = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60 + (only stream 0) */ + StreamMode_TSOUT = 8, /* Transport stream output (only stream 3) */ +}; + + +enum BufferExchangeFlags { + BEF_EVEN_FIELD = 0x00000001, + BEF_CONTINUATION = 0x00000002, + BEF_MORE_DATA = 0x00000004, + BEF_OVERFLOW = 0x00000008, + DF_SWAP32 = 0x00010000, +}; + +typedef void *(IBufferExchange)(void *, void *, u32, u32, u32); + +typedef struct { + IBufferExchange *pExchange; + IBufferExchange *pExchangeVBI; /* Secondary (VBI, ancillary) */ + u8 Stream; + u8 Flags; + u8 Mode; + u8 Reserved; + u16 nLinesVideo; + u16 nBytesPerLineVideo; + u16 nLinesVBI; + u16 nBytesPerLineVBI; + u32 CaptureLength; /* Used for audio and transport stream */ +} MICI_STREAMINFO, *PMICI_STREAMINFO; + +/****************************************************************************/ +/* STRUCTS ******************************************************************/ +/****************************************************************************/ + +/* sound hardware definition */ +#define MIXER_ADDR_TVTUNER 0 +#define MIXER_ADDR_LAST 0 + +struct ngene_channel; + +/*struct sound chip*/ + +struct mychip { + struct ngene_channel *chan; + struct snd_card *card; + struct pci_dev *pci; + struct snd_pcm_substream *substream; + struct snd_pcm *pcm; + unsigned long port; + int irq; + spinlock_t mixer_lock; + spinlock_t lock; + int mixer_volume[MIXER_ADDR_LAST + 1][2]; + int capture_source[MIXER_ADDR_LAST + 1][2]; +}; + +#ifdef NGENE_V4L +struct ngene_overlay { + int tvnorm; + struct v4l2_rect w; + enum v4l2_field field; + struct v4l2_clip *clips; + int nclips; + int setup_ok; +}; + +struct ngene_tvnorm { + int v4l2_id; + char *name; + u16 swidth, sheight; /* scaled standard width, height */ + int tuner_norm; + int soundstd; +}; + +struct ngene_vopen { + struct ngene_channel *ch; + enum v4l2_priority prio; + int width; + int height; + int depth; + struct videobuf_queue vbuf_q; + struct videobuf_queue vbi; + int fourcc; + int picxcount; + int resources; + enum v4l2_buf_type type; + const struct ngene_format *fmt; + + const struct ngene_format *ovfmt; + struct ngene_overlay ov; +}; +#endif + +struct ngene_channel { + struct device device; + struct i2c_adapter i2c_adapter; + + struct ngene *dev; + int number; + int type; + int mode; + + struct dvb_frontend *fe; + struct dmxdev dmxdev; + struct dvb_demux demux; + struct dmx_frontend hw_frontend; + struct dmx_frontend mem_frontend; + int users; + struct video_device *v4l_dev; +#ifndef ONE_ADAPTER + struct dvb_adapter dvb_adapter; +#endif + struct dvb_device *command_dev; + struct dvb_device *audio_dev; + struct dvb_device *video_dev; + struct tasklet_struct demux_tasklet; + + struct SBufferHeader *nextBuffer; + enum KSSTATE State; + enum HWSTATE HWState; + u8 Stream; + u8 Flags; + u8 Mode; + IBufferExchange *pBufferExchange; + IBufferExchange *pBufferExchange2; + + spinlock_t state_lock; + u16 nLines; + u16 nBytesPerLine; + u16 nVBILines; + u16 nBytesPerVBILine; + u16 itumode; + u32 Capture1Length; + u32 Capture2Length; + struct SRingBufferDescriptor RingBuffer; + struct SRingBufferDescriptor TSRingBuffer; + struct SRingBufferDescriptor TSIdleBuffer; + + u32 DataFormatFlags; + + int AudioDTOUpdated; + u32 AudioDTOValue; + + int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t); + u8 lnbh; + + /* stuff from analog driver */ + + int minor; + struct mychip *mychip; + struct snd_card *soundcard; + u8 *evenbuffer; + u8 *soundbuffer; + u8 dma_on; + int soundstreamon; + int audiomute; + int soundbuffisallocated; + int sndbuffflag; + int tun_rdy; + int dec_rdy; + int tun_dec_rdy; + int lastbufferflag; + + struct ngene_tvnorm *tvnorms; + int tvnorm_num; + int tvnorm; + +#ifdef NGENE_V4L + int videousers; + struct v4l2_prio_state prio; + struct ngene_vopen init; + int resources; + struct v4l2_framebuffer fbuf; + struct ngene_buffer *screen; /* overlay */ + struct list_head capture; /* video capture queue */ + spinlock_t s_lock; + struct semaphore reslock; +#endif + + int running; +}; + +struct ngene; + +typedef void (rx_cb_t)(struct ngene *, u32, u8); +typedef void (tx_cb_t)(struct ngene *, u32); + +struct ngene { + int nr; + struct pci_dev *pci_dev; + unsigned char *iomem; + +#ifdef ONE_ADAPTER + struct dvb_adapter dvb_adapter; +#endif + /*struct i2c_adapter i2c_adapter;*/ + + u32 device_version; + u32 fw_interface_version; + u32 icounts; + + u8 *CmdDoneByte; + int BootFirmware; + void *OverflowBuffer; + dma_addr_t PAOverflowBuffer; + void *FWInterfaceBuffer; + dma_addr_t PAFWInterfaceBuffer; + u8 *ngenetohost; + u8 *hosttongene; + + struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE]; + int EventQueueOverflowCount; + int EventQueueOverflowFlag; + struct tasklet_struct event_tasklet; + struct EVENT_BUFFER *EventBuffer; + int EventQueueWriteIndex; + int EventQueueReadIndex; + + wait_queue_head_t cmd_wq; + int cmd_done; + struct semaphore cmd_mutex; + struct semaphore stream_mutex; + struct semaphore pll_mutex; + struct semaphore i2c_switch_mutex; + int i2c_current_channel; + int i2c_current_bus; + spinlock_t cmd_lock; + + struct ngene_channel channel[MAX_STREAM]; + + struct ngene_info *card_info; + + tx_cb_t *TxEventNotify; + rx_cb_t *RxEventNotify; + int tx_busy; + wait_queue_head_t tx_wq; + wait_queue_head_t rx_wq; +#define UART_RBUF_LEN 4096 + u8 uart_rbuf[UART_RBUF_LEN]; + int uart_rp, uart_wp; + + u8 *tsout_buf; +#define TSOUT_BUF_SIZE (512*188*8) + struct dvb_ringbuffer tsout_rbuf; + + u8 *ain_buf; +#define AIN_BUF_SIZE (128*1024) + struct dvb_ringbuffer ain_rbuf; + + + u8 *vin_buf; +#define VIN_BUF_SIZE (4*1920*1080) + struct dvb_ringbuffer vin_rbuf; + + unsigned long exp_val; + int prev_cmd; +}; + +struct channel_info { + int io_type; +#define NGENE_IO_NONE 0 +#define NGENE_IO_TV 1 +#define NGENE_IO_HDTV 2 +#define NGENE_IO_TSIN 4 +#define NGENE_IO_TSOUT 8 +#define NGENE_IO_AIN 16 + + void *fe_config; + void *tuner_config; + + int (*demod_attach)(struct ngene_channel *); + int demod_type; +#define NGENE_DEMOD_NONE 0 +#define NGENE_DEMOD_DRXD 1 +#define NGENE_DEMOD_STB0899 2 +#define NGENE_DEMOD_DRXH 3 + + int (*tuner_attach)(struct ngene_channel *); + int tuner_type; +#define NGENE_TUNER_NONE 0 +#define NGENE_TUNER_MT2060 1 + + u8 demod; + u8 tuner; + u8 lnb; + u8 demoda; + u8 avf; + u8 msp; +}; + +struct ngene_info { + int type; +#define NGENE_APP 0 +#define NGENE_TERRATEC 1 +#define NGENE_SIDEWINDER 2 +#define NGENE_RACER 3 +#define NGENE_VIPER 4 +#define NGENE_PYTHON 5 +#define NGENE_VBOX_V1 6 +#define NGENE_VBOX_V2 7 + + int fw_version; + char *name; + + int io_type[MAX_STREAM]; +#define NGENE_IO_NONE 0 +#define NGENE_IO_TV 1 +#define NGENE_IO_HDTV 2 +#define NGENE_IO_TSIN 4 +#define NGENE_IO_TSOUT 8 +#define NGENE_IO_AIN 16 + + void *fe_config[4]; + void *tuner_config[4]; + + int (*demod_attach[4])(struct ngene_channel *); + int (*tuner_attach[4])(struct ngene_channel *); + + u8 avf[4]; + u8 msp[4]; + u8 demoda[4]; + u8 lnb[4]; + int i2c_access; + u8 ntsc; + u8 exp; + u8 exp_init; + u8 tsf[4]; + u8 i2s[4]; + + int (*gate_ctrl)(struct dvb_frontend *, int); + int (*switch_ctrl)(struct ngene_channel *, int, int); +}; + +#ifdef NGENE_V4L +struct ngene_format{ + char *name; + int fourcc; /* video4linux 2 */ + int btformat; /* BT848_COLOR_FMT_* */ + int format; + int btswap; /* BT848_COLOR_CTL_* */ + int depth; /* bit/pixel */ + int flags; + int hshift, vshift; /* for planar modes */ + int palette; +}; + +#define RESOURCE_OVERLAY 1 +#define RESOURCE_VIDEO 2 +#define RESOURCE_VBI 4 + +struct ngene_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* ngene specific */ + const struct ngene_format *fmt; + int tvnorm; + int btformat; + int btswap; +}; +#endif + +int ngene_command_stream_control(struct ngene *dev, + u8 stream, u8 control, u8 mode, u8 flags); +int ngene_command_nop(struct ngene *dev); +int ngene_command_i2c_read(struct ngene *dev, u8 adr, + u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); +int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); +int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); +int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); +int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, + u16 lines, u16 bpl, u16 vblines, u16 vbibpl); +int ngene_v4l2_init(struct ngene_channel *chan); +void ngene_v4l2_remove(struct ngene_channel *chan); +int ngene_snd_exit(struct ngene_channel *chan); +int ngene_snd_init(struct ngene_channel *chan); + +struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); + +#endif + +/* LocalWords: Endif + */ -- cgit v1.2.3 From 83f3c7157e087ace8fc67fd759bc3d7b3b64531e Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sat, 19 Dec 2009 04:54:44 -0300 Subject: V4L/DVB: ngene: Driver compiles now Remove LNBH21 routines, disable code which broke compilation. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 4 + drivers/media/dvb/Makefile | 3 +- drivers/media/dvb/ngene/Kconfig | 9 + drivers/media/dvb/ngene/Makefile | 11 + drivers/media/dvb/ngene/ngene-core.c | 1431 +--------------------------------- drivers/media/dvb/ngene/ngene.h | 29 - 6 files changed, 46 insertions(+), 1441 deletions(-) create mode 100644 drivers/media/dvb/ngene/Kconfig create mode 100644 drivers/media/dvb/ngene/Makefile (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index cf8f65f309d..161ccfd471c 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -76,6 +76,10 @@ comment "Supported Mantis Adapters" depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/mantis/Kconfig" +comment "Supported nGene Adapters" + depends on DVB_CORE && PCI && I2C + source "drivers/media/dvb/ngene/Kconfig" + comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index c12922c3659..a1a08758a6f 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile @@ -14,6 +14,7 @@ obj-y := dvb-core/ \ siano/ \ dm1105/ \ pt1/ \ - mantis/ + mantis/ \ + ngene/ obj-$(CONFIG_DVB_FIREDTV) += firewire/ diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig new file mode 100644 index 00000000000..3ec8e6fcbb1 --- /dev/null +++ b/drivers/media/dvb/ngene/Kconfig @@ -0,0 +1,9 @@ +config DVB_NGENE + tristate "Micronas nGene support" + depends on DVB_CORE && PCI && I2C + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_STV6110x if !DVB_FE_CUSTOMISE + select DVB_STV090x if !DVB_FE_CUSTOMISE + ---help--- + Support for Micronas PCI express cards with nGene bridge. + diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile new file mode 100644 index 00000000000..40435cad481 --- /dev/null +++ b/drivers/media/dvb/ngene/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the nGene device driver +# + +ngene-objs := ngene-core.o + +obj-$(CONFIG_DVB_NGENE) += ngene.o + +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/ + diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 744a232bd10..c0ef11c77f5 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -48,14 +48,12 @@ #include "ngene-ioctls.h" #endif -#define FW_INC 1 +/* #define FW_INC 1 */ #ifdef FW_INC #include "ngene_fw_15.h" #include "ngene_fw_16.h" #include "ngene_fw_17.h" -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - static int load_firmware; module_param(load_firmware, int, 0444); MODULE_PARM_DESC(load_firmware, "Try to load firmware from file."); @@ -73,6 +71,8 @@ static int debug; module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Print debugging information."); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + #define dprintk if (debug) printk #define DEVICE_NAME "ngene" @@ -670,15 +670,6 @@ static void FillTSBuffer(void *Buffer, int Length, u32 Flags) } } -static void clear_tsin(struct ngene_channel *chan) -{ - struct SBufferHeader *Cur = chan->nextBuffer; - - do { - memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); - Cur = Cur->Next; - } while (Cur != chan->nextBuffer); -} static void flush_buffers(struct ngene_channel *chan) { @@ -952,37 +943,6 @@ done: } -static int ngene_i2c_algo_control(struct i2c_adapter *adap, - unsigned int cmd, unsigned long arg) -{ - struct ngene_channel *chan = - (struct ngene_channel *)i2c_get_adapdata(adap); - - switch (cmd) { - case IOCTL_MIC_TUN_RDY: - chan->tun_rdy = 1; - if (chan->dec_rdy == 1) - chan->tun_dec_rdy = 1; - break; - - case IOCTL_MIC_DEC_RDY: - chan->dec_rdy = 1; - if (chan->tun_rdy == 1) - chan->tun_dec_rdy = 1; - break; - - case IOCTL_MIC_TUN_DETECT: - { - int *palorbtsc = (int *)arg; - *palorbtsc = chan->dev->card_info->ntsc; - break; - } - - default: - break; - } - return 0; -} static u32 ngene_i2c_functionality(struct i2c_adapter *adap) { @@ -994,16 +954,6 @@ struct i2c_algorithm ngene_i2c_algo = { .functionality = ngene_i2c_functionality, }; -static int ngene_i2c_attach(struct i2c_client *client) -{ - return 0; -} - -static int ngene_i2c_detach(struct i2c_client *client) -{ - return 0; -} - static int ngene_i2c_init(struct ngene *dev, int dev_nr) { struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); @@ -1018,8 +968,6 @@ static int ngene_i2c_init(struct ngene *dev, int dev_nr) strcpy(adap->name, "nGene"); adap->id = I2C_HW_SAA7146; - adap->client_register = ngene_i2c_attach; - adap->client_unregister = ngene_i2c_detach; adap->algo = &ngene_i2c_algo; adap->algo_data = (void *)&(dev->channel[dev_nr]); @@ -1040,20 +988,6 @@ int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) return 0; } -static int i2c_write_register(struct i2c_adapter *adapter, - u8 adr, u8 reg, u8 data) -{ - u8 m[2] = {reg, data}; - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; - - if (i2c_transfer(adapter, &msg, 1) != 1) { - printk(KERN_ERR DEVICE_NAME - ": Failed to write to I2C register %02x@%02x!\n", - reg, adr); - return -1; - } - return 0; -} static int i2c_write_read(struct i2c_adapter *adapter, u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) @@ -1143,146 +1077,6 @@ static int i2c_read_eeprom(struct i2c_adapter *adapter, return 0; } -static int ReadEEProm(struct i2c_adapter *adapter, - u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) -{ - int status = 0; - u16 Addr = MICNG_EE_START, Length, tag = 0; - u8 EETag[3]; - - while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { - if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) - return -1; - tag = (EETag[0] << 8) | EETag[1]; - if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) - return -1; - if (tag == Tag) - break; - Addr += sizeof(u16) + 1 + EETag[2]; - } - if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { - printk(KERN_ERR DEVICE_NAME - ": Reached EOEE @ Tag = %04x Length = %3d\n", - tag, EETag[2]); - return -1; - } - Length = EETag[2]; - if (Length > MaxLen) - Length = (u16) MaxLen; - if (Length > 0) { - Addr += sizeof(u16) + 1; - status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); - if (!status) { - *pLength = EETag[2]; - if (Length < EETag[2]) - ; /*status=STATUS_BUFFER_OVERFLOW; */ - } - } - return status; -} - -static int WriteEEProm(struct i2c_adapter *adapter, - u16 Tag, u32 Length, u8 *data) -{ - int status = 0; - u16 Addr = MICNG_EE_START; - u8 EETag[3]; - u16 tag = 0; - int retry, i; - - while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { - if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) - return -1; - tag = (EETag[0] << 8) | EETag[1]; - if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) - return -1; - if (tag == Tag) - break; - Addr += sizeof(u16) + 1 + EETag[2]; - } - if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { - printk(KERN_ERR DEVICE_NAME - ": Reached EOEE @ Tag = %04x Length = %3d\n", - tag, EETag[2]); - return -1; - } - - if (Length > EETag[2]) - return -EINVAL; - /* Note: We write the data one byte at a time to avoid - issues with page sizes. (which are different for - each manufacture and eeprom size) - */ - Addr += sizeof(u16) + 1; - for (i = 0; i < Length; i++, Addr++) { - status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); - - if (status) - break; - - /* Poll for finishing write cycle */ - retry = 10; - while (retry) { - u8 Tmp; - - msleep(50); - status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); - if (status) - break; - if (Tmp != data[i]) - printk(KERN_ERR DEVICE_NAME - "eeprom write error\n"); - retry -= 1; - } - if (status) { - printk(KERN_ERR DEVICE_NAME - ": Timeout polling eeprom\n"); - break; - } - } - return status; -} - -static void i2c_init_eeprom(struct i2c_adapter *adapter) -{ - u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, - 0x10, 0x01, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00}; - - int i; - - for (i = 0; i < sizeof(tags); i++) - i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); -} - -static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) -{ - int stat; - u8 buf[2]; - u32 len = 0; - - stat = ReadEEProm(adapter, tag, 2, buf, &len); - if (stat) - return stat; - if (len != 2) - return -EINVAL; - - *data = (buf[0] << 8) | buf[1]; - return 0; -} - -static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) -{ - int stat; - u8 buf[2]; - - buf[0] = data >> 8; - buf[1] = data & 0xff; - stat = WriteEEProm(adapter, tag, 2, buf); - if (stat) - return stat; - return 0; -} static int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) { @@ -1665,36 +1459,6 @@ static void swap_buffer(u32 *p, u32 len) } } -static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -{ - struct ngene_channel *chan = priv; - struct ngene *dev = chan->dev; - - if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { - dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); - wake_up_interruptible(&dev->ain_rbuf.queue); - } else - printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); - - return 0; -} - -static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -{ - - struct ngene_channel *chan = priv; - struct ngene *dev = chan->dev; - - if (len >= 1920 * 1080) - len = 1920 * 1080; - if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { - dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); - wake_up_interruptible(&dev->vin_rbuf.queue); - } else { - ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ - } - return 0; -} static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) { @@ -1728,15 +1492,6 @@ static void *tsout_exchange(void *priv, void *buf, u32 len, return buf; } -static void set_dto(struct ngene_channel *chan, u32 rate) -{ - u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ - - val = ((val >> 25) + 1) >> 1; - chan->AudioDTOValue = (u32) val; - /* chan->AudioDTOUpdated=1; */ - /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ -} static void set_transfer(struct ngene_channel *chan, int state) { @@ -1814,6 +1569,7 @@ static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct ngene_channel *chan = dvbdmx->priv; +#ifdef NGENE_COMMAND_API struct ngene *dev = chan->dev; if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { @@ -1838,6 +1594,7 @@ static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) } } +#endif if (chan->users == 0) { set_transfer(chan, 1); @@ -1851,6 +1608,7 @@ static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct ngene_channel *chan = dvbdmx->priv; +#ifdef NGENE_COMMAND_API struct ngene *dev = chan->dev; if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { @@ -1870,6 +1628,7 @@ static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) } } +#endif if (--chan->users) return chan->users; @@ -1879,186 +1638,7 @@ static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) return 0; } -static int write_demod(struct i2c_adapter *adapter, u8 adr, u16 reg, u16 data) -{ - u8 mm[5] = { 0x10, (reg >> 8) & 0xff, reg & 0xff, - (data >> 8) & 0xff, data & 0xff}; - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = mm, .len = 5 }; - - if (i2c_transfer(adapter, &msg, 1) != 1) { - printk(KERN_ERR DEVICE_NAME ": error in write_demod\n"); - return -1; - } - return 0; -} - - -static int ngene_drxd_pll_set(struct ngene_channel *chan, - u8 *pll, u8 *aux, u8 plladr) -{ - struct i2c_adapter *adap = &chan->i2c_adapter; - struct i2c_msg msg_pll = {.addr = plladr, .flags = 0, .buf = pll, - .len = 4}; - struct i2c_msg msg_aux = {.addr = plladr, .flags = 0, .buf = aux, - .len = 2}; - int err = 0; - - if (chan->dev->card_info->i2c_access & 1) - down(&chan->dev->pll_mutex); - - chan->fe->ops.i2c_gate_ctrl(chan->fe, 1); - err = i2c_transfer(adap, &msg_pll, 1); - if (err != 1) - goto error; - if (aux) - err = i2c_transfer(adap, &msg_aux, 1); -error: - chan->fe->ops.i2c_gate_ctrl(chan->fe, 0); - if (chan->dev->card_info->i2c_access & 1) - up(&chan->dev->pll_mutex); - return err; -} - -static int ngene_pll_set_th_dtt7520x(void *priv, void *priv_params, - u8 plladr, u8 dadr, s32 *off) -{ - struct dvb_frontend_parameters *params = priv_params; - struct ngene_channel *chan = priv; - - u32 freq = params->frequency; - u8 pll[4], aux[2]; - u8 c1, c2; - u32 div; - - if (freq < 185000000 || freq > 900000000) - return -EINVAL; - - if (freq < 465000000) - c2 = 0x12; - else - c2 = 0x18; - - if (freq < 305000000) - c1 = 0xb4; - else if (freq < 405000000) - c1 = 0xbc; - else if (freq < 445000000) - c1 = 0xf4; - else if (freq < 465000000) - c1 = 0xfc; - else if (freq < 735000000) - c1 = 0xbc; - else if (freq < 835000000) - c1 = 0xf4; - else - c1 = 0xfc; - - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) - c2 ^= 0x10; - - div = (freq + 36000000 + 166667 / 2) / 166667; - *off = ((s32) div) * 166667 - (s32) freq - 36000000; - - pll[0] = (div >> 8) & 0x7f; - pll[1] = div & 0xff; - pll[2] = c1; - pll[3] = c2; - - aux[0] = (c1 & 0xc7) | 0x98; - aux[1] = 0x30; - - return ngene_drxd_pll_set(chan, pll, aux, plladr); -} - -static int ngene_pll_set_mt_3x0823(void *priv, - void *priv_params, - u8 plladr, u8 dadr, s32 *off) -{ - struct dvb_frontend_parameters *params = priv_params; - struct ngene_channel *chan = priv; - struct i2c_adapter *adap = &chan->i2c_adapter; - u32 freq = params->frequency; - u8 pll[4]; - u8 aux[2]; - u8 c1, c2; - u32 div; - - if (freq < 47125000 || freq > 855250000) - return -EINVAL; - else if (freq < 120000000) { - c1 = 0xcc; - c2 = 0x01; - } else if (freq < 155500000) { - c1 = 0xfc; - c2 = 0x01; - } else if (freq < 300000000) { - c1 = 0xbc; - c2 = 0x02; - } else if (freq < 467000000) { - c1 = 0xcc; - c2 = 0x02; - } else { - c1 = 0xcc; - c2 = 0x04; - } - - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) - c2 |= 0x08; - -#define INTERFREQ (36000000) - - div = (freq + INTERFREQ + 166667 / 2) / 166667; - - *off = ((s32) div) * 166667 - (s32) freq - INTERFREQ; - - pll[0] = (div >> 8) & 0x7f; - pll[1] = div & 0xff; - pll[2] = c1; - pll[3] = c2; - - aux[0] = (c1 & 0xc7) | 0x98; - aux[1] = 0x20; - - write_demod(adap, dadr, 0x1007, 0xc27); - - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_7_MHZ: - write_demod(adap, dadr, 0x0020, 0x103); - break; - case BANDWIDTH_AUTO: - case BANDWIDTH_8_MHZ: - write_demod(adap, dadr, 0x0020, 0x003); - break; - case BANDWIDTH_6_MHZ: - write_demod(adap, dadr, 0x0020, 0x002); - /*write_demod(adap, dadr, 0x1022, 397);*/ - break; - } - - return ngene_drxd_pll_set(chan, pll, aux, plladr); - -} - -static s16 osc_deviation(void *priv, s16 deviation, int flag) -{ - struct ngene_channel *chan = priv; - struct i2c_adapter *adap = &chan->i2c_adapter; - u16 data = 0; - - if (flag) { - data = (u16) deviation; - printk(KERN_INFO DEVICE_NAME ": write deviation %d\n", - deviation); - eeprom_write_ushort(adap, 0x1000 + chan->number, data); - } else { - if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) - data = 0; - printk(KERN_INFO DEVICE_NAME ": read deviation %d\n", - (s16) data); - } - return (s16) data; -} static int write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) @@ -2175,8 +1755,6 @@ int dec_fw_boot(struct ngene *dev) u32 size; const struct firmware *fw = NULL; u8 *dec_fw; - char *fw_name; - int err, version; if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { printk(KERN_ERR DEVICE_NAME @@ -2188,7 +1766,7 @@ int dec_fw_boot(struct ngene *dev) DECYPHER_FW); size = fw->size; - dec_fw = fw->data; + dec_fw = (u8 *)fw->data; dec_fw_send(dev, dec_fw, size); release_firmware(fw); return 0; @@ -2487,83 +2065,6 @@ static u32 Buffer2Sizes[MAX_STREAM] = { 0 }; -static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, - struct SRingBufferDescriptor *rbuf, - u32 entries, u32 size1, u32 size2) -{ - if (create_ring_buffer(pci_dev, rbuf, entries) < 0) - return -ENOMEM; - - if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) - return -ENOMEM; - - return 0; -} - -static int channel_allocate_buffers(struct ngene_channel *chan) -{ - struct ngene *dev = chan->dev; - int type = dev->card_info->io_type[chan->number]; - int status; - - chan->State = KSSTATE_STOP; - - if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { - status = create_ring_buffer(dev->pci_dev, - &chan->RingBuffer, - RingBufferSizes[chan->number]); - if (status < 0) - return -ENOMEM; - - if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { - status = AllocateRingBuffers(dev->pci_dev, - dev->PAOverflowBuffer, - &chan->RingBuffer, - Buffer1Sizes[chan->number], - Buffer2Sizes[chan-> - number]); - if (status < 0) - return -ENOMEM; - } else if (type & NGENE_IO_HDTV) { - status = AllocateRingBuffers(dev->pci_dev, - dev->PAOverflowBuffer, - &chan->RingBuffer, - MAX_HDTV_BUFFER_SIZE, 0); - if (status < 0) - return -ENOMEM; - } - } - - if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { - - status = create_ring_buffer(dev->pci_dev, - &chan->TSRingBuffer, RING_SIZE_TS); - if (status < 0) - return -ENOMEM; - - status = AllocateRingBuffers(dev->pci_dev, - dev->PAOverflowBuffer, - &chan->TSRingBuffer, - MAX_TS_BUFFER_SIZE, 0); - if (status) - return -ENOMEM; - } - - if (type & NGENE_IO_TSOUT) { - status = create_ring_buffer(dev->pci_dev, - &chan->TSIdleBuffer, 1); - if (status < 0) - return -ENOMEM; - status = AllocateRingBuffers(dev->pci_dev, - dev->PAOverflowBuffer, - &chan->TSIdleBuffer, - MAX_TS_BUFFER_SIZE, 0); - if (status) - return -ENOMEM; - FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); - } - return 0; -} static int AllocCommonBuffers(struct ngene *dev) { @@ -2737,18 +2238,12 @@ static int ngene_load_firm(struct ngene *dev) default: case 15: version = 15; - ngene_fw = FW15; - size = sizeof(FW15); fw_name = "ngene_15.fw"; break; case 16: - ngene_fw = FW16; - size = sizeof(FW16); fw_name = "ngene_16.fw"; break; case 17: - ngene_fw = FW17; - size = sizeof(FW17); fw_name = "ngene_17.fw"; break; } @@ -2776,7 +2271,7 @@ static int ngene_load_firm(struct ngene *dev) } printk(KERN_INFO DEVICE_NAME ": Loading firmware file %s.\n", fw_name); size = fw->size; - ngene_fw = fw->data; + ngene_fw = (u8 *) fw->data; err = ngene_command_load_firmware(dev, ngene_fw, size); release_firmware(fw); #endif @@ -2843,9 +2338,6 @@ static int ngene_start(struct ngene *dev) {6144 / 64, 0, 0, 2048 / 64, 2048 / 64, 2048 / 64}; u8 tsin4_config[6] = {3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; - u8 ts5_config[6] = - {2048 / 64, 2048 / 64, 0, 2048 / 64, 2048 / 64, - 2048 / 64}; u8 default_config[6] = {4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0}; u8 *bconf = default_config; @@ -2883,546 +2375,23 @@ fail: return stat; } + + /****************************************************************************/ -/* DVB audio/video device functions *****************************************/ +/* Switch control (I2C gates, etc.) *****************************************/ /****************************************************************************/ -static ssize_t audio_write(struct file *file, - const char *buf, size_t count, loff_t *ppos) -{ - return -EINVAL; -} -ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - int left; - int avail; +/****************************************************************************/ +/* Demod/tuner attachment ***************************************************/ +/****************************************************************************/ - left = count; - while (left) { - if (wait_event_interruptible( - dev->ain_rbuf.queue, - dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) - return -EAGAIN; - avail = dvb_ringbuffer_avail(&dev->ain_rbuf); - if (avail > left) - avail = left; - dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); - left -= avail; - buf += avail; - } - return count; -} -static int audio_open(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - struct ngene_channel *chan2 = &chan->dev->channel[2]; - int ret; - - ret = dvb_generic_open(inode, file); - if (ret < 0) - return ret; - my_dvb_ringbuffer_flush(&dev->ain_rbuf); - - chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; - chan2->pBufferExchange = ain_exchange; - ngene_command_stream_control(chan2->dev, chan2->number, 0x80, - SMODE_AUDIO_CAPTURE, 0); - return ret; -} - -static int audio_release(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - struct ngene_channel *chan2 = &chan->dev->channel[2]; - - ngene_command_stream_control(dev, 2, 0, 0, 0); - chan2->pBufferExchange = 0; - - return dvb_generic_release(inode, file); -} - -static const struct file_operations audio_fops = { - .owner = THIS_MODULE, - .read = audio_read, - .write = audio_write, - .open = audio_open, - .release = audio_release, -}; - -static struct dvb_device dvbdev_audio = { - .priv = 0, - .readers = -1, - .writers = 1, - .users = 1, - .fops = &audio_fops, -}; - -static int video_open(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - struct ngene_channel *chan0 = &chan->dev->channel[0]; - int ret; - - ret = dvb_generic_open(inode, file); - if (ret < 0) - return ret; - if ((file->f_flags & O_ACCMODE) != O_RDONLY) - return ret; - my_dvb_ringbuffer_flush(&dev->vin_rbuf); - - chan0->nBytesPerLine = 1920 * 2; - chan0->nLines = 540; - chan0->Capture1Length = 1920 * 2 * 540; - chan0->pBufferExchange = vcap_exchange; - chan0->itumode = 2; - ngene_command_stream_control(chan0->dev, chan0->number, - 0x80, SMODE_VIDEO_CAPTURE, 0); - return ret; -} - -static int video_release(struct inode *inode, struct file *file) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - struct ngene_channel *chan0 = &chan->dev->channel[0]; - - ngene_command_stream_control(dev, 0, 0, 0, 0); - chan0->pBufferExchange = 0; - - return dvb_generic_release(inode, file); -} - -static ssize_t video_write(struct file *file, - const char *buf, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - int left, avail; - - left = count; - while (left) { - if (wait_event_interruptible( - dev->vin_rbuf.queue, - dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) - return -EAGAIN; - avail = dvb_ringbuffer_avail(&dev->vin_rbuf); - if (avail > left) - avail = left; - dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); - left -= avail; - buf += avail; - } - return count; -} - -/* Why is this not exported from dvb_core ?!?! */ - -static int dvb_usercopy2(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - /* - * For this command, the pointer is actually an integer - * argument. - */ - parg = (void *)arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - err = func(inode, file, cmd, parg); - if (err == -ENOIOCTLCMD) - err = -EINVAL; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - kfree(mbuf); - return err; -} - -static int video_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *parg) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - int ret = 0; - unsigned long arg = (unsigned long)parg; - - switch (cmd) { - case VIDEO_SET_STREAMTYPE: - switch (arg) { - case VIDEO_CAP_MPEG2: - /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ - send_cli(dev, "vdec mpeg2\n"); - break; - case VIDEO_CAP_AVC: - /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ - send_cli(dev, "vdec h264\n"); - break; - case VIDEO_CAP_VC1: - /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ - send_cli(dev, "vdec vc1\n"); - break; - default: - ret = -EINVAL; - break; - } - break; - default: - ret = -ENOIOCTLCMD; - return -EINVAL; - } - return ret; -} - -static int video_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); -} - -static const struct file_operations video_fops = { - .owner = THIS_MODULE, - .read = video_read, - .write = video_write, - .open = video_open, - .release = video_release, - .ioctl = video_ioctl, -}; - -static struct dvb_device dvbdev_video = { - .priv = 0, - .readers = -1, - .writers = 1, - .users = -1, - .fops = &video_fops, -}; - -/****************************************************************************/ -/* LNBH21 *******************************************************************/ -/****************************************************************************/ - -static int lnbh21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -{ - struct ngene_channel *chan = - *(struct ngene_channel **) fe->demodulator_priv; - - switch (voltage) { - case SEC_VOLTAGE_OFF: - chan->lnbh &= 0xf3; - break; - case SEC_VOLTAGE_13: - chan->lnbh |= 0x04; - chan->lnbh &= ~0x08; - break; - case SEC_VOLTAGE_18: - chan->lnbh |= 0x0c; - break; - default: - return -EINVAL; - }; - chan->lnbh |= 0x10; - return i2c_write(&chan->i2c_adapter, - chan->dev->card_info->lnb[chan->number], chan->lnbh); -} - -static int lnbh21_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) -{ - struct ngene_channel *chan = - *(struct ngene_channel **)fe->demodulator_priv; - - switch (tone) { - case SEC_TONE_ON: - chan->lnbh |= 0x20; - break; - case SEC_TONE_OFF: - chan->lnbh &= 0xdf; - break; - default: - return -EINVAL; - } - return i2c_write(&chan->i2c_adapter, - chan->dev->card_info->lnb[chan->number], chan->lnbh); -} - -/****************************************************************************/ -/* Switch control (I2C gates, etc.) *****************************************/ -/****************************************************************************/ - -static int avf_output(struct ngene_channel *chan, int state) -{ - if (chan->dev->card_info->avf[chan->number]) - i2c_write_register(&chan->i2c_adapter, - chan->dev->card_info->avf[chan->number], - 0xf2, state ? 0x89 : 0x80); - return 0; -} - -/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ - -static int exp_set(struct ngene *dev) -{ - return i2c_write(&dev->channel[0].i2c_adapter, - dev->card_info->exp, dev->exp_val); -} - -static int exp_init(struct ngene *dev) -{ - if (!dev->card_info->exp) - return 0; - dev->exp_val = dev->card_info->exp_init; - return exp_set(dev); -} - -static int exp_set_bit(struct ngene *dev, int bit, int val) -{ - if (val) - set_bit(bit, &dev->exp_val); - else - clear_bit(bit, &dev->exp_val); - return exp_set(dev); -} - -static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) -{ - switch (type) { - case 0: /* I2C tuner gate on/off */ - return exp_set_bit(chan->dev, 4 + chan->number, val); - case 1: /* Stream: 0=TS 1=ITU */ - avf_output(chan, val); - return exp_set_bit(chan->dev, 6 + chan->number, val); - case 2: /* Input: 0=digital 1=analog antenna input */ - exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); - exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); - break; - } - return 0; -} - -static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) -{ - switch (type) { - case 0: /* I2C tuner gate on/off */ - return exp_set_bit(chan->dev, 4 + chan->number, val); - case 1: /* Stream: 0=TS 1=ITU */ - avf_output(chan, val); - return exp_set_bit(chan->dev, 6 + chan->number, val); - case 2: /* Input: 0=digital 1=analog antenna input */ - exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); - exp_set_bit(chan->dev, 1 + chan->number * 2, 0); - break; - } - return 0; -} - -static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - /* Well, just abuse sec :-) */ - struct ngene_channel *chan = fe->sec_priv; - struct ngene *dev = chan->dev; - - return dev->card_info->switch_ctrl(chan, 0, enable); -} - -static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) -{ - switch (type) { - case 0: /* I2C tuner gate on/off */ - if (chan->number > 1) - return -EINVAL; - return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); - case 1: /* Stream: 0=TS 1=ITU */ - avf_output(chan, val); - return 0; - } - return 0; -} - -static int viper_reset_xc(struct dvb_frontend *fe) -{ - struct ngene_channel *chan = fe->sec_priv; - struct ngene *dev = chan->dev; - - printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); - - if (chan->number > 1) - return -EINVAL; - - ngene_command_gpio_set(dev, 3 + chan->number, 0); - msleep(150); - ngene_command_gpio_set(dev, 3 + chan->number, 1); - return 0; -} - -static int python_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - struct ngene_channel *chan = fe->sec_priv; - struct ngene *dev = chan->dev; - - if (chan->number == 0) - return ngene_command_gpio_set(dev, 3, enable); - if (chan->number == 1) - return ngene_command_gpio_set(dev, 4, enable); - return -EINVAL; -} - -/****************************************************************************/ -/* Demod/tuner attachment ***************************************************/ -/****************************************************************************/ - -static int tuner_attach_mt2060(struct ngene_channel *chan) -{ - struct ngene *dev = chan->dev; - void *tconf = dev->card_info->tuner_config[chan->number]; - u8 drxa = dev->card_info->demoda[chan->number]; - struct dvb_frontend *fe = chan->fe, *fe2; - - fe->sec_priv = chan; - fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; - - dev->card_info->gate_ctrl(fe, 1); - fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); - dev->card_info->gate_ctrl(fe, 0); - - i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); - write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); - write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); - write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); - - return fe2 ? 0 : -ENODEV; -} - -static int tuner_attach_xc3028(struct ngene_channel *chan) -{ - struct ngene *dev = chan->dev; - void *tconf = dev->card_info->tuner_config[chan->number]; - struct dvb_frontend *fe = chan->fe, *fe2; - - fe->sec_priv = chan; - fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; - - dev->card_info->gate_ctrl(fe, 1); - fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); - dev->card_info->gate_ctrl(fe, 0); - - /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ - - return fe2 ? 0 : -ENODEV; -} - -static int demod_attach_drxd(struct ngene_channel *chan) -{ - void *feconf = chan->dev->card_info->fe_config[chan->number]; - - chan->fe = drxd_attach(feconf, - chan, &chan->i2c_adapter, - &chan->dev->pci_dev->dev); - return (chan->fe) ? 0 : -ENODEV; -} - -static int demod_attach_drxh(struct ngene_channel *chan) -{ - void *feconf = chan->dev->card_info->fe_config[chan->number]; - - chan->fe = drxh_attach(feconf, chan, - &chan->i2c_adapter, &chan->dev->pci_dev->dev); - return (chan->fe) ? 0 : -ENODEV; -} - -static int demod_attach_stb0899(struct ngene_channel *chan) -{ - void *feconf = chan->dev->card_info->fe_config[chan->number]; - - chan->fe = stb0899_attach(feconf, - chan, &chan->i2c_adapter, - &chan->dev->pci_dev->dev); - if (chan->fe) { - chan->set_tone = chan->fe->ops.set_tone; - chan->fe->ops.set_tone = lnbh21_set_tone; - chan->fe->ops.set_voltage = lnbh21_set_voltage; - } - - return (chan->fe) ? 0 : -ENODEV; -} - -static int demod_attach_stv0900(struct ngene_channel *chan) -{ - void *feconf = chan->dev->card_info->fe_config[chan->number]; - - chan->fe = stv0900_attach(feconf, - chan, &chan->i2c_adapter, - &chan->dev->pci_dev->dev); - - if (chan->fe) { - chan->set_tone = chan->fe->ops.set_tone; - chan->fe->ops.set_tone = lnbh21_set_tone; - chan->fe->ops.set_voltage = lnbh21_set_voltage; - } - - return (chan->fe) ? 0 : -ENODEV; -} - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -static void release_channel(struct ngene_channel *chan) +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +static void release_channel(struct ngene_channel *chan) { struct dvb_demux *dvbdemux = &chan->demux; struct ngene *dev = chan->dev; @@ -3436,10 +2405,6 @@ static void release_channel(struct ngene_channel *chan) if (chan->command_dev) dvb_unregister_device(chan->command_dev); #endif - if (chan->audio_dev) - dvb_unregister_device(chan->audio_dev); - if (chan->video_dev) - dvb_unregister_device(chan->video_dev); if (chan->fe) { dvb_unregister_frontend(chan->fe); /*dvb_frontend_detach(chan->fe); */ @@ -3457,10 +2422,6 @@ static void release_channel(struct ngene_channel *chan) #endif } - if (io & (NGENE_IO_AIN)) { - ngene_snd_exit(chan); - kfree(chan->soundbuffer); - } } static int init_channel(struct ngene_channel *chan) @@ -3502,13 +2463,6 @@ static int init_channel(struct ngene_channel *chan) &chan->mem_frontend, adapter); if (io & NGENE_IO_TSOUT) { dvbdemux->write_to_decoder = write_to_decoder; - dvb_register_device(adapter, &chan->audio_dev, - &dvbdev_audio, (void *)chan, - DVB_DEVICE_AUDIO); - dvb_register_device(adapter, &chan->video_dev, - &dvbdev_video, (void *)chan, - DVB_DEVICE_VIDEO); - } #ifdef NGENE_COMMAND_API dvb_register_device(adapter, &chan->command_dev, @@ -3536,19 +2490,6 @@ static int init_channel(struct ngene_channel *chan) } } - if (io & (NGENE_IO_AIN)) { - ngene_snd_init(chan); -#ifdef NGENE_V4L - spin_lock_init(&chan->s_lock); - init_MUTEX(&chan->reslock); - INIT_LIST_HEAD(&chan->capture); -#endif - - chan->soundbuffer = kmalloc(MAX_AUDIO_BUFFER_SIZE, GFP_KERNEL); - if (!chan->soundbuffer) - return -ENOMEM; - memset(chan->soundbuffer, 0, MAX_AUDIO_BUFFER_SIZE); - } return ret; } @@ -3616,8 +2557,6 @@ static int __devinit ngene_probe(struct pci_dev *pci_dev, goto fail1; dev->i2c_current_bus = -1; - exp_init(dev); - /* Disable analog TV decoder chips if present */ if (copy_eeprom) { i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); @@ -3648,321 +2587,6 @@ fail1: /* Card configs *************************************************************/ /****************************************************************************/ -static struct drxd_config fe_terratec_dvbt_0 = { - .index = 0, - .demod_address = 0x70, - .demod_revision = 0xa2, - .demoda_address = 0x00, - .pll_address = 0x60, - .pll_type = DRXD_PLL_DTT7520X, - .clock = 20000, - .pll_set = ngene_pll_set_th_dtt7520x, - .osc_deviation = osc_deviation, -}; - -static struct drxd_config fe_terratec_dvbt_1 = { - .index = 1, - .demod_address = 0x71, - .demod_revision = 0xa2, - .demoda_address = 0x00, - .pll_address = 0x60, - .pll_type = DRXD_PLL_DTT7520X, - .clock = 20000, - .pll_set = ngene_pll_set_th_dtt7520x, - .osc_deviation = osc_deviation, -}; - -static struct ngene_info ngene_info_terratec = { - .type = NGENE_TERRATEC, - .name = "Terratec Integra/Cinergy2400i Dual DVB-T", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_drxd, demod_attach_drxd}, - .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, - .i2c_access = 1, -}; - -/****************************************************************************/ - -static struct mt2060_config tuner_python_0 = { - .i2c_address = 0x60, - .clock_out = 3, - .input = 0 -}; - -static struct mt2060_config tuner_python_1 = { - .i2c_address = 0x61, - .clock_out = 3, - .input = 1 -}; - -static struct drxd_config fe_python_0 = { - .index = 0, - .demod_address = 0x71, - .demod_revision = 0xb1, - .demoda_address = 0x41, - .clock = 16000, - .osc_deviation = osc_deviation, -}; - -static struct drxd_config fe_python_1 = { - .index = 1, - .demod_address = 0x70, - .demod_revision = 0xb1, - .demoda_address = 0x45, - .clock = 16000, - .osc_deviation = osc_deviation, -}; - -static struct ngene_info ngene_info_python = { - .type = NGENE_PYTHON, - .name = "Micronas MicPython/Hedgehog Dual DVB-T", - .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_AIN, NGENE_IO_AIN}, - .demod_attach = {demod_attach_drxd, demod_attach_drxd}, - .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, - .fe_config = {&fe_python_0, &fe_python_1}, - .tuner_config = {&tuner_python_0, &tuner_python_1}, - .avf = {0x43, 0x47}, - .msp = {0x40, 0x42}, - .demoda = {0x41, 0x45}, - .gate_ctrl = python_gate_ctrl, - .switch_ctrl = python_switch_ctrl, -}; - -/****************************************************************************/ - -static struct drxd_config fe_appb_dvbt_0 = { - .index = 0, - .demod_address = 0x71, - .demod_revision = 0xa2, - .demoda_address = 0x41, - .pll_address = 0x63, - .pll_type = DRXD_PLL_MT3X0823, - .clock = 20000, - .pll_set = ngene_pll_set_mt_3x0823, - .osc_deviation = osc_deviation, -}; - -static struct drxd_config fe_appb_dvbt_1 = { - .index = 1, - .demod_address = 0x70, - .demod_revision = 0xa2, - .demoda_address = 0x45, - .pll_address = 0x60, - .pll_type = DRXD_PLL_MT3X0823, - .clock = 20000, - .pll_set = ngene_pll_set_mt_3x0823, - .osc_deviation = osc_deviation, -}; - -static struct ngene_info ngene_info_appboard = { - .type = NGENE_APP, - .name = "Micronas Application Board Dual DVB-T", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_drxd, demod_attach_drxd}, - .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, - .avf = {0x43, 0x47}, -}; - -static struct ngene_info ngene_info_appboard_ntsc = { - .type = NGENE_APP, - .name = "Micronas Application Board Dual DVB-T", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_drxd, demod_attach_drxd}, - .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, - .avf = {0x43, 0x47}, - .ntsc = 1, -}; - -/****************************************************************************/ - -static struct stb0899_config fe_sidewinder_0 = { - .demod_address = 0x68, - .pll_address = 0x63, -}; - -static struct stb0899_config fe_sidewinder_1 = { - .demod_address = 0x6b, - .pll_address = 0x60, -}; - -static struct ngene_info ngene_info_sidewinder = { - .type = NGENE_SIDEWINDER, - .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, - .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, - .lnb = {0x0b, 0x08}, -}; - -/****************************************************************************/ -/* Yet unnamed S2 card with dual DVB-S2 demod */ -/****************************************************************************/ - -static struct stv0900_config fe_s2_0 = { - .addr = 0x68, - .pll = 0x63, - .pll_type = 0, - .nr = 0, -}; - -static struct stv0900_config fe_s2_1 = { - .addr = 0x68, - .pll = 0x60, - .pll_type = 0, - .nr = 1, -}; - -static struct ngene_info ngene_info_s2 = { - .type = NGENE_SIDEWINDER, - .name = "S2", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, - NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, - .fe_config = {&fe_s2_0, &fe_s2_1}, - .lnb = {0x0b, 0x08}, - .tsf = {3, 3}, - .fw_version = 15, -}; - -static struct stv0900_config fe_s2b_0 = { - .addr = 0x68, - .pll = 0x60, - .pll_type = 0x10, - .nr = 0, -}; - -static struct stv0900_config fe_s2b_1 = { - .addr = 0x68, - .pll = 0x63, - .pll_type = 0x10, - .nr = 1, -}; - -static struct ngene_info ngene_info_s2_b = { - .type = NGENE_SIDEWINDER, - .name = "S2 V2", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, - NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, - .fe_config = {&fe_s2b_0, &fe_s2b_1}, - .lnb = {0x0b, 0x08}, - .tsf = {3, 3}, - .fw_version = 17, -}; - -/****************************************************************************/ - -static struct xc3028_config tuner_viper_0 = { - .adr = 0x61, - .reset = viper_reset_xc -}; - -static struct xc3028_config tuner_viper_1 = { - .adr = 0x64, - .reset = viper_reset_xc -}; - -static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; - -static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; - -static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; - -static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; - -static struct ngene_info ngene_info_viper_v1 = { - .type = NGENE_VIPER, - .name = "Micronas MicViper Dual ATSC DRXH", - .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_AIN, NGENE_IO_AIN}, - .demod_attach = {demod_attach_drxh, demod_attach_drxh}, - .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, - .tuner_config = {&tuner_viper_0, &tuner_viper_1}, - .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, - .avf = {0x43, 0x47}, - .msp = {0x40, 0x42}, - .exp = 0x20, - .exp_init = 0xf5, - .gate_ctrl = viper_gate_ctrl, - .switch_ctrl = viper_switch_ctrl, - .tsf = {2, 2}, -}; - -static struct ngene_info ngene_info_viper_v2 = { - .type = NGENE_VIPER, - .name = "Micronas MicViper Dual ATSC DRXL", - .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_AIN, NGENE_IO_AIN}, - .demod_attach = {demod_attach_drxh, demod_attach_drxh}, - .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, - .tuner_config = {&tuner_viper_0, &tuner_viper_1}, - .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, - .avf = {0x43, 0x47}, - .msp = {0x40, 0x42}, - .exp = 0x38, - .exp_init = 0xf5, - .gate_ctrl = viper_gate_ctrl, - .switch_ctrl = viper_switch_ctrl, - .tsf = {2, 2}, -}; - -/****************************************************************************/ - -static struct ngene_info ngene_info_vbox_v1 = { - .type = NGENE_VBOX_V1, - .name = "VBox Cat's Eye 164E", - .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_AIN, NGENE_IO_AIN}, - .demod_attach = {demod_attach_drxh, demod_attach_drxh}, - .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, - .tuner_config = {&tuner_viper_0, &tuner_viper_1}, - .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, - .avf = {0x43, 0x47}, - .msp = {0x40, 0x42}, - .exp = 0x20, - .exp_init = 0xf5, - .gate_ctrl = viper_gate_ctrl, - .switch_ctrl = viper_switch_ctrl, - .tsf = {2, 2}, -}; - -/****************************************************************************/ - -static struct ngene_info ngene_info_vbox_v2 = { - .type = NGENE_VBOX_V2, - .name = "VBox Cat's Eye 164E", - .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_TSIN | NGENE_IO_TV, - NGENE_IO_AIN, NGENE_IO_AIN}, - .demod_attach = {demod_attach_drxh, demod_attach_drxh}, - .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, - .tuner_config = {&tuner_viper_0, &tuner_viper_1}, - .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, - .avf = {0x43, 0x47}, - .msp = {0x40, 0x42}, - .exp = 0x20, - .exp_init = 0xf5, - .gate_ctrl = viper_gate_ctrl, - .switch_ctrl = viper_switch_ctrl2, - .tsf = {2, 2}, -}; - -/****************************************************************************/ - -static struct ngene_info ngene_info_racer = { - .type = NGENE_RACER, - .name = "Micronas MicRacer HDTV Decoder Card", - .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, - NGENE_IO_AIN, NGENE_IO_NONE, - NGENE_IO_TSOUT}, - .i2s = {0, 0, 1, 0}, - .fw_version = 17, -}; /****************************************************************************/ @@ -3977,21 +2601,6 @@ static struct ngene_info ngene_info_racer = { /****************************************************************************/ static const struct pci_device_id ngene_id_tbl[] __devinitdata = { - NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), - NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), - NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), - NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), - NGENE_ID(0x153b, 0x1167, ngene_info_terratec), - NGENE_ID(0x18c3, 0x0030, ngene_info_python), - NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), - NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), - NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), - NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), - NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), - NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), - NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), - NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), - NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), {0} }; diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h index 9b48250fdbf..74c6dab220a 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/dvb/ngene/ngene.h @@ -25,8 +25,6 @@ #define _NGENE_H_ #define ONE_ADAPTER -#define NGENE_COMMAND_API -/*#define NGENE_V4L*/ #include #include @@ -34,35 +32,14 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include "dmxdev.h" #include "dvbdev.h" #include "dvb_demux.h" #include "dvb_frontend.h" #include "dvb_ringbuffer.h" -#include "drxd.h" -#include "drxh.h" -#include "xc3028.h" -#include "stb0899.h" -#include "stv0900.h" -#include "mt2060.h" - -#ifdef NGENE_V4L -#include -#include -#include -#endif #define NGENE_VID 0x18c3 #define NGENE_PID 0x0720 @@ -675,9 +652,6 @@ struct ngene_channel { #ifndef ONE_ADAPTER struct dvb_adapter dvb_adapter; #endif - struct dvb_device *command_dev; - struct dvb_device *audio_dev; - struct dvb_device *video_dev; struct tasklet_struct demux_tasklet; struct SBufferHeader *nextBuffer; @@ -715,7 +689,6 @@ struct ngene_channel { struct mychip *mychip; struct snd_card *soundcard; u8 *evenbuffer; - u8 *soundbuffer; u8 dma_on; int soundstreamon; int audiomute; @@ -887,8 +860,6 @@ struct ngene_info { u8 lnb[4]; int i2c_access; u8 ntsc; - u8 exp; - u8 exp_init; u8 tsf[4]; u8 i2s[4]; -- cgit v1.2.3 From 0027ebb73eff5bf0709f016edcad2be0605a3e4f Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sat, 19 Dec 2009 06:38:05 -0300 Subject: V4L/DVB: ngene: Always use firmware loader Always use firmware loader. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 47 ++++++++++++------------------------ 1 file changed, 16 insertions(+), 31 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index c0ef11c77f5..1fb16353708 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -48,17 +48,6 @@ #include "ngene-ioctls.h" #endif -/* #define FW_INC 1 */ -#ifdef FW_INC -#include "ngene_fw_15.h" -#include "ngene_fw_16.h" -#include "ngene_fw_17.h" - -static int load_firmware; -module_param(load_firmware, int, 0444); -MODULE_PARM_DESC(load_firmware, "Try to load firmware from file."); -#endif - static int copy_eeprom; module_param(copy_eeprom, int, 0444); MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); @@ -2238,43 +2227,39 @@ static int ngene_load_firm(struct ngene *dev) default: case 15: version = 15; + size = 23466; fw_name = "ngene_15.fw"; break; case 16: + size = 23498; fw_name = "ngene_16.fw"; break; case 17: + size = 24446; fw_name = "ngene_17.fw"; break; } -#ifdef FW_INC - if (load_firmware && - request_firmware(&fw, fw_name, &dev->pci_dev->dev) >= 0) { - printk(KERN_INFO DEVICE_NAME - ": Loading firmware file %s.\n", fw_name); - size = fw->size; - ngene_fw = fw->data; - } else - printk(KERN_INFO DEVICE_NAME - ": Loading built-in firmware version %d.\n", version); - err = ngene_command_load_firmware(dev, ngene_fw, size); - if (fw) - release_firmware(fw); -#else if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) { printk(KERN_ERR DEVICE_NAME - ": Could not load firmware file %s. \n", fw_name); + ": Could not load firmware file %s.\n", fw_name); printk(KERN_INFO DEVICE_NAME ": Copy %s to your hotplug directory!\n", fw_name); return -1; } - printk(KERN_INFO DEVICE_NAME ": Loading firmware file %s.\n", fw_name); - size = fw->size; - ngene_fw = (u8 *) fw->data; - err = ngene_command_load_firmware(dev, ngene_fw, size); + if (size != fw->size) { + printk(KERN_ERR DEVICE_NAME + ": Firmware %s has invalid size!", fw_name); + err = -1; + } else { + printk(KERN_INFO DEVICE_NAME + ": Loading firmware file %s.\n", fw_name); + ngene_fw = (u8 *) fw->data; + err = ngene_command_load_firmware(dev, ngene_fw, size); + } + release_firmware(fw); -#endif + return err; } -- cgit v1.2.3 From 6ed36e6670635b162cc59e40cdb0fbcc51d59d1e Mon Sep 17 00:00:00 2001 From: Matthias Benesch Date: Sat, 19 Dec 2009 22:18:53 -0300 Subject: V4L/DVB: ngene: Additional clean-up Remove and disable unnecessary code. Disable define ONE_ADAPTER. Signed-off-by: Matthias Benesch Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 3 ++- drivers/media/dvb/ngene/ngene.h | 39 +----------------------------------- 2 files changed, 3 insertions(+), 39 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 1fb16353708..eb47b86902f 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -2435,7 +2435,8 @@ static int init_channel(struct ngene_channel *chan) #else ret = dvb_register_adapter(&chan->dvb_adapter, "nGene", THIS_MODULE, - &chan->dev->pci_dev->dev); + &chan->dev->pci_dev->dev, + adapter_nr); if (ret < 0) return ret; adapter = &chan->dvb_adapter; diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h index 74c6dab220a..243f86c8589 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/dvb/ngene/ngene.h @@ -24,7 +24,7 @@ #ifndef _NGENE_H_ #define _NGENE_H_ -#define ONE_ADAPTER +/*#define ONE_ADAPTER*/ #include #include @@ -794,38 +794,6 @@ struct ngene { int prev_cmd; }; -struct channel_info { - int io_type; -#define NGENE_IO_NONE 0 -#define NGENE_IO_TV 1 -#define NGENE_IO_HDTV 2 -#define NGENE_IO_TSIN 4 -#define NGENE_IO_TSOUT 8 -#define NGENE_IO_AIN 16 - - void *fe_config; - void *tuner_config; - - int (*demod_attach)(struct ngene_channel *); - int demod_type; -#define NGENE_DEMOD_NONE 0 -#define NGENE_DEMOD_DRXD 1 -#define NGENE_DEMOD_STB0899 2 -#define NGENE_DEMOD_DRXH 3 - - int (*tuner_attach)(struct ngene_channel *); - int tuner_type; -#define NGENE_TUNER_NONE 0 -#define NGENE_TUNER_MT2060 1 - - u8 demod; - u8 tuner; - u8 lnb; - u8 demoda; - u8 avf; - u8 msp; -}; - struct ngene_info { int type; #define NGENE_APP 0 @@ -906,12 +874,7 @@ int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, u16 lines, u16 bpl, u16 vblines, u16 vbibpl); -int ngene_v4l2_init(struct ngene_channel *chan); -void ngene_v4l2_remove(struct ngene_channel *chan); -int ngene_snd_exit(struct ngene_channel *chan); -int ngene_snd_init(struct ngene_channel *chan); -struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); #endif -- cgit v1.2.3 From 8bba2607f1927cf3166a64dfd4e4c38a2e3af990 Mon Sep 17 00:00:00 2001 From: Matthias Benesch Date: Sat, 19 Dec 2009 12:48:22 -0300 Subject: V4L/DVB: ngene: Added Media-Pointer MP-S2/CineS2 DVB-S2 Twin Tuner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for nGene based Media-Pointer DVB-S2 twin tuner cards. [mchehab@redhat.com: Fix compilation error: unknown field ‘ref_clk’] Signed-off-by: Matthias Benesch Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 115 +++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index eb47b86902f..0e0c01396ce 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -44,6 +44,10 @@ #include "ngene.h" +#include "stv6110x.h" +#include "stv090x.h" +#include "lnbh24.h" + #ifdef NGENE_COMMAND_API #include "ngene-ioctls.h" #endif @@ -2371,6 +2375,60 @@ fail: /* Demod/tuner attachment ***************************************************/ /****************************************************************************/ +static int tuner_attach_stv6110(struct ngene_channel *chan) +{ + struct stv090x_config *feconf = (struct stv090x_config *) + chan->dev->card_info->fe_config[chan->number]; + struct stv6110x_config *tunerconf = (struct stv6110x_config *) + chan->dev->card_info->tuner_config[chan->number]; + struct stv6110x_devctl *ctl; + + ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, + &chan->i2c_adapter); + if (ctl == NULL) { + printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); + return -ENODEV; + } + + feconf->tuner_init = ctl->tuner_init; + feconf->tuner_set_mode = ctl->tuner_set_mode; + feconf->tuner_set_frequency = ctl->tuner_set_frequency; + feconf->tuner_get_frequency = ctl->tuner_get_frequency; + feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth; + feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth; + feconf->tuner_set_bbgain = ctl->tuner_set_bbgain; + feconf->tuner_get_bbgain = ctl->tuner_get_bbgain; + feconf->tuner_set_refclk = ctl->tuner_set_refclk; + feconf->tuner_get_status = ctl->tuner_get_status; + + return 0; +} + + +static int demod_attach_stv0900(struct ngene_channel *chan) +{ + struct stv090x_config *feconf = (struct stv090x_config *) + chan->dev->card_info->fe_config[chan->number]; + + chan->fe = dvb_attach(stv090x_attach, + feconf, + &chan->i2c_adapter, + chan->number == 0 ? STV090x_DEMODULATOR_0 : + STV090x_DEMODULATOR_1); + if (chan->fe == NULL) { + printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); + return -ENODEV; + } + + if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0, + 0, chan->dev->card_info->lnb[chan->number])) { + printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); + dvb_frontend_detach(chan->fe); + return -ENODEV; + } + + return 0; +} /****************************************************************************/ /****************************************************************************/ @@ -2573,6 +2631,59 @@ fail1: /* Card configs *************************************************************/ /****************************************************************************/ +static struct stv090x_config fe_mps2 = { + .device = STV0900, + .demod_mode = STV090x_DUAL, + .clk_mode = STV090x_CLK_EXT, + + .xtal = 27000000, + .address = 0x68, +// .ref_clk = 27000000, + + .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + + .repeater_level = STV090x_RPTLEVEL_16, + + .diseqc_envelope_mode = true, + + .tuner_init = NULL, + .tuner_set_mode = NULL, + .tuner_set_frequency = NULL, + .tuner_get_frequency = NULL, + .tuner_set_bandwidth = NULL, + .tuner_get_bandwidth = NULL, + .tuner_set_bbgain = NULL, + .tuner_get_bbgain = NULL, + .tuner_set_refclk = NULL, + .tuner_get_status = NULL, +}; + +static struct stv6110x_config tuner_mps2_0 = { + .addr = 0x60, + .refclk = 27000000, +}; + +static struct stv6110x_config tuner_mps2_1 = { + .addr = 0x63, + .refclk = 27000000, +}; + +static struct ngene_info ngene_info_mps2 = { + .type = NGENE_SIDEWINDER, + .name = "Media-Pointer MP-S2/CineS2 DVB-S2 Twin Tuner", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, + .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, + .fe_config = {&fe_mps2, &fe_mps2}, + .tuner_config = {&tuner_mps2_0, &tuner_mps2_1}, + .lnb = {0x0b, 0x08}, + .tsf = {3, 3}, + .fw_version = 17, +}; + +/****************************************************************************/ + /****************************************************************************/ @@ -2587,8 +2698,12 @@ fail1: /****************************************************************************/ static const struct pci_device_id ngene_id_tbl[] __devinitdata = { + NGENE_ID(0x18c3, 0xabc3, ngene_info_mps2), + NGENE_ID(0x18c3, 0xabc4, ngene_info_mps2), + NGENE_ID(0x18c3, 0xdb01, ngene_info_mps2), {0} }; +MODULE_DEVICE_TABLE(pci, ngene_id_tbl); /****************************************************************************/ /* Init/Exit ****************************************************************/ -- cgit v1.2.3 From adc1d21eec74afbd38a9099f4aff4bcd5b9eaea2 Mon Sep 17 00:00:00 2001 From: Matthias Benesch Date: Sat, 19 Dec 2009 12:57:16 -0300 Subject: V4L/DVB: ngene: Remove firmware debugging Remove firmware debugging, because setting ngene_fw_debug and requesting firmware from file causes a kernel error. Signed-off-by: Matthias Benesch Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 0e0c01396ce..cf12bff5744 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -56,10 +56,6 @@ static int copy_eeprom; module_param(copy_eeprom, int, 0444); MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); -static int ngene_fw_debug; -module_param(ngene_fw_debug, int, 0444); -MODULE_PARM_DESC(ngene_fw_debug, "Debug firmware."); - static int debug; module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Print debugging information."); @@ -435,7 +431,6 @@ static int ngene_command_load_firmware(struct ngene *dev, cleft - FIRSTCHUNK); cleft = FIRSTCHUNK; } - ngene_fw[FW_DEBUG_DEFAULT - PROGRAM_SRAM] = ngene_fw_debug; ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft); memset(&com, 0, sizeof(struct ngene_command)); -- cgit v1.2.3 From dc35c9ae193564af2003117857848d69af24d534 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sat, 19 Dec 2009 22:48:14 -0300 Subject: V4L/DVB: ngene: Fix unloading of module Fixed unloading of module ngene. Signed-off-by: Roland Praml Signed-off-by: Matthias Benesch Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index cf12bff5744..52798b7c8d9 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -2445,7 +2445,7 @@ static void release_channel(struct ngene_channel *chan) #endif if (chan->fe) { dvb_unregister_frontend(chan->fe); - /*dvb_frontend_detach(chan->fe); */ + dvb_frontend_detach(chan->fe); chan->fe = 0; } dvbdemux->dmx.close(&dvbdemux->dmx); @@ -2577,8 +2577,10 @@ static int __devinit ngene_probe(struct pci_dev *pci_dev, return -ENODEV; dev = vmalloc(sizeof(struct ngene)); - if (dev == NULL) - return -ENOMEM; + if (dev == NULL) { + stat = -ENOMEM; + goto fail0; + } memset(dev, 0, sizeof(struct ngene)); dev->pci_dev = pci_dev; @@ -2618,6 +2620,8 @@ fail2: ngene_stop(dev); fail1: ngene_release_buffers(dev); +fail0: + pci_disable_device(pci_dev); pci_set_drvdata(pci_dev, 0); return stat; } @@ -2743,7 +2747,7 @@ static struct pci_driver ngene_pci_driver = { .name = "ngene", .id_table = ngene_id_tbl, .probe = ngene_probe, - .remove = ngene_remove, + .remove = __devexit_p(ngene_remove), .err_handler = &ngene_errors, }; -- cgit v1.2.3 From 236fa316baf6bb89b2f361230d570093a2a79794 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sat, 19 Dec 2009 22:55:59 -0300 Subject: V4L/DVB: ngene: Speed-up tuning Remove stray mleep() which prevented fast tuning. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 52798b7c8d9..bba59b667d4 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -331,7 +331,6 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) dev->BootFirmware = 0; dev->prev_cmd = com->cmd.hdr.Opcode; - msleep(10); if (!com->out_len) return 0; -- cgit v1.2.3 From 44cdd064aa698c033e0a345ed187db7c24134d93 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 20 Dec 2009 02:30:52 -0300 Subject: V4L/DVB: ngene: Change severity of some diagnostic messages Changed severity of some diagnostic messages. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index bba59b667d4..12810834d05 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -728,9 +728,11 @@ int ngene_command_stream_control(struct ngene *dev, u8 stream, u8 control, com.in_len = sizeof(struct FW_STREAM_CONTROL); com.out_len = 0; - printk(KERN_INFO DEVICE_NAME ": Stream=%02x, Control=%02x, Mode=%02x\n", - com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control, - com.cmd.StreamControl.Mode); + dprintk(KERN_INFO DEVICE_NAME + ": Stream=%02x, Control=%02x, Mode=%02x\n", + com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control, + com.cmd.StreamControl.Mode); + chan->Mode = mode; if (!(control & 0x80)) { @@ -1042,7 +1044,7 @@ static int i2c_write_eeprom(struct i2c_adapter *adapter, .len = sizeof(m)}; if (i2c_transfer(adapter, &msg, 1) != 1) { - dprintk(KERN_DEBUG DEVICE_NAME ": Error writing EEPROM!\n"); + dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n"); return -EIO; } return 0; @@ -1058,7 +1060,7 @@ static int i2c_read_eeprom(struct i2c_adapter *adapter, .buf = data, .len = len} }; if (i2c_transfer(adapter, msgs, 2) != 2) { - dprintk(KERN_DEBUG DEVICE_NAME ": Error reading EEPROM\n"); + dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n"); return -EIO; } return 0; @@ -2331,7 +2333,7 @@ static int ngene_start(struct ngene *dev) bconf = hdtv_config; ngene_reset_decypher(dev); } - printk(KERN_INFO DEVICE_NAME ": FW 17 buffer config\n"); + dprintk(KERN_DEBUG DEVICE_NAME ": FW 17 buffer config\n"); stat = ngene_command_config_free_buf(dev, bconf); } else { int bconf = BUFFER_CONFIG_4422; -- cgit v1.2.3 From 948a119547cf5043b40c2151d6f6913fbcf65e38 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 22 Dec 2009 03:34:29 -0300 Subject: V4L/DVB: ngene: Remove kernel version check for dvb_[un]register_adapter Remove kernel version check for dvb_[un]register_adapter. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 12810834d05..72c06c66a95 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -2466,7 +2466,7 @@ static void release_channel(struct ngene_channel *chan) static int init_channel(struct ngene_channel *chan) { int ret = 0, nr = chan->number; - struct dvb_adapter *adapter = 0; + struct dvb_adapter *adapter = NULL; struct dvb_demux *dvbdemux = &chan->demux; struct ngene *dev = chan->dev; struct ngene_info *ni = dev->card_info; -- cgit v1.2.3 From 126cd4bc5fa9cdbedb89bbe7e568140c94900ca7 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 22 Dec 2009 04:37:53 -0300 Subject: V4L/DVB: DVB: Export dvb_ringbuffer_flush() again Add EXPORT_SYMBOL(dvb_ringbuffer_flush) again, replace my_dvb_ringbuffer_flush() in ngene driver. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 1 + drivers/media/dvb/ngene/ngene-core.c | 16 ++-------------- 2 files changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index 584bbd194dc..a5712cd7c65 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -89,6 +89,7 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) rbuf->pread = rbuf->pwrite; rbuf->error = 0; } +EXPORT_SYMBOL(dvb_ringbuffer_flush); void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) { diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 72c06c66a95..7d9feba71e1 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -76,18 +76,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \ (dev->iomem + (adr)), (count)) -/****************************************************************************/ -/* Functions with missing kernel exports ************************************/ -/****************************************************************************/ - -/* yeah, let's throw out all exports which are not used in kernel ... */ - -void my_dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) -{ - rbuf->pread = rbuf->pwrite; - rbuf->error = 0; -} - /****************************************************************************/ /* nGene interrupt handler **************************************************/ /****************************************************************************/ @@ -1518,7 +1506,7 @@ static void set_transfer(struct ngene_channel *chan, int state) /* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", ngreadl(0x9310)); */ - my_dvb_ringbuffer_flush(&dev->tsout_rbuf); + dvb_ringbuffer_flush(&dev->tsout_rbuf); control = 0x80; if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { chan->Capture1Length = 512 * 188; @@ -1549,7 +1537,7 @@ static void set_transfer(struct ngene_channel *chan, int state) if (!state) { spin_lock_irq(&chan->state_lock); chan->pBufferExchange = 0; - my_dvb_ringbuffer_flush(&dev->tsout_rbuf); + dvb_ringbuffer_flush(&dev->tsout_rbuf); spin_unlock_irq(&chan->state_lock); } } -- cgit v1.2.3 From cf1b12f2b355a29c44dad426f545db8fa26bd81c Mon Sep 17 00:00:00 2001 From: Matthias Benesch Date: Wed, 23 Dec 2009 05:55:02 -0300 Subject: V4L/DVB: ngene: Added module parameter "one_adapter" If parameter "one_adapter" is set, only one adapter per device will be attached. Otherwise an adapter for every frontend will be attached. Signed-off-by: Matthias Benesch Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 45 +++++++++++++++++------------------- drivers/media/dvb/ngene/ngene.h | 9 +------- 2 files changed, 22 insertions(+), 32 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 7d9feba71e1..907a5032784 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -52,6 +52,10 @@ #include "ngene-ioctls.h" #endif +static int one_adapter = 1; +module_param(one_adapter, int, 0444); +MODULE_PARM_DESC(one_adapter, "Use only one adapter."); + static int copy_eeprom; module_param(copy_eeprom, int, 0444); MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); @@ -2444,9 +2448,9 @@ static void release_channel(struct ngene_channel *chan) &chan->mem_frontend); dvb_dmxdev_release(&chan->dmxdev); dvb_dmx_release(&chan->demux); -#ifndef ONE_ADAPTER - dvb_unregister_adapter(&chan->dvb_adapter); -#endif + + if (chan->number == 0 || !one_adapter) + dvb_unregister_adapter(&dev->adapter[chan->number]); } } @@ -2472,17 +2476,18 @@ static int init_channel(struct ngene_channel *chan) if (io & NGENE_IO_TSOUT) dec_fw_boot(dev); -#ifdef ONE_ADAPTER - adapter = &chan->dev->dvb_adapter; -#else - ret = dvb_register_adapter(&chan->dvb_adapter, "nGene", - THIS_MODULE, - &chan->dev->pci_dev->dev, - adapter_nr); - if (ret < 0) - return ret; - adapter = &chan->dvb_adapter; -#endif + if (nr == 0 || !one_adapter) { + adapter = &dev->adapter[nr]; + ret = dvb_register_adapter(adapter, "nGene", + THIS_MODULE, + &chan->dev->pci_dev->dev, + adapter_nr); + if (ret < 0) + return ret; + } else { + adapter = &dev->adapter[0]; + } + ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", ngene_start_feed, ngene_stop_feed, chan); @@ -2527,7 +2532,7 @@ static int init_channels(struct ngene *dev) for (i = 0; i < MAX_STREAM; i++) { if (init_channel(&dev->channel[i]) < 0) { - for (j = 0; j < i; j++) + for (j = i - 1; j >= 0; j--) release_channel(&dev->channel[j]); return -1; } @@ -2545,11 +2550,8 @@ static void __devexit ngene_remove(struct pci_dev *pdev) int i; tasklet_kill(&dev->event_tasklet); - for (i = 0; i < MAX_STREAM; i++) + for (i = MAX_STREAM - 1; i >= 0; i--) release_channel(&dev->channel[i]); -#ifdef ONE_ADAPTER - dvb_unregister_adapter(&dev->dvb_adapter); -#endif ngene_stop(dev); ngene_release_buffers(dev); pci_set_drvdata(pdev, 0); @@ -2595,11 +2597,6 @@ static int __devinit ngene_probe(struct pci_dev *pci_dev, /*i2c_check_eeprom(&dev->i2c_adapter);*/ /* Register DVB adapters and devices for both channels */ -#ifdef ONE_ADAPTER - if (dvb_register_adapter(&dev->dvb_adapter, "nGene", THIS_MODULE, - &dev->pci_dev->dev, adapter_nr) < 0) - goto fail2; -#endif if (init_channels(dev) < 0) goto fail2; diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h index 243f86c8589..15505c2b253 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/dvb/ngene/ngene.h @@ -24,8 +24,6 @@ #ifndef _NGENE_H_ #define _NGENE_H_ -/*#define ONE_ADAPTER*/ - #include #include #include @@ -649,9 +647,6 @@ struct ngene_channel { struct dmx_frontend mem_frontend; int users; struct video_device *v4l_dev; -#ifndef ONE_ADAPTER - struct dvb_adapter dvb_adapter; -#endif struct tasklet_struct demux_tasklet; struct SBufferHeader *nextBuffer; @@ -728,9 +723,6 @@ struct ngene { struct pci_dev *pci_dev; unsigned char *iomem; -#ifdef ONE_ADAPTER - struct dvb_adapter dvb_adapter; -#endif /*struct i2c_adapter i2c_adapter;*/ u32 device_version; @@ -764,6 +756,7 @@ struct ngene { int i2c_current_bus; spinlock_t cmd_lock; + struct dvb_adapter adapter[MAX_STREAM]; struct ngene_channel channel[MAX_STREAM]; struct ngene_info *card_info; -- cgit v1.2.3 From 9fdd797659de7a989025c64c336542ac9c15d4d1 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 23 Dec 2009 16:26:17 -0300 Subject: V4L/DVB: ngene: Code cleanup Remove/comment-out unused code, make some functions/declarations static. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 790 +------------ drivers/media/dvb/ngene/ngene-ioctls.h | 216 ---- drivers/media/dvb/ngene/ngene-snd.c | 421 ------- drivers/media/dvb/ngene/ngene-v4l2.c | 1937 -------------------------------- drivers/media/dvb/ngene/ngene.h | 11 - 5 files changed, 10 insertions(+), 3365 deletions(-) delete mode 100644 drivers/media/dvb/ngene/ngene-ioctls.h delete mode 100644 drivers/media/dvb/ngene/ngene-snd.c delete mode 100644 drivers/media/dvb/ngene/ngene-v4l2.c (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 907a5032784..6f1b0661814 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -48,17 +48,10 @@ #include "stv090x.h" #include "lnbh24.h" -#ifdef NGENE_COMMAND_API -#include "ngene-ioctls.h" -#endif - static int one_adapter = 1; module_param(one_adapter, int, 0444); MODULE_PARM_DESC(one_adapter, "Use only one adapter."); -static int copy_eeprom; -module_param(copy_eeprom, int, 0444); -MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); static int debug; module_param(debug, int, 0444); @@ -342,19 +335,8 @@ static int ngene_command(struct ngene *dev, struct ngene_command *com) return result; } -int ngene_command_nop(struct ngene *dev) -{ - struct ngene_command com; - - com.cmd.hdr.Opcode = CMD_NOP; - com.cmd.hdr.Length = 0; - com.in_len = 0; - com.out_len = 0; - - return ngene_command(dev, &com); -} -int ngene_command_i2c_read(struct ngene *dev, u8 adr, +static int ngene_command_i2c_read(struct ngene *dev, u8 adr, u8 *out, u8 outlen, u8 *in, u8 inlen, int flag) { struct ngene_command com; @@ -381,7 +363,8 @@ int ngene_command_i2c_read(struct ngene *dev, u8 adr, return 0; } -int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen) +static int ngene_command_i2c_write(struct ngene *dev, u8 adr, + u8 *out, u8 outlen) { struct ngene_command com; @@ -435,81 +418,6 @@ static int ngene_command_load_firmware(struct ngene *dev, return ngene_command(dev, &com); } -int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) -{ - struct ngene_command com; - - com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; - com.cmd.hdr.Length = 1; - com.cmd.SfrIramRead.address = adr; - com.in_len = 1; - com.out_len = 2; - - if (ngene_command(dev, &com) < 0) - return -EIO; - - *data = com.cmd.raw8[1]; - return 0; -} - -int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) -{ - struct ngene_command com; - - com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; - com.cmd.hdr.Length = 2; - com.cmd.SfrIramWrite.address = adr; - com.cmd.SfrIramWrite.data = data; - com.in_len = 2; - com.out_len = 1; - - if (ngene_command(dev, &com) < 0) - return -EIO; - - return 0; -} - -static int ngene_command_config_uart(struct ngene *dev, u8 config, - tx_cb_t *tx_cb, rx_cb_t *rx_cb) -{ - struct ngene_command com; - - com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; - com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; - com.cmd.ConfigureUart.UartControl = config; - com.in_len = sizeof(struct FW_CONFIGURE_UART); - com.out_len = 0; - - if (ngene_command(dev, &com) < 0) - return -EIO; - - dev->TxEventNotify = tx_cb; - dev->RxEventNotify = rx_cb; - - dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); - - return 0; -} - -static void tx_cb(struct ngene *dev, u32 ts) -{ - dev->tx_busy = 0; - wake_up_interruptible(&dev->tx_wq); -} - -static void rx_cb(struct ngene *dev, u32 ts, u8 c) -{ - int rp = dev->uart_rp; - int nwp, wp = dev->uart_wp; - - /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ - nwp = (wp + 1) % (UART_RBUF_LEN); - if (nwp == rp) - return; - dev->uart_rbuf[wp] = c; - dev->uart_wp = nwp; - wake_up_interruptible(&dev->rx_wq); -} static int ngene_command_config_buf(struct ngene *dev, u8 config) { @@ -555,16 +463,6 @@ static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) return ngene_command(dev, &com); } -/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! - Also better set bootdelay to 1 in nvram or less. */ -static void ngene_reset_decypher(struct ngene *dev) -{ - printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); - ngene_command_gpio_set(dev, 4, 0); - msleep(1); - ngene_command_gpio_set(dev, 4, 1); - msleep(2000); -} /* 02000640 is sample on rising edge. @@ -693,8 +591,8 @@ static void clear_buffers(struct ngene_channel *chan) } } -int ngene_command_stream_control(struct ngene *dev, u8 stream, u8 control, - u8 mode, u8 flags) +static int ngene_command_stream_control(struct ngene *dev, u8 stream, + u8 control, u8 mode, u8 flags) { struct ngene_channel *chan = &dev->channel[stream]; struct ngene_command com; @@ -847,23 +745,6 @@ int ngene_command_stream_control(struct ngene *dev, u8 stream, u8 control, return 0; } -int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, - u16 lines, u16 bpl, u16 vblines, u16 vbibpl) -{ - if (!(mode & SMODE_TRANSPORT_STREAM)) - return -EINVAL; - - if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) - return -EINVAL; - - if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) - return -EINVAL; - - if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) - return -EINVAL; - - return ngene_command_stream_control(dev, stream, control, mode, 0); -} /****************************************************************************/ /* I2C **********************************************************************/ @@ -924,13 +805,12 @@ done: } - static u32 ngene_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL; } -struct i2c_algorithm ngene_i2c_algo = { +static struct i2c_algorithm ngene_i2c_algo = { .master_xfer = ngene_i2c_master_xfer, .functionality = ngene_i2c_functionality, }; @@ -956,476 +836,6 @@ static int ngene_i2c_init(struct ngene *dev, int dev_nr) return i2c_add_adapter(adap); } -int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) -{ - u8 m[1] = {data}; - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; - - if (i2c_transfer(adapter, &msg, 1) != 1) { - printk(KERN_ERR DEVICE_NAME - ": Failed to write to I2C adr %02x!\n", adr); - return -1; - } - return 0; -} - - -static int i2c_write_read(struct i2c_adapter *adapter, - u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) -{ - struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, - .buf = w, .len = wlen}, - {.addr = adr, .flags = I2C_M_RD, - .buf = r, .len = rlen} }; - - if (i2c_transfer(adapter, msgs, 2) != 2) { - printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); - return -1; - } - return 0; -} - -static int test_dec_i2c(struct i2c_adapter *adapter, int reg) -{ - u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; - u8 data2[256]; - int i; - - memset(data2, 0, 256); - i2c_write_read(adapter, 0x66, data, 2, data2, 4); - for (i = 0; i < 4; i++) - printk("%02x ", data2[i]); - printk("\n"); - - return 0; -} - - -/****************************************************************************/ -/* EEPROM TAGS **************************************************************/ -/****************************************************************************/ - -#define MICNG_EE_START 0x0100 -#define MICNG_EE_END 0x0FF0 - -#define MICNG_EETAG_END0 0x0000 -#define MICNG_EETAG_END1 0xFFFF - -/* 0x0001 - 0x000F reserved for housekeeping */ -/* 0xFFFF - 0xFFFE reserved for housekeeping */ - -/* Micronas assigned tags - EEProm tags for hardware support */ - -#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ -#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ - -#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ -#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ - -/* Tag range for OEMs */ - -#define MICNG_EETAG_OEM_FIRST 0xC000 -#define MICNG_EETAG_OEM_LAST 0xFFEF - -static int i2c_write_eeprom(struct i2c_adapter *adapter, - u8 adr, u16 reg, u8 data) -{ - u8 m[3] = {(reg >> 8), (reg & 0xff), data}; - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, - .len = sizeof(m)}; - - if (i2c_transfer(adapter, &msg, 1) != 1) { - dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n"); - return -EIO; - } - return 0; -} - -static int i2c_read_eeprom(struct i2c_adapter *adapter, - u8 adr, u16 reg, u8 *data, int len) -{ - u8 msg[2] = {(reg >> 8), (reg & 0xff)}; - struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, - .buf = msg, .len = 2 }, - {.addr = adr, .flags = I2C_M_RD, - .buf = data, .len = len} }; - - if (i2c_transfer(adapter, msgs, 2) != 2) { - dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n"); - return -EIO; - } - return 0; -} - - -static int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) -{ - u8 buf[64]; - int i; - - if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { - printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); - return -1; - } - for (i = 0; i < sizeof(buf); i++) { - if (!(i & 15)) - printk("\n"); - printk("%02x ", buf[i]); - } - printk("\n"); - - return 0; -} - -static int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) -{ - u8 buf[64]; - int i; - - if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { - printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); - return -1; - } - buf[36] = 0xc3; - buf[39] = 0xab; - for (i = 0; i < sizeof(buf); i++) { - i2c_write_eeprom(adapter, adr2, i, buf[i]); - msleep(10); - } - return 0; -} - - -/****************************************************************************/ -/* COMMAND API interface ****************************************************/ -/****************************************************************************/ - -#ifdef NGENE_COMMAND_API - -static int command_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *parg) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - int err = 0; - - switch (cmd) { - case IOCTL_MIC_NO_OP: - err = ngene_command_nop(dev); - break; - - case IOCTL_MIC_DOWNLOAD_FIRMWARE: - break; - - case IOCTL_MIC_I2C_READ: - { - MIC_I2C_READ *msg = parg; - - err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, - msg->OutData, msg->OutLength, - msg->OutData, msg->InLength, 1); - break; - } - - case IOCTL_MIC_I2C_WRITE: - { - MIC_I2C_WRITE *msg = parg; - - err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, - msg->Data, msg->Length); - break; - } - - case IOCTL_MIC_TEST_GETMEM: - { - MIC_MEM *m = parg; - - if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) - return -EINVAL; - - /* WARNING, only use this on x86, - other archs may not swallow this */ - err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); - break; - } - - case IOCTL_MIC_TEST_SETMEM: - { - MIC_MEM *m = parg; - - if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) - return -EINVAL; - - err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); - break; - } - - case IOCTL_MIC_SFR_READ: - { - MIC_IMEM *m = parg; - - err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); - break; - } - - case IOCTL_MIC_SFR_WRITE: - { - MIC_IMEM *m = parg; - - err = ngene_command_imem_write(dev, m->Address, m->Data, 1); - break; - } - - case IOCTL_MIC_IRAM_READ: - { - MIC_IMEM *m = parg; - - err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); - break; - } - - case IOCTL_MIC_IRAM_WRITE: - { - MIC_IMEM *m = parg; - - err = ngene_command_imem_write(dev, m->Address, m->Data, 0); - break; - } - - case IOCTL_MIC_STREAM_CONTROL: - { - MIC_STREAM_CONTROL *m = parg; - - err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, - m->nLines, m->nBytesPerLine, - m->nVBILines, m->nBytesPerVBILine); - break; - } - - default: - err = -EINVAL; - break; - } - return err; -} - -static int command_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - void *parg = (void *)arg, *pbuf = NULL; - char buf[64]; - int res = -EFAULT; - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - parg = buf; - if (_IOC_SIZE(cmd) > sizeof(buf)) { - pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (!pbuf) - return -ENOMEM; - parg = pbuf; - } - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto error; - } - res = command_do_ioctl(inode, file, cmd, parg); - if (res < 0) - goto error; - if (_IOC_DIR(cmd) & _IOC_READ) - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - res = -EFAULT; -error: - kfree(pbuf); - return res; -} - -struct page *ngene_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - return 0; -} - -static int ngene_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long off = vma->vm_pgoff << PAGE_SHIFT; - unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; - unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; - - if (size > psize) - return -EINVAL; - - if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, - vma->vm_page_prot)) - return -EAGAIN; - return 0; -} - -static int write_uart(struct ngene *dev, u8 *data, int len) -{ - struct ngene_command com; - - com.cmd.hdr.Opcode = CMD_WRITE_UART; - com.cmd.hdr.Length = len; - memcpy(com.cmd.WriteUart.Data, data, len); - com.cmd.WriteUart.Data[len] = 0; - com.cmd.WriteUart.Data[len + 1] = 0; - com.in_len = len; - com.out_len = 0; - - if (ngene_command(dev, &com) < 0) - return -EIO; - - return 0; -} - -static int send_cli(struct ngene *dev, char *cmd) -{ - /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ - return write_uart(dev, cmd, strlen(cmd)); -} - -static int send_cli_val(struct ngene *dev, char *cmd, u32 val) -{ - char s[32]; - - snprintf(s, 32, "%s %d\n", cmd, val); - /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ - return write_uart(dev, s, strlen(s)); -} - -static int ngene_command_write_uart_user(struct ngene *dev, - const u8 *data, int len) -{ - struct ngene_command com; - - dev->tx_busy = 1; - com.cmd.hdr.Opcode = CMD_WRITE_UART; - com.cmd.hdr.Length = len; - - if (copy_from_user(com.cmd.WriteUart.Data, data, len)) - return -EFAULT; - com.in_len = len; - com.out_len = 0; - - if (ngene_command(dev, &com) < 0) - return -EIO; - - return 0; -} - -static ssize_t uart_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - int len, ret = 0; - size_t left = count; - - while (left) { - len = left; - if (len > 250) - len = 250; - ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); - if (ret < 0) - return ret; - ngene_command_write_uart_user(dev, buf, len); - left -= len; - buf += len; - } - return count; -} - -static ssize_t ts_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - - if (wait_event_interruptible(dev->tsout_rbuf.queue, - dvb_ringbuffer_free - (&dev->tsout_rbuf) >= count) < 0) - return 0; - - dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); - - return count; -} - -static ssize_t uart_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - struct dvb_device *dvbdev = file->private_data; - struct ngene_channel *chan = dvbdev->priv; - struct ngene *dev = chan->dev; - int left; - int wp, rp, avail, len; - - if (!dev->uart_rbuf) - return -EINVAL; - if (count > 128) - count = 128; - left = count; - while (left) { - if (wait_event_interruptible(dev->rx_wq, - dev->uart_wp != dev->uart_rp) < 0) - return -EAGAIN; - wp = dev->uart_wp; - rp = dev->uart_rp; - avail = (wp - rp); - - if (avail < 0) - avail += UART_RBUF_LEN; - if (avail > left) - avail = left; - if (wp < rp) { - len = UART_RBUF_LEN - rp; - if (len > avail) - len = avail; - if (copy_to_user(buf, dev->uart_rbuf + rp, len)) - return -EFAULT; - if (len < avail) - if (copy_to_user(buf + len, dev->uart_rbuf, - avail - len)) - return -EFAULT; - } else { - if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) - return -EFAULT; - } - dev->uart_rp = (rp + avail) % UART_RBUF_LEN; - left -= avail; - buf += avail; - } - return count; -} - -static const struct file_operations command_fops = { - .owner = THIS_MODULE, - .read = uart_read, - .write = ts_write, - .ioctl = command_ioctl, - .open = dvb_generic_open, - .release = dvb_generic_release, - .poll = 0, - .mmap = ngene_mmap, -}; - -static struct dvb_device dvbdev_command = { - .priv = 0, - .readers = -1, - .writers = -1, - .users = -1, - .fops = &command_fops, -}; - -#endif /****************************************************************************/ /* DVB functions and API interface ******************************************/ @@ -1550,32 +960,6 @@ static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct ngene_channel *chan = dvbdmx->priv; -#ifdef NGENE_COMMAND_API - struct ngene *dev = chan->dev; - - if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { - switch (dvbdmxfeed->pes_type) { - case DMX_TS_PES_VIDEO: - send_cli_val(dev, "vpid", dvbdmxfeed->pid); - send_cli(dev, "res 1080i50\n"); - /* send_cli(dev, "vdec mpeg2\n"); */ - break; - - case DMX_TS_PES_AUDIO: - send_cli_val(dev, "apid", dvbdmxfeed->pid); - send_cli(dev, "start\n"); - break; - - case DMX_TS_PES_PCR: - send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); - break; - - default: - break; - } - - } -#endif if (chan->users == 0) { set_transfer(chan, 1); @@ -1589,27 +973,6 @@ static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct ngene_channel *chan = dvbdmx->priv; -#ifdef NGENE_COMMAND_API - struct ngene *dev = chan->dev; - - if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { - switch (dvbdmxfeed->pes_type) { - case DMX_TS_PES_VIDEO: - send_cli(dev, "stop\n"); - break; - - case DMX_TS_PES_AUDIO: - break; - - case DMX_TS_PES_PCR: - break; - - default: - break; - } - - } -#endif if (--chan->users) return chan->users; @@ -1621,23 +984,6 @@ static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -static int write_to_decoder(struct dvb_demux_feed *feed, - const u8 *buf, size_t len) -{ - struct dvb_demux *dvbdmx = feed->demux; - struct ngene_channel *chan = dvbdmx->priv; - struct ngene *dev = chan->dev; - - if (wait_event_interruptible(dev->tsout_rbuf.queue, - dvb_ringbuffer_free - (&dev->tsout_rbuf) >= len) < 0) - return 0; - - dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); - - return len; -} - static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, int (*start_feed)(struct dvb_demux_feed *), int (*stop_feed)(struct dvb_demux_feed *), @@ -1678,86 +1024,12 @@ static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); } -/****************************************************************************/ -/* Decypher firmware loading ************************************************/ -/****************************************************************************/ - -#define DECYPHER_FW "decypher.fw" - -static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) -{ - while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) - msleep(1); - - - dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); - - return len; -} - -u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; - -int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) -{ - struct ngene_channel *chan = &dev->channel[4]; - u32 len = 180, cc = 0; - u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; - - set_transfer(chan, 1); - msleep(100); - while (size) { - len = 180; - if (len > size) - len = size; - buf[3] = 0x10 | (cc & 0x0f); - buf[4] = (cc >> 8); - buf[5] = cc & 0xff; - buf[6] = len; - - dec_ts_send(dev, buf, 8); - dec_ts_send(dev, fw, len); - if (len < 180) - dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); - cc++; - size -= len; - fw += len; - } - for (len = 0; len < 512; len++) - dec_ts_send(dev, dec_fw_fill_ts, 188); - while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) - msleep(10); - msleep(100); - set_transfer(chan, 0); - return 0; -} - -int dec_fw_boot(struct ngene *dev) -{ - u32 size; - const struct firmware *fw = NULL; - u8 *dec_fw; - - if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { - printk(KERN_ERR DEVICE_NAME - ": %s not found. Check hotplug directory.\n", - DECYPHER_FW); - return -1; - } - printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", - DECYPHER_FW); - - size = fw->size; - dec_fw = (u8 *)fw->data; - dec_fw_send(dev, dec_fw, size); - release_firmware(fw); - return 0; -} /****************************************************************************/ /* nGene hardware init and release functions ********************************/ /****************************************************************************/ -void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) +static void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) { struct SBufferHeader *Cur = rb->Head; u32 j; @@ -1786,7 +1058,7 @@ void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead); } -void free_idlebuffer(struct ngene *dev, +static void free_idlebuffer(struct ngene *dev, struct SRingBufferDescriptor *rb, struct SRingBufferDescriptor *tb) { @@ -1804,7 +1076,7 @@ void free_idlebuffer(struct ngene *dev, } } -void free_common_buffers(struct ngene *dev) +static void free_common_buffers(struct ngene *dev) { u32 i; struct ngene_channel *chan; @@ -1832,7 +1104,7 @@ void free_common_buffers(struct ngene *dev) /* Ring buffer handling *****************************************************/ /****************************************************************************/ -int create_ring_buffer(struct pci_dev *pci_dev, +static int create_ring_buffer(struct pci_dev *pci_dev, struct SRingBufferDescriptor *descr, u32 NumBuffers) { dma_addr_t tmp; @@ -2311,8 +1583,6 @@ static int ngene_start(struct ngene *dev) goto fail; if (dev->card_info->fw_version == 17) { - u8 hdtv_config[6] = - {6144 / 64, 0, 0, 2048 / 64, 2048 / 64, 2048 / 64}; u8 tsin4_config[6] = {3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; u8 default_config[6] = @@ -2321,30 +1591,14 @@ static int ngene_start(struct ngene *dev) if (dev->card_info->io_type[3] == NGENE_IO_TSIN) bconf = tsin4_config; - if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { - bconf = hdtv_config; - ngene_reset_decypher(dev); - } dprintk(KERN_DEBUG DEVICE_NAME ": FW 17 buffer config\n"); stat = ngene_command_config_free_buf(dev, bconf); } else { int bconf = BUFFER_CONFIG_4422; - - if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { - bconf = BUFFER_CONFIG_8022; - ngene_reset_decypher(dev); - } if (dev->card_info->io_type[3] == NGENE_IO_TSIN) bconf = BUFFER_CONFIG_3333; stat = ngene_command_config_buf(dev, bconf); } - - if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { - ngene_command_config_uart(dev, 0xc1, tx_cb, rx_cb); - test_dec_i2c(&dev->channel[0].i2c_adapter, 0); - test_dec_i2c(&dev->channel[0].i2c_adapter, 1); - } - return stat; fail: ngwritel(0, NGENE_INT_ENABLE); @@ -2432,10 +1686,6 @@ static void release_channel(struct ngene_channel *chan) tasklet_kill(&chan->demux_tasklet); if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { -#ifdef NGENE_COMMAND_API - if (chan->command_dev) - dvb_unregister_device(chan->command_dev); -#endif if (chan->fe) { dvb_unregister_frontend(chan->fe); dvb_frontend_detach(chan->fe); @@ -2452,7 +1702,6 @@ static void release_channel(struct ngene_channel *chan) if (chan->number == 0 || !one_adapter) dvb_unregister_adapter(&dev->adapter[chan->number]); } - } static int init_channel(struct ngene_channel *chan) @@ -2472,10 +1721,6 @@ static int init_channel(struct ngene_channel *chan) if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { if (nr >= STREAM_AUDIOIN1) chan->DataFormatFlags = DF_SWAP32; - - if (io & NGENE_IO_TSOUT) - dec_fw_boot(dev); - if (nr == 0 || !one_adapter) { adapter = &dev->adapter[nr]; ret = dvb_register_adapter(adapter, "nGene", @@ -2494,14 +1739,6 @@ static int init_channel(struct ngene_channel *chan) ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux, &chan->hw_frontend, &chan->mem_frontend, adapter); - if (io & NGENE_IO_TSOUT) { - dvbdemux->write_to_decoder = write_to_decoder; - } -#ifdef NGENE_COMMAND_API - dvb_register_device(adapter, &chan->command_dev, - &dvbdev_command, (void *)chan, - DVB_DEVICE_SEC); -#endif } if (io & NGENE_IO_TSIN) { @@ -2522,7 +1759,6 @@ static int init_channel(struct ngene_channel *chan) nr); } } - return ret; } @@ -2589,12 +1825,6 @@ static int __devinit ngene_probe(struct pci_dev *pci_dev, goto fail1; dev->i2c_current_bus = -1; - /* Disable analog TV decoder chips if present */ - if (copy_eeprom) { - i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); - i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); - } - /*i2c_check_eeprom(&dev->i2c_adapter);*/ /* Register DVB adapters and devices for both channels */ if (init_channels(dev) < 0) diff --git a/drivers/media/dvb/ngene/ngene-ioctls.h b/drivers/media/dvb/ngene/ngene-ioctls.h deleted file mode 100644 index 4aa2f64a531..00000000000 --- a/drivers/media/dvb/ngene/ngene-ioctls.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2006-2007 Micronas - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 only, as published by the Free Software Foundation. - * - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#ifndef _NGENE_IOCTLS_H_ -#define _NGENE_IOCTLS_H_ - -#include -#include - -#define NGENE_MAGIC 'n' - -typedef struct { - unsigned char I2CAddress; - unsigned char OutLength; /* bytes to write first */ - unsigned char InLength; /* bytes to read */ - unsigned char OutData[256]; /* output data */ - unsigned char InData[256]; /* input data */ -} MIC_I2C_READ, *PMIC_I2C_READ; - -#define IOCTL_MIC_I2C_READ _IOWR(NGENE_MAGIC, 0x00, MIC_I2C_READ) - - -typedef struct { - unsigned char I2CAddress; - unsigned char Length; - unsigned char Data[250]; -} MIC_I2C_WRITE, *PMIC_I2C_WRITE; - -typedef struct { - unsigned char Length; - unsigned char Data[250]; -} MIC_I2C_CONTINUE_WRITE, *PMIC_I2C_CONTINUE_WRITE; - -#define IOCTL_MIC_I2C_WRITE _IOW(NGENE_MAGIC, 0x01, \ - MIC_I2C_WRITE) -#define IOCTL_MIC_I2C_WRITE_NOSTOP _IOW(NGENE_MAGIC, 0x0c, \ - MIC_I2C_WRITE) -#define IOCTL_MIC_I2C_CONTINUE_WRITE_NOSTOP _IOW(NGENE_MAGIC, 0x0d, \ - MIC_I2C_CONTINUE_WRITE) -#define IOCTL_MIC_I2C_CONTINUE_WRITE _IOW(NGENE_MAGIC, 0x0e, \ - MIC_I2C_CONTINUE_WRITE) - -typedef struct { - unsigned char ModeSelect; /* see bellow */ - unsigned char OutLength; /* bytes to write first */ - unsigned char InLength; /* bytes to read */ - unsigned char OutData[250]; /* output data */ -} MIC_SPI_READ, *PMIC_SPI_READ; - -#define IOCTL_MIC_SPI_READ _IOWR(NGENE_MAGIC, 0x02, MIC_SPI_READ) - -typedef struct { - unsigned char ModeSelect; /* see below */ - unsigned char Length; - unsigned char Data[250]; -} MIC_SPI_WRITE, *PMIC_SPI_WRITE; - -#define IOCTL_MIC_SPI_WRITE _IOW(NGENE_MAGIC, 0x03, MIC_SPI_READ) - -#define IOCTL_MIC_DOWNLOAD_FIRMWARE _IOW(NGENE_MAGIC, 0x06, unsigned char) - -#define IOCTL_MIC_NO_OP _IO(NGENE_MAGIC, 0x18) - -#define IOCTL_MIC_TUN_RDY _IO(NGENE_MAGIC, 0x07) -#define IOCTL_MIC_DEC_SRATE _IOW(NGENE_MAGIC, 0x0a, int) -#define IOCTL_MIC_DEC_RDY _IO(NGENE_MAGIC, 0x09) -#define IOCTL_MIC_DEC_FREESYNC _IOW(NGENE_MAGIC, 0x08, int) -#define IOCTL_MIC_TUN_DETECT _IOWR(NGENE_MAGIC, 0x0b, int) - -typedef struct { - unsigned char Stream; /* < UVI1, UVI2, or TVOUT */ - unsigned char Control; - unsigned char Mode; - unsigned short nLines; - unsigned short nBytesPerLine; - unsigned short nVBILines; - unsigned short nBytesPerVBILine; -} MIC_STREAM_CONTROL, *PMIC_STREAM_CONTROL; - -enum MIC_STREAM_CONTROL_MODE_BITS { - MSC_MODE_LOOPBACK = 0x80, - MSC_MODE_AVLOOP = 0x40, - MSC_MODE_AUDIO_SPDIF = 0x20, - MSC_MODE_AVSYNC = 0x10, - MSC_MODE_TRANSPORT_STREAM = 0x08, - MSC_MODE_AUDIO_CAPTURE = 0x04, - MSC_MODE_VBI_CAPTURE = 0x02, - MSC_MODE_VIDEO_CAPTURE = 0x01 -}; - -#define IOCTL_MIC_STREAM_CONTROL _IOW(NGENE_MAGIC, 0x22, MIC_STREAM_CONTROL) - -typedef struct { - unsigned char Stream; /* < UVI1, UVI2 */ - unsigned int Rate; /* < Rate in 100nsec to release the buffers - to the stream filters */ -} MIC_SIMULATE_CONTROL, *PMIC_SIMULATE_CONTROL; - -#define IOCTL_MIC_SIMULATE_CONTROL _IOW(NGENE_MAGIC, 0x23, \ - MIC_SIMULATE_CONTROL) - -/* - * IOCTL definitions for the test driver - * - * NOTE: the test driver also supports following IOCTL defined above: - * IOCTL_MIC_NO_OP: - * IOCTL_MIC_RECEIVE_BUFFER: - * IOCTL_MIC_STREAM_CONTROL: - * IOCTL_MIC_I2C_READ: - * IOCTL_MIC_I2C_WRITE: - * - * - * VI2C access to NGene memory (read) - * - * GETMEM in : ULONG start offset - * out : read data (length defined by size of output buffer) - * SETMEM in : ULONG start offset followed by data to be written - * (length defined by size of input buffer) - */ - -typedef struct { - __u32 Start; - __u32 Length; - __u8 *Data; -} MIC_MEM; - -#define IOCTL_MIC_TEST_GETMEM _IOWR(NGENE_MAGIC, 0x90, MIC_MEM) -#define IOCTL_MIC_TEST_SETMEM _IOW(NGENE_MAGIC, 0x91, MIC_MEM) - -typedef struct { - __u8 Address; - __u8 Data; -} MIC_IMEM; - -#define IOCTL_MIC_SFR_READ _IOWR(NGENE_MAGIC, 0xa2, MIC_IMEM) -#define IOCTL_MIC_SFR_WRITE _IOWR(NGENE_MAGIC, 0xa3, MIC_IMEM) - -#define IOCTL_MIC_IRAM_READ _IOWR(NGENE_MAGIC, 0xa4, MIC_IMEM) -#define IOCTL_MIC_IRAM_WRITE _IOWR(NGENE_MAGIC, 0xa5, MIC_IMEM) - -/* - * Set Ngene gpio bit - */ -typedef struct { - unsigned char Select; - unsigned char Level; -} MIC_SET_GPIO_PIN, *PMIC_SET_GPIO_PIN; - -#define IOCTL_MIC_SET_GPIO_PIN _IOWR(NGENE_MAGIC, 0xa6, MIC_SET_GPIO_PIN) - -/* - * Uart ioctls: - * These are implemented in the test driver. - * - * Enable UART - * - * In: 1 byte containing baud rate: 0 = 19200, 1 = 9600, 2 = 4800, 3 = 2400 - * Out: nothing - */ -#define IOCTL_MIC_UART_ENABLE _IOW(NGENE_MAGIC, 0xa9, unsigned char) - -/* - * Enable UART - * - * In: nothing - * Out: nothing - */ -#define IOCTL_MIC_UART_DISABLE _IO(NGENE_MAGIC, 0xAA) - -/* - * Write UART - * - * In: data to write - * Out: nothing - * Note: Call returns immediatly, data are send out asynchrounsly - */ -#define IOCTL_MIC_UART_WRITE _IOW(NGENE_MAGIC, 0xAB, unsigned char) - -/* - * Read UART - * - * In: nothing - * Out: Data read (since last call) - * Note: Call returns immediatly - */ -#define IOCTL_MIC_UART_READ _IOR(NGENE_MAGIC, 0xAC, unsigned char) - -/* - * UART Status - * - * In: nothing - * Out: Byte 0 : Transmitter busy, - * Byte 1 : Nbr of characters available for read. - * Note: Call returns immediatly - */ -#define IOCTL_MIC_UART_STATUS _IOR(NGENE_MAGIC, 0xAD, unsigned char) - -#endif diff --git a/drivers/media/dvb/ngene/ngene-snd.c b/drivers/media/dvb/ngene/ngene-snd.c deleted file mode 100644 index 1ca343236ff..00000000000 --- a/drivers/media/dvb/ngene/ngene-snd.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * ngene_snd.c: nGene PCIe bridge driver ALSA support - * - * Copyright (C) 2005-2007 Micronas - * - * Based on the initial ALSA support port by Thomas Eschbach. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 only, as published by the Free Software Foundation. - * - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include - -#include "ngene.h" -#include "ngene-ioctls.h" - -static int sound_dev; - -/* sound module parameters (see "Module Parameters") */ -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; - -/****************************************************************************/ -/* PCM Sound Funktions ******************************************************/ -/****************************************************************************/ - -static struct snd_pcm_hardware snd_mychip_capture_hw = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 - | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 - | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), - .rate_min = 11025, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 16384, - .period_bytes_min = 8192, - .period_bytes_max = 8192, - .periods_min = 1, - .periods_max = 2, -}; - -/* open callback */ -static int snd_mychip_capture_open(struct snd_pcm_substream *substream) -{ - - struct mychip *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_mychip_capture_hw; - chip->substream = substream; - return 0; -} - -/* close callback */ -static int snd_mychip_capture_close(struct snd_pcm_substream *substream) -{ - struct mychip *chip = snd_pcm_substream_chip(substream); - chip->substream = NULL; - return 0; - -} - -/* hw_params callback */ -static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct mychip *chip = snd_pcm_substream_chip(substream); - struct ngene_channel *chan = chip->chan; - if (chan->soundbuffisallocated == 0) { - chan->soundbuffisallocated = 1; - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - } - return 0; -} - -/* hw_free callback */ -static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct mychip *chip = snd_pcm_substream_chip(substream); - struct ngene_channel *chan = chip->chan; - int retval = 0; - if (chan->soundbuffisallocated == 1) { - chan->soundbuffisallocated = 0; - retval = snd_pcm_lib_free_pages(substream); - } - return retval; -} - -/* prepare callback */ -static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream) -{ - - struct mychip *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ngene_channel *chan = chip->chan; - struct ngene_channel *ch = &chan->dev->channel[chan->number - 2]; - struct i2c_adapter *adap = &ch->i2c_adapter; - - if (ch->soundstreamon == 1) - ;/*ngene_command_stream_control_sound(chan->dev, chan->number, - 0x00, 0x00);*/ - i2c_clients_command(adap, IOCTL_MIC_DEC_SRATE, &(runtime->rate)); - mdelay(80); - if (ch->soundstreamon == 1) - ;/*ngene_command_stream_control_sound(chan->dev, chan->number, - 0x80, 0x04);*/ - - return 0; -} - -/* trigger callback */ -static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct mychip *chip = snd_pcm_substream_chip(substream); - struct ngene_channel *chan = chip->chan; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* do something to start the PCM engine */ - chan->sndbuffflag = 0; - break; - case SNDRV_PCM_TRIGGER_STOP: - /* do something to stop the PCM engine */ - chip->substream = NULL; - chan->sndbuffflag = 0; - break; - default: - return -EINVAL; - } - return 0; -} - -/* pointer callback */ -static snd_pcm_uframes_t -snd_mychip_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct mychip *chip = snd_pcm_substream_chip(substream); - struct ngene_channel *chan = chip->chan; - unsigned int current_ptr; - - if (chan->sndbuffflag == 0) { - current_ptr = (unsigned int) - bytes_to_frames(substream->runtime, 0); - } else { - current_ptr = (unsigned int) - bytes_to_frames(substream->runtime, 8192); - } - return current_ptr; -} - -/*copy sound buffer to pcm middel layer*/ -static int snd_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *dst, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mychip *chip = snd_pcm_substream_chip(substream); - struct ngene_channel *chan = chip->chan; - - memcpy(dst, chan->soundbuffer, frames_to_bytes(runtime, count)); - return 0; -} - -static int snd_pcm_capture_silence(struct snd_pcm_substream *substream, - int channel, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - /* - struct snd_pcm_runtime *runtime = substream->runtime; - struct mychip *chip = snd_pcm_substream_chip(substream); - struct ngene_channel *chan = chip->chan; - */ - return 0; -} - -/* operators */ -static struct snd_pcm_ops snd_mychip_capture_ops = { - .open = snd_mychip_capture_open, - .close = snd_mychip_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_mychip_pcm_hw_params, - .hw_free = snd_mychip_pcm_hw_free, - .prepare = snd_mychip_pcm_prepare, - .trigger = snd_mychip_pcm_trigger, - .pointer = snd_mychip_pcm_pointer, - .copy = snd_capture_copy, - .silence = snd_pcm_capture_silence, -}; - -static void mychip_pcm_free(struct snd_pcm *pcm) -{ - pcm->private_data = NULL; -} - -/* create a pcm device */ -static int snd_mychip_new_pcm(struct mychip *chip, struct ngene_channel *chan) -{ - struct snd_pcm *pcm; - int err; - char gro[10]; - sprintf(gro, "PCM%d", chan->number); - - err = snd_pcm_new(chip->card, gro, 0, 0, 1, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - pcm->private_free = mychip_pcm_free; - - sprintf(pcm->name, "MyPCM_%d", chan->number); - - chip->pcm = pcm; - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops); - /* pre-allocation of buffers */ - - err = snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data( - GFP_KERNEL), - 0, 16 * 1024); - - return 0; -} - -#define ngene_VOLUME(xname, xindex, addr) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_volume_info, \ - .get = snd_volume_get, .put = snd_volume_put, \ - .private_value = addr } - -static int snd_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *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_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct mychip *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_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct mychip *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 ngene_CAPSRC(xname, xindex, addr) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_capsrc_info, \ - .get = snd_capsrc_get, .put = snd_capsrc_put, \ - .private_value = addr } - -static int snd_capsrc_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *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_capsrc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct mychip *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_capsrc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct mychip *chip = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - - 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; - - spin_unlock_irq(&chip->mixer_lock); - - if (change) - printk(KERN_INFO "snd_capsrc_put change\n"); - return 0; -} - -static struct snd_kcontrol_new snd_controls[] = { - ngene_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), - ngene_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), -}; - -static int snd_card_new_mixer(struct mychip *chip) -{ - struct snd_card *card = chip->card; - unsigned int idx; - int err; - - strcpy(card->mixername, "NgeneMixer"); - - for (idx = 0; idx < ARRAY_SIZE(snd_controls); idx++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_controls[idx], chip)); - if (err < 0) - return err; - } - return 0; -} - -int ngene_snd_init(struct ngene_channel *chan) -{ - struct snd_card *card; - struct mychip *chip; - int err; - - if (sound_dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[sound_dev]) { - sound_dev++; - return -ENOENT; - } - card = snd_card_new(index[sound_dev], id[sound_dev], - THIS_MODULE, sizeof(struct mychip)); - if (card == NULL) - return -ENOMEM; - - chip = card->private_data; - chip->card = card; - chip->irq = -1; - - sprintf(card->shortname, "MyChip%d%d", chan->dev->nr, chan->number); - sprintf(card->shortname, "Myown%d%d", chan->dev->nr, chan->number); - sprintf(card->longname, "My first Own Chip on Card Nr.%d is %d", - chan->dev->nr, chan->number); - - spin_lock_init(&chip->lock); - spin_lock_init(&chip->mixer_lock); - - snd_card_new_mixer(chip); - - snd_mychip_new_pcm(chip, chan); - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - chan->soundcard = card; - chan->mychip = chip; - chip->chan = chan; - sound_dev++; - return 0; -} - -int ngene_snd_exit(struct ngene_channel *chan) -{ - snd_card_free(chan->soundcard); - return 0; -} diff --git a/drivers/media/dvb/ngene/ngene-v4l2.c b/drivers/media/dvb/ngene/ngene-v4l2.c deleted file mode 100644 index c0a9147c44a..00000000000 --- a/drivers/media/dvb/ngene/ngene-v4l2.c +++ /dev/null @@ -1,1937 +0,0 @@ -/* - * ngene_v4l2.c: nGene PCIe bridge driver V4L2 support - * - * Copyright (C) 2005-2007 Micronas - * - * Based on the initial V4L2 support port by Thomas Eschbach. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 only, as published by the Free Software Foundation. - * - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ngene.h" -#include "ngene-ioctls.h" - -/****************************************************************************/ - -static unsigned int gbuffers = 8; -static unsigned int gbufsize = 0x208000; - -enum km_type ngene_km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; - -#define V4L2_STD_NTSC_M_KOREA ((v4l2_std_id)0x00004000) -#define V4L2_STD_SECAM_L1 ((v4l2_std_id)0x00008000) - -static inline void *my_video_get_drvdata(struct video_device *vd) -{ - return dev_get_drvdata(vd->dev); -} - -static inline void my_video_set_drvdata(struct video_device *vd, void *d) -{ - dev_set_drvdata(vd->dev, d); -} - -static struct ngene_tvnorm ngene_tvnorms_hd[] = { - { - .v4l2_id = V4L2_STD_PAL_BG, - .name = "1080i50", - .swidth = 1920, - .sheight = 1080, - .tuner_norm = 1, - .soundstd = 1, - } -}; - -static struct ngene_tvnorm ngene_tvnorms_sd[] = { - /* PAL-BDGHI */ - /* max. active video is actually 922, but 924 is divisible by 4 & 3!*/ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ - { - .v4l2_id = V4L2_STD_PAL_BG, - .name = "PAL-BG", - .swidth = 720, - .sheight = 576, - .tuner_norm = 1, - .soundstd = 1, - }, { - .v4l2_id = V4L2_STD_PAL_DK, - .name = "PAL-DK", - .swidth = 720, - .sheight = 576, - .tuner_norm = 2, - .soundstd = 2, - }, { - .v4l2_id = V4L2_STD_PAL_H, - .name = "PAL-H", - .swidth = 720, - .sheight = 576, - .tuner_norm = 0, - .soundstd = 1, - }, { - .v4l2_id = V4L2_STD_PAL_I, - .name = "PAL-I", - .swidth = 720, - .sheight = 576, - .tuner_norm = 4, - .soundstd = 4, - }, { - .v4l2_id = V4L2_STD_PAL_M, - .name = "PAL_M", - .swidth = 720, - .sheight = 5760, - .tuner_norm = 7, - .soundstd = 5, - }, { - .v4l2_id = V4L2_STD_NTSC_M, - .name = "NTSC_M", - .swidth = 720, - .sheight = 480, - .tuner_norm = 7, - .soundstd = 5, - }, { - .v4l2_id = V4L2_STD_NTSC_M_JP, - .name = "NTSC_M_JP", - .swidth = 720, - .sheight = 480, - .tuner_norm = 7, - .soundstd = 6, - }, { - .v4l2_id = V4L2_STD_PAL_N, - .name = "PAL-N", - .swidth = 720, - .sheight = 576, - .tuner_norm = 7, - .soundstd = 5, - }, { - .v4l2_id = V4L2_STD_SECAM_B, - .name = "SECAM_B", - .swidth = 720, - .sheight = 576, - .tuner_norm = 1, - .soundstd = 1, - }, { - .v4l2_id = V4L2_STD_SECAM_D, - .name = "SECAM_D", - .swidth = 720, - .sheight = 576, - .tuner_norm = 2, - .soundstd = 2, - }, { - .v4l2_id = V4L2_STD_SECAM_G, - .name = "SECAM_G", - .swidth = 720, - .sheight = 576, - .tuner_norm = 3, - .soundstd = 1, - }, { - .v4l2_id = V4L2_STD_SECAM_H, - .name = "SECAM_H", - .swidth = 720, - .sheight = 576, - .tuner_norm = 3, - .soundstd = 1, - }, { - .v4l2_id = V4L2_STD_SECAM_K, - .name = "SECAM_K", - .swidth = 720, - .sheight = 576, - .tuner_norm = 2, - .soundstd = 2, - }, { - .v4l2_id = V4L2_STD_SECAM_K1, - .name = "SECAM_K1", - .swidth = 720, - .sheight = 576, - .tuner_norm = 2, - .soundstd = 2, - }, { - .v4l2_id = V4L2_STD_SECAM_L, - .name = "SECAM_L", - .swidth = 720, - .sheight = 576, - .tuner_norm = 5, - .soundstd = 3, - }, { - .v4l2_id = V4L2_STD_NTSC_M_KOREA, - .name = "NTSC_M_KOREA", - .swidth = 720, - .sheight = 480, - .tuner_norm = 7, - .soundstd = 7, - }, { - .v4l2_id = V4L2_STD_SECAM_L1, - .name = "SECAM_L1", - .swidth = 720, - .sheight = 576, - .tuner_norm = 6, - .soundstd = 3, - } - -}; - -static const int NGENE_TVNORMS = ARRAY_SIZE(ngene_tvnorms_sd); - -static u8 BlackLine[1440] = { - /* 0x80, */ 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, - 0x80, -}; - -#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) -#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 1) - -static const struct v4l2_queryctrl no_ctl = { - .name = "no_ctl", - .flags = V4L2_CTRL_FLAG_DISABLED, -}; - -static const struct v4l2_queryctrl ngene_ctls[] = { - /* --- video --- */ - { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = -127, - .maximum = 127, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 63, - .step = 1, - .default_value = 30, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 4094, - .step = 1, - .default_value = 2000, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = -2047, - .maximum = 2047, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - /* --- audio --- */ - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, { - .id = V4L2_CID_PRIVATE_SHARPNESS, - .name = "sharpness", - .minimum = 0, - .maximum = 100, - .step = 1, - .default_value = 50, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - -}; - -static const int NGENE_CTLS = ARRAY_SIZE(ngene_ctls); - -static const struct ngene_format ngene_formats[] = { - { - .name = "4:2:2, packed, YUYV", - .palette = -1, - .fourcc = V4L2_PIX_FMT_YUYV, - .format = V4L2_PIX_FMT_YUYV, - .palette = VIDEO_PALETTE_YUYV, - .depth = 16, - .flags = 0x02,/* FORMAT_FLAGS_PACKED, */ - } -}; - -static const unsigned int NGENE_FORMATS = ARRAY_SIZE(ngene_formats); - -/****************************************************************************/ - -static struct videobuf_queue *ngene_queue(struct ngene_vopen *vopen) -{ - struct videobuf_queue *q = NULL; - - switch (vopen->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - q = &vopen->vbuf_q; - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - q = &vopen->vbi; - break; - default: - break; - } - return q; -} - -static int ngene_resource(struct ngene_vopen *vopen) -{ - int res = 0; - - switch (vopen->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - res = RESOURCE_VIDEO; - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - res = RESOURCE_VBI; - break; - default: - break; - } - return res; -} - -static int ngene_try_fmt(struct ngene_vopen *vopen, struct ngene_channel *chan, - struct v4l2_format *f) -{ - switch (f->type) { - - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - const struct ngene_format *fmt; - enum v4l2_field field; - unsigned int maxw, maxh; - int maxLinesPerField; - - fmt = ngene_formats; - if (NULL == fmt) - return -EINVAL; - - /* fixup format */ - maxw = chan->tvnorms[chan->tvnorm].swidth; - maxLinesPerField = chan->tvnorms[chan->tvnorm].sheight; - maxh = maxLinesPerField; - field = f->fmt.pix.field; - - if (V4L2_FIELD_ANY == field) - field = (f->fmt.pix.height > maxh / 2) - ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; - - if (V4L2_FIELD_SEQ_BT == field) - field = V4L2_FIELD_SEQ_TB; - - /* update data for the application */ - f->fmt.pix.field = field; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - f->fmt.pix.width &= ~0x03; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; - } - - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - return -EINVAL; - - case V4L2_BUF_TYPE_VBI_CAPTURE: - return 0; - - default: - return -EINVAL; - } -} - -/****************************************************************************/ -/* Analog driver stuff ******************************************************/ -/****************************************************************************/ - -static int check_alloc_res(struct ngene_channel *channel, - struct ngene_vopen *vopen, int bit) -{ - if (vopen->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - down(&channel->reslock); - if (channel->resources & bit) { - /* no, someone else uses it */ - up(&channel->reslock); - return 0; - } - /* it's free, grab it */ - vopen->resources |= bit; - channel->resources |= bit; - up(&channel->reslock); - return 1; -} - -static int check_res(struct ngene_vopen *vopen, int bit) -{ - return vopen->resources & bit; -} - -static int locked_res(struct ngene_channel *chan, int bit) -{ - return chan->resources & bit; -} - -static void free_res(struct ngene_channel *channel, - struct ngene_vopen *vopen, int bits) -{ - down(&channel->reslock); - vopen->resources &= ~bits; - channel->resources &= ~bits; - up(&channel->reslock); -} - -/****************************************************************************/ -/* MISC HELPERS *************************************************************/ -/****************************************************************************/ - -static int ngene_g_fmt(struct ngene_vopen *vopen, struct v4l2_format *f) -{ - if (!vopen->fmt) - vopen->fmt = ngene_formats; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->fmt.pix.width = vopen->width; - f->fmt.pix.height = vopen->height; - f->fmt.pix.field = vopen->vbuf_q.field; - f->fmt.pix.pixelformat = vopen->fmt->fourcc; - f->fmt.pix.bytesperline = (f->fmt.pix.width * 16) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - return 0; - - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - memset(&f->fmt.win, 0, sizeof(struct v4l2_window)); - return 0; - f->fmt.win.w = vopen->ov.w; - f->fmt.win.field = vopen->ov.field; - return 0; - - case V4L2_BUF_TYPE_VBI_CAPTURE: - return -EINVAL; - - default: - return -EINVAL; - } -} - -static int ngene_switch_type(struct ngene_vopen *vopen, enum v4l2_buf_type type) -{ - struct videobuf_queue *q = ngene_queue(vopen); - int res = ngene_resource(vopen); - - if (check_res(vopen, res)) - return -EBUSY; - if (videobuf_queue_is_busy(q)) - return -EBUSY; - vopen->type = type; - return 0; -} - -static int ngene_s_fmt(struct ngene_vopen *vopen, struct ngene_channel *chan, - struct v4l2_format *f) -{ - int retval; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - const struct ngene_format *fmt; - retval = ngene_try_fmt(vopen, chan, f); - if (0 != retval) - return retval; - - retval = ngene_switch_type(vopen, f->type); - if (0 != retval) - return retval; - fmt = ngene_formats; - - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) - return -EINVAL; - /* update our state informations */ - mutex_lock(&vopen->vbuf_q.lock); - vopen->fmt = fmt; - vopen->vbuf_q.field = f->fmt.pix.field; - vopen->vbuf_q.last = V4L2_FIELD_INTERLACED; - vopen->width = f->fmt.pix.width; - vopen->height = f->fmt.pix.height; - chan->init.fmt = fmt; - chan->init.width = f->fmt.pix.width; - chan->init.height = f->fmt.pix.height; - mutex_unlock(&vopen->vbuf_q.lock); - - return 0; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - return -EINVAL; - case V4L2_BUF_TYPE_VBI_CAPTURE: - return -EINVAL; - default: - return -EINVAL; - } -} - -/****************************************************************************/ -/* SG support ***************************************************************/ -/****************************************************************************/ - -static inline enum km_type ngene_kmap_type(int out) -{ - return ngene_km_types[(in_softirq() ? 2 : 0) + out]; -} - -static inline void *ngene_kmap(struct page *page, int out) -{ - return kmap_atomic(page, ngene_kmap_type(out)); -} - -static inline void ngene_kunmap(void *vaddr, int out) -{ - kunmap_atomic(vaddr, ngene_kmap_type(out)); -} - -struct scatter_walk { - struct scatterlist *sg; - struct page *page; - void *data; - unsigned int len_this_page; - unsigned int len_this_segment; - unsigned int offset; -}; - -static inline struct scatterlist *sg_next(struct scatterlist *sg) -{ - return sg + 1; -} - -void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes) -{ - if (nbytes <= walk->len_this_page && - (((unsigned long)walk->data) & - (PAGE_CACHE_SIZE - 1)) + nbytes <= PAGE_CACHE_SIZE) - return walk->data; - else - return walk->data; -} - -void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) -{ - unsigned int rest_of_page; - - walk->sg = sg; - walk->page = sg->page; - walk->len_this_segment = sg->length; - rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); - walk->len_this_page = min(sg->length, rest_of_page); - walk->offset = sg->offset; -} - -void scatterwalk_map(struct scatter_walk *walk, int out) -{ - walk->data = ngene_kmap(walk->page, out) + walk->offset; -} - -static void scatterwalk_pagedone(struct scatter_walk *walk, int out, - unsigned int more) -{ - /* walk->data may be pointing the first byte of the next page; - however, we know we transfered at least one byte. So, - walk->data - 1 will be a virtual address in the mapped page. */ - - if (out) - flush_dcache_page(walk->page); - - if (more) { - walk->len_this_segment -= walk->len_this_page; - - if (walk->len_this_segment) { - walk->page++; - walk->len_this_page = min(walk->len_this_segment, - (unsigned)PAGE_CACHE_SIZE); - walk->offset = 0; - } else { - scatterwalk_start(walk, sg_next(walk->sg)); - } - } -} - -void scatterwalk_done(struct scatter_walk *walk, int out, int more) -{ - ngene_kunmap(walk->data, out); - if (walk->len_this_page == 0 || !more) - scatterwalk_pagedone(walk, out, more); -} - -/* - * Do not call this unless the total length of all of the fragments - * has been verified as multiple of the block size. - */ -int scatterwalk_copychunks(struct scatter_walk *walk, size_t nbytes, int out) -{ - walk->offset += nbytes; - walk->len_this_page -= nbytes; - walk->len_this_segment -= nbytes; - return 0; -} - -static void *vid_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -{ - struct ngene_channel *chan = priv; - struct ngene_buffer *item; - int wstrich, hstrich; - u8 *odd, *even; - u32 bpl = chan->tvnorms[chan->tvnorm].swidth * 2; - - struct scatter_walk walk_out; - const unsigned int bsize = PAGE_SIZE; - unsigned int nbytes; - int rest_of_buffer, ah, rwstrich; - - spin_lock(&chan->s_lock); - - if (list_empty(&chan->capture)) { - chan->evenbuffer = NULL; - goto out; - } - item = list_entry(chan->capture.next, struct ngene_buffer, vb.queue); - - if (chan->tvnorms[chan->tvnorm].sheight == 1080) - buf += 3840; - - odd = buf; - - hstrich = item->vb.height; - if (hstrich > chan->tvnorms[chan->tvnorm].sheight) - hstrich = chan->tvnorms[chan->tvnorm].sheight; - - wstrich = item->vb.width; - if (wstrich > chan->tvnorms[chan->tvnorm].swidth) - wstrich = chan->tvnorms[chan->tvnorm].swidth; - wstrich <<= 1; - - if (flags & BEF_EVEN_FIELD) { - chan->evenbuffer = buf; - if (chan->lastbufferflag) { - chan->lastbufferflag = 0; - if (chan->tvnorms[chan->tvnorm].sheight == 576) { - memcpy(buf + 413280, BlackLine, 1440); - memcpy(buf + 411840, BlackLine, 1440); - } - goto out; - } - } - chan->lastbufferflag = 1; - if (chan->evenbuffer) - even = chan->evenbuffer; - else - even = odd; - if (chan->tvnorms[chan->tvnorm].sheight == 576) { - memcpy(odd + 413280, BlackLine, 1440); - memcpy(odd + 411840, BlackLine, 1440); - } - nbytes = item->vb.dma.sglen * PAGE_SIZE; - scatterwalk_start(&walk_out, item->vb.dma.sglist); - ah = 0; - rwstrich = wstrich; - do { - u8 *dst_p; - - rest_of_buffer = bsize; - scatterwalk_map(&walk_out, 1); - dst_p = scatterwalk_whichbuf(&walk_out, bsize); - nbytes -= bsize; - scatterwalk_copychunks(&walk_out, bsize, 1); - - while (rest_of_buffer > 0 && ah < hstrich) { - if (rest_of_buffer >= rwstrich) { - if (ah % 2 == 0) { - memcpy(walk_out.data + - (bsize - rest_of_buffer), - odd, rwstrich); - odd += bpl - (wstrich - rwstrich); - } else { - memcpy(walk_out.data + - (bsize - rest_of_buffer), - even, rwstrich); - even += bpl - (wstrich - rwstrich); - } - rest_of_buffer -= rwstrich; - ah++; - rwstrich = wstrich; - } else { - if (ah % 2 == 0) { - memcpy(walk_out.data + - (bsize - rest_of_buffer), - odd, rest_of_buffer); - odd += rest_of_buffer; - } else { - memcpy(walk_out.data + - (bsize - rest_of_buffer), - even, rest_of_buffer); - even += rest_of_buffer; - } - rwstrich -= rest_of_buffer; - rest_of_buffer = 0; - } - } - scatterwalk_done(&walk_out, 1, nbytes); - } while (nbytes && ah < hstrich); - - { - struct timeval ts; - do_gettimeofday(&ts); - list_del(&item->vb.queue); - item->vb.state = STATE_DONE; - item->vb.ts = ts; - wake_up(&item->vb.done); - chan->evenbuffer = NULL; - } - -out: - spin_unlock(&chan->s_lock); - return 0; -} - -static void *snd_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -{ - struct ngene_channel *chan = priv; - struct mychip *mychip = chan->mychip; - - if (chan->audiomute == 0) - memcpy(chan->soundbuffer, (u8 *) buf, MAX_AUDIO_BUFFER_SIZE); - else - memset(chan->soundbuffer, 0, MAX_AUDIO_BUFFER_SIZE); - - if (mychip->substream != NULL) { - if (chan->sndbuffflag == 0) - chan->sndbuffflag = 1; - else - chan->sndbuffflag = 0; - spin_unlock(&mychip->lock); - snd_pcm_period_elapsed(mychip->substream); - spin_lock(&mychip->lock); - } - return 0; -} - -static void set_analog_transfer(struct ngene_channel *chan, int state) -{ - struct ngene_channel *ch; - u8 flags = 0; - - ch = &chan->dev->channel[chan->number + 2]; - /* printk(KERN_INFO "set_analog_transfer %d\n", state); */ - - if (1) { /* chan->tun_dec_rdy == 1){ */ - if (state) { - - chan->Capture1Length = - chan->tvnorms[chan->tvnorm].swidth * - chan->tvnorms[chan->tvnorm].sheight; - if (chan->tvnorms[chan->tvnorm].sheight == 576) - chan->nLines = 287; - else if (chan->tvnorms[chan->tvnorm].sheight == 1080) - chan->nLines = 541; - else - chan->nLines = - chan->tvnorms[chan->tvnorm].sheight / 2; - chan->nBytesPerLine = - chan->tvnorms[chan->tvnorm].swidth * 2; - if (chan->dev->card_info->io_type[chan->number] == - NGENE_IO_HDTV) { - chan->itumode = 2; - flags = SFLAG_ORDER_LUMA_CHROMA; - } else { - chan->itumode = 0; - flags = SFLAG_ORDER_LUMA_CHROMA; - } - chan->pBufferExchange = vid_exchange; - ngene_command_stream_control(chan->dev, chan->number, - 0x80, - SMODE_VIDEO_CAPTURE, - flags); - - ch->Capture1Length = MAX_AUDIO_BUFFER_SIZE; - ch->pBufferExchange = snd_exchange; - ngene_command_stream_control(ch->dev, ch->number, - 0x80, - SMODE_AUDIO_CAPTURE, 0); - ch->soundstreamon = 1; - } else { - ngene_command_stream_control(chan->dev, chan->number, - 0, 0, 0); - ngene_command_stream_control(ch->dev, ch->number, - 0, 0, 0); - ch->soundstreamon = 0; - } - } -} - -static int ngene_analog_start_feed(struct ngene_channel *chan) -{ - int freerunmode = 1; - struct i2c_adapter *adapter = &chan->i2c_adapter; - - if (chan->users == 0 && chan->number < 2) { - chan->evenbuffer = NULL; - chan->users = 1; - i2c_clients_command(adapter, IOCTL_MIC_DEC_FREESYNC, - &freerunmode); - msleep(25); - set_analog_transfer(chan, 1); - msleep(25); - freerunmode = 0; - i2c_clients_command(adapter, IOCTL_MIC_DEC_FREESYNC, - &freerunmode); - } - return chan->users; -} - -static int ngene_analog_stop_feed(struct ngene_channel *chan) -{ - int freerunmode = 1; - struct i2c_adapter *adapter = &chan->i2c_adapter; - if (chan->users == 1 && chan->number < 2) { - chan->users = 0; - i2c_clients_command(adapter, - IOCTL_MIC_DEC_FREESYNC, &freerunmode); - msleep(20); - set_analog_transfer(chan, 0); - } - return 0; -} - -/****************************************************************************/ -/* V4L2 API interface *******************************************************/ -/****************************************************************************/ - -void ngene_dma_free(struct videobuf_queue *q, - struct ngene_channel *chan, struct ngene_buffer *buf) -{ - videobuf_waiton(&buf->vb, 0, 0); - videobuf_dma_unmap(q, &buf->vb.dma); - videobuf_dma_free(&buf->vb.dma); - buf->vb.state = STATE_NEEDS_INIT; -} - -static int ngene_prepare_buffer(struct videobuf_queue *q, - struct ngene_channel *chan, - struct ngene_buffer *buf, - const struct ngene_format *fmt, - unsigned int width, unsigned int height, - enum v4l2_field field) -{ - int rc = 0; - /* check settings */ - if (NULL == fmt) - return -EINVAL; - - if (width < 48 || height < 32) - return -EINVAL; - - buf->vb.size = (width * height * 16 /* fmt->depth */) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - /* alloc + fill struct ngene_buffer (if changed) */ - if (buf->vb.width != width || buf->vb.height != height || - buf->vb.field != field || buf->fmt != fmt || - buf->tvnorm != chan->tvnorm) { - - buf->vb.width = width; - buf->vb.height = height; - buf->vb.field = field; - buf->tvnorm = chan->tvnorm; - buf->fmt = fmt; - - ngene_dma_free(q, chan, buf); - } - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - if (buf->vb.field == 0) - buf->vb.field = V4L2_FIELD_INTERLACED; - - if (STATE_NEEDS_INIT == buf->vb.state) { - buf->vb.width = width; - buf->vb.height = height; - buf->vb.field = field; - buf->tvnorm = chan->tvnorm; - buf->fmt = fmt; - - rc = videobuf_iolock(q, &buf->vb, &chan->fbuf); - if (0 != rc) - goto fail; - } - if (!buf->vb.dma.bus_addr) - videobuf_dma_sync(q, &buf->vb.dma); - buf->vb.state = STATE_PREPARED; - return 0; - -fail: - ngene_dma_free(q, chan, buf); - return rc; - -} - -static int buffer_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) -{ - struct ngene_vopen *vopen = q->priv_data; - *size = 2 * vopen->width * vopen->height; - if (0 == *count) - *count = gbuffers; - while (*size * *count > gbuffers * gbufsize) - (*count)--; - q->field = V4L2_FIELD_INTERLACED; - q->last = V4L2_FIELD_INTERLACED; - return 0; -} - -static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); - struct ngene_vopen *vopen = q->priv_data; - return ngene_prepare_buffer(q, vopen->ch, buf, vopen->fmt, - vopen->width, vopen->height, field); -} - -static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); - struct ngene_vopen *vopen = q->priv_data; - ngene_dma_free(q, vopen->ch, buf); -} - -static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct ngene_buffer *buf = container_of(vb, struct ngene_buffer, vb); - struct ngene_vopen *vopen = q->priv_data; - struct ngene_channel *chan = vopen->ch; - - buf->vb.state = STATE_QUEUED; - list_add_tail(&buf->vb.queue, &chan->capture); -} - -static struct videobuf_queue_ops ngene_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -int video_open(struct inode *inode, struct file *flip) -{ - struct ngene_vopen *vopen = NULL; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - struct video_device *vd = video_devdata(flip); - struct ngene_channel *chan = my_video_get_drvdata(vd); - - vopen = kmalloc(sizeof(*vopen), GFP_KERNEL); - if (!vopen) - return -ENOMEM; - memset(vopen, 0, sizeof(*vopen)); - flip->private_data = vopen; - v4l2_prio_open(&chan->prio, &vopen->prio); - vopen->ch = chan; - vopen->picxcount = 0; - vopen->type = type; - videobuf_queue_init(&vopen->vbuf_q, &ngene_video_qops, - chan->dev->pci_dev, &chan->s_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct ngene_buffer), vopen); - - vopen->ovfmt = ngene_formats; - chan->videousers++; - if (chan->dev->card_info->switch_ctrl) - chan->dev->card_info->switch_ctrl(chan, 2, 1); - return 0; -} - -int video_close(struct inode *inode, struct file *filp) -{ - struct ngene_vopen *vopen = filp->private_data; - struct ngene_channel *chan = vopen->ch; - - chan->videousers--; - if (!chan->videousers) { - if (chan->dev->card_info->switch_ctrl) - chan->dev->card_info->switch_ctrl(chan, 2, 0); - ngene_analog_stop_feed(chan); - } - videobuf_mmap_free(&vopen->vbuf_q); - v4l2_prio_close(&chan->prio, &vopen->prio); - filp->private_data = NULL; - kfree(vopen); - return 0; -} - -/****************************************************************************/ - -static int vid_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *parg) -{ - struct ngene_vopen *vopen = file->private_data; - struct ngene_channel *chan = vopen->ch; - struct ngene *dev = chan->dev; - struct i2c_adapter *adap = &chan->i2c_adapter; - int retval = 0; - int err = 0; - - switch (cmd) { - - case VIDIOC_S_CTRL: - { - struct v4l2_control *c = parg; - - err = v4l2_prio_check(&chan->prio, &vopen->prio); - if (err) - return err; - - if (c->id == V4L2_CID_AUDIO_MUTE) { - if (c->value) - (dev->channel[chan->number + 2]).audiomute = 1; - else - (dev->channel[chan->number + 2]).audiomute = 0; - return 0; - } - if (c->value != V4L2_CID_AUDIO_MUTE) - ngene_analog_stop_feed(chan); - i2c_clients_command(adap, cmd, parg); - return 0; - } - - case VIDIOC_S_TUNER: - { - err = v4l2_prio_check(&chan->prio, &vopen->prio); - if (err != 0) - return err; - i2c_clients_command(adap, cmd, parg); - return 0; - } - - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = parg; - u8 drxa = dev->card_info->demoda[chan->number]; - - if (chan->fe && chan->fe->ops.tuner_ops.set_frequency) - chan->fe->ops.tuner_ops. - set_frequency(chan->fe, f->frequency * 62500); - if (drxa) - ; - } - - case VIDIOC_S_INPUT: - { - err = v4l2_prio_check(&chan->prio, &vopen->prio); - if (err != 0) - return err; - i2c_clients_command(adap, cmd, parg); - return 0; - } - - case VIDIOC_G_STD: - { - v4l2_std_id *id = parg; - *id = chan->tvnorms[chan->tvnorm].v4l2_id; - return 0; - } - - case VIDIOC_S_STD: - { - v4l2_std_id *id = parg; - unsigned int i; - - err = v4l2_prio_check(&chan->prio, &vopen->prio); - if (err != 0) - return err; - ngene_analog_stop_feed(chan); - i2c_clients_command(adap, cmd, parg); - for (i = 0; i < chan->tvnorm_num; i++) - if (*id & chan->tvnorms[i].v4l2_id) - break; - if (i == chan->tvnorm_num) - return -EINVAL; - - chan->tvnorm = i; - mdelay(50); - ngene_analog_start_feed(chan); - return 0; - } - - case VIDIOC_G_FREQUENCY: - case VIDIOC_G_INPUT: - case VIDIOC_S_AUDIO: - case VIDIOC_G_AUDIO: - case VIDIOC_ENUMAUDIO: - case VIDIOC_S_MODULATOR: - case VIDIOC_G_MODULATOR: - case VIDIOC_G_CTRL: - { - i2c_clients_command(adap, cmd, parg); - return 0; - } - - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *tuner = parg; - if (tuner->index != 0) - return -EINVAL; - i2c_clients_command(adap, cmd, parg); - - if (chan->fe && chan->fe->ops.tuner_ops.get_status) { - u32 status; - - chan->fe->ops.tuner_ops.get_status(chan->fe, &status); - tuner->signal = status; - } - return 0; - } - - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *c = parg; - int i; - - if ((c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) && - (c->id < V4L2_CID_PRIVATE_BASE || - c->id >= V4L2_CID_PRIVATE_LASTP1)) - return -EINVAL; - for (i = 0; i < NGENE_CTLS; i++) - if (ngene_ctls[i].id == c->id) - break; - if (i == NGENE_CTLS) { - *c = no_ctl; - return 0; - } - *c = ngene_ctls[i]; - return 0; - } - - case VIDIOC_G_FMT: - { - struct v4l2_format *f = parg; - ngene_g_fmt(vopen, f); - } - - case VIDIOC_S_FMT: - { - struct v4l2_format *f = parg; - - ngene_analog_stop_feed(chan); - return ngene_s_fmt(vopen, chan, f); - } - - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = parg; - enum v4l2_buf_type type; - unsigned int i; - int index; - - type = f->type; - if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { - /* vbi - index = f->index; - if (0 != index) - return -EINVAL; - memset(f, 0, sizeof(*f)); - f->index = index; - f->type = type; - f->pixelformat = V4L2_PIX_FMT_GREY; - strcpy(f->description, "vbi data"); */ - return EINVAL; - } - - /* video capture + overlay */ - index = -1; - for (i = 0; i < NGENE_FORMATS; i++) { - if (ngene_formats[i].fourcc != -1) - index++; - if ((unsigned int)index == f->index) - break; - } - if (NGENE_FORMATS == i) - return -EINVAL; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - /* dprintk(KERN_DEBUG - "Video Overlay not supported yet.\n"); */ - return -EINVAL; - break; - default: - return -EINVAL; - } - memset(f, 0, sizeof(*f)); - f->index = index; - f->type = type; - f->pixelformat = ngene_formats[i].fourcc; - strlcpy(f->description, ngene_formats[i].name, - sizeof(f->description)); - return 0; - - } - - case VIDIOC_QUERYSTD: - { - v4l2_std_id *id = parg; - *id = V4L2_STD_625_50 | V4L2_STD_525_60; - return 0; - } - - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = parg; - unsigned int index = e->index; - - if (index >= chan->tvnorm_num) - return -EINVAL; - v4l2_video_std_construct(e, chan->tvnorms[e->index].v4l2_id, - chan->tvnorms[e->index].name); - e->index = index; - return 0; - } - - case VIDIOC_QUERYCAP: - { - static char driver[] = {'n', 'G', 'e', 'n', 'e', '\0'}; - static char card[] = {'M', 'k', '4', 'x', 'x', '\0'}; - struct v4l2_capability *cap = parg; - - memset(cap, 0, sizeof(*cap)); - if (dev->nr == 0) - card[3] = '0'; - else - card[3] = '1'; - if (chan->number) - card[4] = 'a'; - else - card[4] = 'b'; - strlcpy(cap->driver, driver, sizeof(cap->driver)); - strlcpy(cap->card, card, sizeof(cap->card)); - cap->bus_info[0] = 0; - cap->version = KERNEL_VERSION(0, 8, 1); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE| - V4L2_CAP_TUNER|V4L2_CAP_AUDIO| - V4L2_CAP_READWRITE|V4L2_CAP_STREAMING; - return 0; - } - - case VIDIOC_ENUMINPUT: - { - static char *inputname[2] = { - "AnalogTuner", - "S-Video" - }; - - struct v4l2_input *i = parg; - unsigned int index; - index = i->index; - - if (index > 1) - return -EINVAL; - - memset(i, 0, sizeof(*i)); - i->index = index; - strlcpy(i->name, inputname[index], sizeof(i->name)); - - i->type = index ? V4L2_INPUT_TYPE_CAMERA : - V4L2_INPUT_TYPE_TUNER; - i->audioset = 0; - i->tuner = 0; - i->std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M; - i->status = 0;/* V4L2_IN_ST_NO_H_LOCK; */ - return 0; - } - - case VIDIOC_G_PARM: - return -EINVAL; - - case VIDIOC_S_PARM: - return -EINVAL; - - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *prio = parg; - *prio = v4l2_prio_max(&chan->prio); - return 0; - } - - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *prio = parg; - return v4l2_prio_change(&chan->prio, &vopen->prio, *prio); - return 0; - } - - case VIDIOC_CROPCAP: - return -EINVAL; - - case VIDIOC_G_CROP: - return -EINVAL; - - case VIDIOC_S_CROP: - return -EINVAL; - - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *fb = parg; - - *fb = chan->fbuf; - fb->capability = 0; - if (vopen->ovfmt) - fb->fmt.pixelformat = vopen->ovfmt->fourcc; - return 0; - } - - case VIDIOC_REQBUFS: - return videobuf_reqbufs(ngene_queue(vopen), parg); - - case VIDIOC_QUERYBUF: - return videobuf_querybuf(ngene_queue(vopen), parg); - - case VIDIOC_QBUF: - return videobuf_qbuf(ngene_queue(vopen), parg); - - case VIDIOC_DQBUF: - return videobuf_dqbuf(ngene_queue(vopen), parg, - file->f_flags & O_NONBLOCK); - - case VIDIOC_S_FBUF: - { - /* ngene_analog_stop_feed(chan); */ - struct v4l2_framebuffer *fb = parg; - const struct ngene_format *fmt; - - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) - return -EPERM; - - /* check args */ - fmt = ngene_formats; /*format_by_fourcc(fb->fmt.pixelformat);*/ - if (NULL == fmt) - return -EINVAL; - - if (0 == (fmt->flags & 0x02 /*FORMAT_FLAGS_PACKED*/)) - return -EINVAL; - - mutex_lock(&vopen->vbuf_q.lock); - retval = -EINVAL; - - if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { - int maxLinesPerField; - - if (fb->fmt.width > - chan->tvnorms[chan->tvnorm].swidth) - goto vopen_unlock_and_return; - maxLinesPerField = chan->tvnorms[chan->tvnorm].sheight; - if (fb->fmt.height > maxLinesPerField) - goto vopen_unlock_and_return; - } - - /* ok, accept it */ - chan->fbuf.base = fb->base; - chan->fbuf.fmt.width = fb->fmt.width; - chan->fbuf.fmt.height = fb->fmt.height; - if (0 != fb->fmt.bytesperline) - chan->fbuf.fmt.bytesperline = fb->fmt.bytesperline; - else - chan->fbuf.fmt.bytesperline = - chan->fbuf.fmt.width * fmt->depth / 8; - - retval = 0; - vopen->ovfmt = fmt; - chan->init.ovfmt = fmt; - -vopen_unlock_and_return: - mutex_unlock(&vopen->vbuf_q.lock); - return retval; - - } - - case VIDIOC_ENUMOUTPUT: - return -EINVAL; - - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = parg; - return ngene_try_fmt(vopen, chan, f); - - } - - case VIDIOC_STREAMON: - { - int res = ngene_resource(vopen); - if (!check_alloc_res(chan, vopen, res)) - return -EBUSY; - ngene_analog_start_feed(chan); - return videobuf_streamon(ngene_queue(vopen)); - } - - case VIDIOC_STREAMOFF: - { - int res = ngene_resource(vopen); - int retval = videobuf_streamoff(ngene_queue(vopen)); - ngene_analog_stop_feed(chan); - if (retval < 0) - return retval; - - free_res(chan, vopen, res); - return 0; - } - - case VIDIOC_OVERLAY: - return -EINVAL; - - case VIDIOCGFBUF: - { - struct video_buffer *vb = parg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - - default: - err = -EINVAL; - break; - } - return err; -} - -/* -static int vid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, vid_do_ioctl); -} -*/ -static unsigned int video_fix_command(unsigned int cmd) -{ - switch (cmd) { - } - return cmd; -} - -static int vid_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - void *parg = (void *)arg, *pbuf = NULL; - char buf[64]; - int res = -EFAULT; - cmd = video_fix_command(cmd); - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - parg = buf; - if (_IOC_SIZE(cmd) > sizeof(buf)) { - pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (!pbuf) - return -ENOMEM; - parg = pbuf; - } - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) - goto error; - } - res = vid_do_ioctl(inode, file, cmd, parg); - if (res < 0) - goto error; - if (_IOC_DIR(cmd) & _IOC_READ) - if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) - res = -EFAULT; -error: - kfree(pbuf); - return res; -} - -static int ngene_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct ngene_vopen *vopen = file->private_data; - return videobuf_mmap_mapper(ngene_queue(vopen), vma); -} - -#define MAGIC_BUFFER 0x20040302 -void *my_videobuf_alloc(unsigned int size) -{ - struct videobuf_buffer *vb; - - vb = kmalloc(size, GFP_KERNEL); - if (NULL != vb) { - memset(vb, 0, size); - videobuf_dma_init(&vb->dma); - init_waitqueue_head(&vb->done); - vb->magic = MAGIC_BUFFER; - } - return vb; -} - -static ssize_t driver_read(struct file *file, char *user, - size_t count, loff_t *offset) -{ - char __user *data = user; - struct ngene_channel *chan; - int retval = 0; - struct videobuf_queue *q; - struct ngene_vopen *vopen = file->private_data; - int nonblocking = file->f_flags & O_NONBLOCK; - enum v4l2_field field; - unsigned long flags; - unsigned size, nbufs, bytes; - - if (!vopen) - return 0; - - chan = vopen->ch; - q = &vopen->vbuf_q; - - mutex_lock(&q->lock); - nbufs = 1; - size = 0; - q->ops->buf_setup(q, &nbufs, &size); - - if (NULL == q->read_buf) { - /* need to capture a new frame */ - retval = -ENOMEM; - q->read_buf = my_videobuf_alloc(q->msize); - if (NULL == q->read_buf) - goto done; - - q->read_buf->memory = V4L2_MEMORY_USERPTR; - field = V4L2_FIELD_INTERLACED; - retval = q->ops->buf_prepare(q, q->read_buf, field); - if (0 != retval) { - kfree(q->read_buf); - q->read_buf = NULL; - goto done; - } - - spin_lock_irqsave(q->irqlock, flags); - q->ops->buf_queue(q, q->read_buf); - spin_unlock_irqrestore(q->irqlock, flags); - q->read_off = 0; - } - - ngene_analog_start_feed(chan); - /* wait until capture is done */ - retval = videobuf_waiton(q->read_buf, nonblocking, 1); - if (0 != retval) - goto done; - videobuf_dma_sync(q, &q->read_buf->dma); - - if (STATE_ERROR == q->read_buf->state) { - /* catch I/O errors */ - q->ops->buf_release(q, q->read_buf); - kfree(q->read_buf); - q->read_buf = NULL; - retval = -EIO; - goto done; - } - - /* copy to userspace */ - bytes = count; - if (bytes > q->read_buf->size - q->read_off) - bytes = q->read_buf->size - q->read_off; - retval = -EFAULT; - - if (copy_to_user(data, q->read_buf->dma.vmalloc + q->read_off, bytes)) - goto done; - - retval = bytes; - - q->read_off += bytes; - if (q->read_off == q->read_buf->size) { - /* all data copied, cleanup */ - q->ops->buf_release(q, q->read_buf); - kfree(q->read_buf); - q->read_buf = NULL; - } - -done: - mutex_unlock(&q->lock); - - ngene_analog_stop_feed(chan); - - return retval; -} - -static unsigned int ngene_poll(struct file *file, poll_table *wait) -{ - struct ngene_vopen *vopen = file->private_data; - struct ngene_buffer *buf; - enum v4l2_field field; - - if (check_res(vopen, RESOURCE_VIDEO)) { - /* streaming capture */ - if (list_empty(&vopen->vbuf_q.stream)) - return POLLERR; - buf = list_entry(vopen->vbuf_q.stream.next, - struct ngene_buffer, vb.stream); - } else { - /* read() capture */ - mutex_lock(&vopen->vbuf_q.lock); - if (NULL == vopen->vbuf_q.read_buf) { - /* need to capture a new frame */ - if (locked_res(vopen->ch, RESOURCE_VIDEO)) { - mutex_unlock(&vopen->vbuf_q.lock); - return POLLERR; - } - vopen->vbuf_q.read_buf = - videobuf_alloc(vopen->vbuf_q.msize); - if (NULL == vopen->vbuf_q.read_buf) { - mutex_unlock(&vopen->vbuf_q.lock); - return POLLERR; - } - vopen->vbuf_q.read_buf->memory = V4L2_MEMORY_USERPTR; - field = videobuf_next_field(&vopen->vbuf_q); - if (0 != - vopen->vbuf_q.ops-> - buf_prepare(&vopen->vbuf_q, - vopen->vbuf_q.read_buf, field)) { - mutex_unlock(&vopen->vbuf_q.lock); - return POLLERR; - } - vopen->vbuf_q.ops->buf_queue(&vopen->vbuf_q, - vopen->vbuf_q.read_buf); - vopen->vbuf_q.read_off = 0; - } - mutex_unlock(&vopen->vbuf_q.lock); - buf = (struct ngene_buffer *)vopen->vbuf_q.read_buf; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == STATE_DONE || buf->vb.state == STATE_ERROR) - return POLLIN | POLLRDNORM; - return 0; -} - -static const struct file_operations ngene_fops = { - .owner = THIS_MODULE, - .read = driver_read, - .write = 0, - .open = video_open, - .release = video_close, - .ioctl = vid_ioctl, - .poll = ngene_poll, - .mmap = ngene_mmap, -}; - -static struct video_device ngene_cinfo = { - .name = "analog_Ngene", - .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_SCALES, - .fops = &ngene_fops, - .minor = -1, -}; - -void ngene_v4l2_remove(struct ngene_channel *chan) -{ - video_unregister_device(chan->v4l_dev); -} - -int ngene_v4l2_init(struct ngene_channel *chan) -{ - int ret = 0; - struct video_device *v_dev; - - chan->evenbuffer = NULL; - chan->dma_on = 0; - - v_dev = video_device_alloc(); - *v_dev = ngene_cinfo; - /* v_dev->dev = &(chan->dev->pci_dev->dev); */ - v_dev->release = video_device_release; - v_dev->minor = -1; - video_register_device(v_dev, VFL_TYPE_GRABBER, -1); - snprintf(v_dev->name, sizeof(v_dev->name), "AnalognGene%d", - v_dev->minor); - chan->v4l_dev = v_dev; - chan->minor = v_dev->minor; - printk(KERN_INFO "nGene V4L2 device video%d registered.\n", - v_dev->minor); - - v_dev->dev = &chan->device; - my_video_set_drvdata(chan->v4l_dev, chan); - - v4l2_prio_init(&chan->prio); - - if (chan->dev->card_info->io_type[chan->number] == NGENE_IO_HDTV) { - chan->tvnorms = ngene_tvnorms_hd; - chan->tvnorm_num = 1; - } else { - chan->tvnorms = ngene_tvnorms_sd; - chan->tvnorm_num = NGENE_TVNORMS; - } - chan->tvnorm = 0; - - spin_lock_init(&chan->s_lock); - init_MUTEX(&chan->reslock); - INIT_LIST_HEAD(&chan->capture); - chan->users = 0; - chan->videousers = 0; - chan->init.ov.w.width = 384; - chan->init.ov.w.height = 288; - chan->init.fmt = ngene_formats; - chan->init.width = 384; - chan->init.height = 288; - chan->tun_rdy = 0; - chan->dec_rdy = 0; - chan->tun_dec_rdy = 0; - chan->lastbufferflag = -1; - - if (chan->dev->card_info->avf[chan->number]) - avf4910a_attach(&chan->i2c_adapter, - chan->dev->card_info->avf[chan->number]); - - return ret; -} diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h index 15505c2b253..1c6f0e742ad 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/dvb/ngene/ngene.h @@ -857,17 +857,6 @@ struct ngene_buffer { }; #endif -int ngene_command_stream_control(struct ngene *dev, - u8 stream, u8 control, u8 mode, u8 flags); -int ngene_command_nop(struct ngene *dev); -int ngene_command_i2c_read(struct ngene *dev, u8 adr, - u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); -int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); -int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); -int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); -int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, - u16 lines, u16 bpl, u16 vblines, u16 vbibpl); - #endif -- cgit v1.2.3 From c58b5ecd46bf1b4a54b769d4a17afd97af23188d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 26 Dec 2009 16:56:26 -0300 Subject: V4L/DVB: [nGene] Trivial I2C related fixes/cleanups Trivial I2C related fixes/cleanups - Remove Unused I2C ID - point the I2C device to the physical device Signed-off-by: Manu Abraham Acked-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 6f1b0661814..1c86edd908f 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -828,9 +828,9 @@ static int ngene_i2c_init(struct ngene *dev, int dev_nr) strcpy(adap->name, "nGene"); - adap->id = I2C_HW_SAA7146; adap->algo = &ngene_i2c_algo; adap->algo_data = (void *)&(dev->channel[dev_nr]); + adap->dev.parent = &dev->pci_dev->dev; mutex_init(&adap->bus_lock); return i2c_add_adapter(adap); -- cgit v1.2.3 From edad22a7b0e5899ee503794543ce4c77cfb34d58 Mon Sep 17 00:00:00 2001 From: Matthias Benesch Date: Fri, 8 Jan 2010 17:38:03 -0300 Subject: V4L/DVB: ngene: Mystique SaTiX-S2 Dual Identify card 18c3:db01 as 'Mystique SaTiX-S2 Dual'. Signed-off-by: Matthias Benesch Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 1c86edd908f..31f32b8bc4b 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1897,12 +1897,25 @@ static struct ngene_info ngene_info_mps2 = { .fw_version = 17, }; +static struct ngene_info ngene_info_satixs2 = { + .type = NGENE_SIDEWINDER, + .name = "Mystique SaTiX-S2 Dual", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, + .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, + .fe_config = {&fe_mps2, &fe_mps2}, + .tuner_config = {&tuner_mps2_0, &tuner_mps2_1}, + .lnb = {0x0b, 0x08}, + .tsf = {3, 3}, + .fw_version = 17, +}; + /****************************************************************************/ /****************************************************************************/ -/****************************************************************************/ +/* PCI Subsystem ID *********************************************************/ /****************************************************************************/ #define NGENE_ID(_subvend, _subdev, _driverdata) { \ @@ -1915,7 +1928,7 @@ static struct ngene_info ngene_info_mps2 = { static const struct pci_device_id ngene_id_tbl[] __devinitdata = { NGENE_ID(0x18c3, 0xabc3, ngene_info_mps2), NGENE_ID(0x18c3, 0xabc4, ngene_info_mps2), - NGENE_ID(0x18c3, 0xdb01, ngene_info_mps2), + NGENE_ID(0x18c3, 0xdb01, ngene_info_satixs2), {0} }; MODULE_DEVICE_TABLE(pci, ngene_id_tbl); -- cgit v1.2.3 From 83e74554d4b1c6f4906c8a4fff270fcd42978987 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Mon, 1 Feb 2010 22:01:31 -0300 Subject: V4L/DVB: ngene: Adapt to current frontend drivers Adapt to current stv090x + stv6110 drivers. [mchehab@redhat.com: removed compilation hack added by me on a prev patch] Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 31f32b8bc4b..42506dc2e70 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1853,7 +1853,6 @@ static struct stv090x_config fe_mps2 = { .xtal = 27000000, .address = 0x68, -// .ref_clk = 27000000, .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, @@ -1861,27 +1860,18 @@ static struct stv090x_config fe_mps2 = { .repeater_level = STV090x_RPTLEVEL_16, .diseqc_envelope_mode = true, - - .tuner_init = NULL, - .tuner_set_mode = NULL, - .tuner_set_frequency = NULL, - .tuner_get_frequency = NULL, - .tuner_set_bandwidth = NULL, - .tuner_get_bandwidth = NULL, - .tuner_set_bbgain = NULL, - .tuner_get_bbgain = NULL, - .tuner_set_refclk = NULL, - .tuner_get_status = NULL, }; static struct stv6110x_config tuner_mps2_0 = { .addr = 0x60, .refclk = 27000000, + .clk_div = 1, }; static struct stv6110x_config tuner_mps2_1 = { .addr = 0x63, .refclk = 27000000, + .clk_div = 1, }; static struct ngene_info ngene_info_mps2 = { -- cgit v1.2.3 From 589816c61b74d8f16218a5ffdb95b1bf1897f65c Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 20 Jan 2010 17:53:06 -0300 Subject: V4L/DVB: ngene: Set ADC ranges to 1Vpp Set ADC1 and ADC2 range of the stv0900 to 1Vpp. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 42506dc2e70..15d91f2ac5f 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1859,6 +1859,9 @@ static struct stv090x_config fe_mps2 = { .repeater_level = STV090x_RPTLEVEL_16, + .adc1_range = STV090x_ADC_1Vpp, + .adc2_range = STV090x_ADC_1Vpp, + .diseqc_envelope_mode = true, }; -- cgit v1.2.3 From b1ec9532341fafacfce8b1951c5f388eae014e16 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 20 Jan 2010 18:06:51 -0300 Subject: V4L/DVB: ngene: Workaround for command timeout Implement workaround for comamnd timeout. Use FW15 and avoid switching DMA on and off. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 50 +++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 15d91f2ac5f..fd665912dec 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -59,6 +59,8 @@ MODULE_PARM_DESC(debug, "Print debugging information."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +#define COMMAND_TIMEOUT_WORKAROUND + #define dprintk if (debug) printk #define DEVICE_NAME "ngene" @@ -258,6 +260,27 @@ static irqreturn_t irq_handler(int irq, void *dev_id) /* nGene command interface **************************************************/ /****************************************************************************/ +static void dump_command_io(struct ngene *dev) +{ + u8 buf[8], *b; + + ngcpyfrom(buf, HOST_TO_NGENE, 8); + printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", + HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + + ngcpyfrom(buf, NGENE_TO_HOST, 8); + printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", + NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + + b = dev->hosttongene; + printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", + b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + + b = dev->ngenetohost; + printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", + b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); +} + static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) { int ret; @@ -310,6 +333,7 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) printk(KERN_ERR DEVICE_NAME ": Command timeout cmd=%02x prev=%02x\n", com->cmd.hdr.Opcode, dev->prev_cmd); + dump_command_io(dev); return -1; } if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) @@ -856,7 +880,10 @@ static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) struct ngene_channel *chan = priv; - dvb_dmx_swfilter(&chan->demux, buf, len); +#ifdef COMMAND_TIMEOUT_WORKAROUND + if (chan->users > 0) +#endif + dvb_dmx_swfilter(&chan->demux, buf, len); return 0; } @@ -890,11 +917,6 @@ static void set_transfer(struct ngene_channel *chan, int state) struct ngene *dev = chan->dev; int ret; - /* - if (chan->running) - return; - */ - /* printk(KERN_INFO DEVICE_NAME ": st %d\n", state); msleep(100); @@ -962,7 +984,10 @@ static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct ngene_channel *chan = dvbdmx->priv; if (chan->users == 0) { - set_transfer(chan, 1); +#ifdef COMMAND_TIMEOUT_WORKAROUND + if (!chan->running) +#endif + set_transfer(chan, 1); /* msleep(10); */ } @@ -977,7 +1002,9 @@ static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (--chan->users) return chan->users; +#ifndef COMMAND_TIMEOUT_WORKAROUND set_transfer(chan, 0); +#endif return 0; } @@ -1683,6 +1710,11 @@ static void release_channel(struct ngene_channel *chan) struct ngene_info *ni = dev->card_info; int io = ni->io_type[chan->number]; +#ifdef COMMAND_TIMEOUT_WORKAROUND + if (chan->running) + set_transfer(chan, 0); +#endif + tasklet_kill(&chan->demux_tasklet); if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { @@ -1887,7 +1919,7 @@ static struct ngene_info ngene_info_mps2 = { .tuner_config = {&tuner_mps2_0, &tuner_mps2_1}, .lnb = {0x0b, 0x08}, .tsf = {3, 3}, - .fw_version = 17, + .fw_version = 15, }; static struct ngene_info ngene_info_satixs2 = { @@ -1900,7 +1932,7 @@ static struct ngene_info ngene_info_satixs2 = { .tuner_config = {&tuner_mps2_0, &tuner_mps2_1}, .lnb = {0x0b, 0x08}, .tsf = {3, 3}, - .fw_version = 17, + .fw_version = 15, }; /****************************************************************************/ -- cgit v1.2.3 From ace30f74ac1b3f20ab8f98995510a5e0d643c42c Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 20 Jan 2010 19:03:22 -0300 Subject: V4L/DVB: ngene: Take care of late interrupts Request might already have been processed when the interrupt arrives. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index fd665912dec..389204b7df1 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -253,7 +253,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) spin_unlock(&dev->channel[i].state_lock); } - return rc; + /* Request might have been processed by a previous call. */ + return IRQ_HANDLED; } /****************************************************************************/ -- cgit v1.2.3 From e890e7c0426ab99b032d5b387b1ca9fad6928895 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 3 Feb 2010 13:57:58 -0300 Subject: V4L/DVB: ngene: Use correct name for cineS2 cards Cards 18c3:abc3/18c3:abc4 should be displayed as 'Linux4Media cineS2'. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 389204b7df1..1bb9bc78573 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1879,7 +1879,7 @@ fail0: /* Card configs *************************************************************/ /****************************************************************************/ -static struct stv090x_config fe_mps2 = { +static struct stv090x_config fe_cineS2 = { .device = STV0900, .demod_mode = STV090x_DUAL, .clk_mode = STV090x_CLK_EXT, @@ -1898,26 +1898,26 @@ static struct stv090x_config fe_mps2 = { .diseqc_envelope_mode = true, }; -static struct stv6110x_config tuner_mps2_0 = { +static struct stv6110x_config tuner_cineS2_0 = { .addr = 0x60, .refclk = 27000000, .clk_div = 1, }; -static struct stv6110x_config tuner_mps2_1 = { +static struct stv6110x_config tuner_cineS2_1 = { .addr = 0x63, .refclk = 27000000, .clk_div = 1, }; -static struct ngene_info ngene_info_mps2 = { +static struct ngene_info ngene_info_cineS2 = { .type = NGENE_SIDEWINDER, - .name = "Media-Pointer MP-S2/CineS2 DVB-S2 Twin Tuner", + .name = "Linux4Media cineS2 DVB-S2 Twin Tuner", .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, - .fe_config = {&fe_mps2, &fe_mps2}, - .tuner_config = {&tuner_mps2_0, &tuner_mps2_1}, + .fe_config = {&fe_cineS2, &fe_cineS2}, + .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, .lnb = {0x0b, 0x08}, .tsf = {3, 3}, .fw_version = 15, @@ -1929,8 +1929,8 @@ static struct ngene_info ngene_info_satixs2 = { .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, - .fe_config = {&fe_mps2, &fe_mps2}, - .tuner_config = {&tuner_mps2_0, &tuner_mps2_1}, + .fe_config = {&fe_cineS2, &fe_cineS2}, + .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, .lnb = {0x0b, 0x08}, .tsf = {3, 3}, .fw_version = 15, @@ -1952,8 +1952,8 @@ static struct ngene_info ngene_info_satixs2 = { /****************************************************************************/ static const struct pci_device_id ngene_id_tbl[] __devinitdata = { - NGENE_ID(0x18c3, 0xabc3, ngene_info_mps2), - NGENE_ID(0x18c3, 0xabc4, ngene_info_mps2), + NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), + NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), NGENE_ID(0x18c3, 0xdb01, ngene_info_satixs2), {0} }; -- cgit v1.2.3 From 684688d87d697724c46be77858641ee2e8885b02 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 3 Feb 2010 18:59:20 -0300 Subject: V4L/DVB: ngene: Make checkpatch.pl happy Make checkpatch.pl happy. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 20 +++++++++++--------- drivers/media/dvb/ngene/ngene.h | 15 +++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 1bb9bc78573..1b53482f6e7 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -267,11 +267,13 @@ static void dump_command_io(struct ngene *dev) ngcpyfrom(buf, HOST_TO_NGENE, 8); printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", - HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); ngcpyfrom(buf, NGENE_TO_HOST, 8); printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", - NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); b = dev->hosttongene; printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", @@ -1198,7 +1200,7 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev, * sizeof(struct HW_SCATTER_GATHER_ELEMENT); u64 PASCListMem; - PHW_SCATTER_GATHER_ELEMENT SCListEntry; + struct HW_SCATTER_GATHER_ELEMENT *SCListEntry; u64 PASCListEntry; struct SBufferHeader *Cur; void *SCListMem; @@ -1220,7 +1222,7 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev, pRingBuffer->Buffer1Length = Buffer1Length; pRingBuffer->Buffer2Length = Buffer2Length; - SCListEntry = (PHW_SCATTER_GATHER_ELEMENT) SCListMem; + SCListEntry = SCListMem; PASCListEntry = PASCListMem; Cur = pRingBuffer->Head; @@ -1611,10 +1613,10 @@ static int ngene_start(struct ngene *dev) goto fail; if (dev->card_info->fw_version == 17) { - u8 tsin4_config[6] = - {3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; - u8 default_config[6] = - {4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0}; + u8 tsin4_config[6] = { + 3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; + u8 default_config[6] = { + 4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0}; u8 *bconf = default_config; if (dev->card_info->io_type[3] == NGENE_IO_TSIN) diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h index 1c6f0e742ad..a7eb2984631 100644 --- a/drivers/media/dvb/ngene/ngene.h +++ b/drivers/media/dvb/ngene/ngene.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include @@ -200,8 +200,6 @@ struct EVENT_BUFFER { u32 Reserved[2]; } __attribute__ ((__packed__)); -typedef struct EVENT_BUFFER *PEVENT_BUFFER; - /* Firmware commands. */ enum OPCODES { @@ -488,18 +486,15 @@ struct ngene_command { #define EVENT_QUEUE_SIZE 16 -typedef struct HW_SCATTER_GATHER_ELEMENT *PHW_SCATTER_GATHER_ELEMENT; -typedef struct FWRB *PFWRB; - /* Gathers the current state of a single channel. */ struct SBufferHeader { struct BUFFER_HEADER ngeneBuffer; /* Physical descriptor */ struct SBufferHeader *Next; void *Buffer1; - PHW_SCATTER_GATHER_ELEMENT scList1; + struct HW_SCATTER_GATHER_ELEMENT *scList1; void *Buffer2; - PHW_SCATTER_GATHER_ELEMENT scList2; + struct HW_SCATTER_GATHER_ELEMENT *scList2; }; /* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */ @@ -554,7 +549,7 @@ enum BufferExchangeFlags { typedef void *(IBufferExchange)(void *, void *, u32, u32, u32); -typedef struct { +struct MICI_STREAMINFO { IBufferExchange *pExchange; IBufferExchange *pExchangeVBI; /* Secondary (VBI, ancillary) */ u8 Stream; @@ -566,7 +561,7 @@ typedef struct { u16 nLinesVBI; u16 nBytesPerLineVBI; u32 CaptureLength; /* Used for audio and transport stream */ -} MICI_STREAMINFO, *PMICI_STREAMINFO; +}; /****************************************************************************/ /* STRUCTS ******************************************************************/ -- cgit v1.2.3 From 6525e67c01d303153272c26cb8118a3c314f4a1f Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Wed, 3 Feb 2010 22:06:15 -0300 Subject: V4L/DVB: ngene: Fix I2C initialisation Use I2C_CLASS_TV_DIGITAL, not I2C_ADAP_CLASS_TV_DIGITAL. Remove initialisation of bus_lock mutex. Thanks to Mauro for pointing out. Signed-off-by: Oliver Endriss Thanks-to: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 1b53482f6e7..ea610e4b571 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -847,11 +847,7 @@ static int ngene_i2c_init(struct ngene *dev, int dev_nr) struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); i2c_set_adapdata(adap, &(dev->channel[dev_nr])); -#ifdef I2C_ADAP_CLASS_TV_DIGITAL - adap->class = I2C_ADAP_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; -#else - adap->class = I2C_CLASS_TV_ANALOG; -#endif + adap->class = I2C_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; strcpy(adap->name, "nGene"); @@ -859,7 +855,6 @@ static int ngene_i2c_init(struct ngene *dev, int dev_nr) adap->algo_data = (void *)&(dev->channel[dev_nr]); adap->dev.parent = &dev->pci_dev->dev; - mutex_init(&adap->bus_lock); return i2c_add_adapter(adap); } -- cgit v1.2.3 From 6fd2d0f924e352e50a35ac9d9534ccc91b5c9bb9 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 5 Feb 2010 02:46:47 -0300 Subject: V4L/DVB: using vmalloc requires include linux/vmalloc.h After merging the scsi-post-merge tree, today's linux-next build (powerpc allyesconfig) failed like this: drivers/media/dvb/ngene/ngene-core.c: In function 'ngene_release_buffers': drivers/media/dvb/ngene/ngene-core.c:1443: error: implicit declaration of function 'vfree' drivers/media/dvb/ngene/ngene-core.c: In function 'ngene_get_buffers': drivers/media/dvb/ngene/ngene-core.c:1454: error: implicit declaration of function 'vmalloc' drivers/media/dvb/ngene/ngene-core.c:1454: warning: assignment makes pointer from integer without a cast drivers/media/dvb/ngene/ngene-core.c:1461: warning: assignment makes pointer from integer without a cast drivers/media/dvb/ngene/ngene-core.c:1467: warning: assignment makes pointer from integer without a cast drivers/media/dvb/ngene/ngene-core.c: In function 'ngene_probe': drivers/media/dvb/ngene/ngene-core.c:1836: warning: assignment makes pointer from integer without a cast Caused by commit b54c755d6263efe376f3dfc8c72c8e7b4fb4f4c1 ("V4L/DVB: ngene: Initial check-in"). Signed-off-by: Stephen Rothwell Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index ea610e4b571..cb5982ed850 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "ngene.h" -- cgit v1.2.3 From fad93fdb14f13e7b869a878c0fba3b6e0f91e0b6 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sat, 6 Feb 2010 05:55:47 -0300 Subject: V4L/DVB: STV0900 Cut 3.0 AGC2 fix for NetUP Dual DVB-S2-CI card if the AGC2 > 1400 then no signal on this frequency for STV0900 Cut 3.0. For Cut 2.0 this value is 700. Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_sw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index 96a5a5e29ed..ba0709b2d43 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c @@ -1230,6 +1230,9 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1; result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS); + + dprintk("%s: modcode=0x%x \n", __func__, result->modcode); + switch (result->standard) { case STV0900_DVBS2_STANDARD: result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD); @@ -1634,7 +1637,8 @@ static int stv0900_blind_search_algo(struct dvb_frontend *fe) agc2_int = stv0900_blind_check_agc2_min_level(intp, demod); - if (agc2_int > STV0900_BLIND_SEARCH_AGC2_TH) + dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th); + if (agc2_int > agc2_th) return FALSE; if (intp->chip_id == 0x10) -- cgit v1.2.3 From f0289efa1938eac27a98883bf33af946b13e1110 Mon Sep 17 00:00:00 2001 From: Klaas de Waal Date: Sun, 7 Feb 2010 14:09:16 -0300 Subject: V4L/DVB: dst: fixes for DVB-C Twinhan VP2031 Remove check "state->dst_type == DST_DTYPE_IS_CABLE" in function dst_get_tuna (around line 1352) to select the correct checksum computation Fill in the .caps field in struct dst_dvbc_ops (around line 1824) with all the supported QAM modulation methods to match the capabilities of the card as implemented in function dst_set_modulation (around line 502). Note that beginning with linux kernel version 2.6.32 the modulation method is checked (by function dvb_frontend_check_parameters in file drivers/media/dvb/dvb-core/dvb_frontend.c) and thus tuning fails if you use a modulation method that is not present in the .caps field. This patch has been tested on a Twinhan VP2031A DVB-C card with the 2.6.32.2 kernel. Signed-off-by: Klaas de Waal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 91353a6faf1..8b0cde38984 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1352,8 +1352,7 @@ static int dst_get_tuna(struct dst_state *state) return retval; } if ((state->type_flags & DST_TYPE_HAS_VLF) && - !(state->dst_type == DST_TYPE_IS_CABLE) && - !(state->dst_type == DST_TYPE_IS_ATSC)) { + !(state->dst_type == DST_TYPE_IS_ATSC)) { if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { dprintk(verbose, DST_INFO, 1, "checksum failure ? "); @@ -1820,8 +1819,13 @@ static struct dvb_frontend_ops dst_dvbc_ops = { .frequency_max = 858000000, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, - /* . symbol_rate_tolerance = ???,*/ - .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO + .caps = FE_CAN_FEC_AUTO | + FE_CAN_QAM_AUTO | + FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 }, .release = dst_release, -- cgit v1.2.3 From 62bdbb735c0415c2ffdddc2269a860a76f7f716a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 6 Feb 2010 05:43:58 -0300 Subject: V4L/DVB: drivers/media: Correct NULL test In each case, the NULL test has been performed already. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ expression *x; expression e; identifier l; @@ if (x == NULL || ...) { ... when forall return ...; } ... when != goto l; when != x = e when != &x *x == NULL // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stv0900_core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index e5791b2b913..01f8f1f802f 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -1417,11 +1417,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, return error; } - if (state->internal == NULL) { - error = STV0900_INVALID_HANDLE; - return error; - } - intp = state->internal; intp->demod_mode = p_init->demod_mode; -- cgit v1.2.3 From fd9be0dc9b0b2baf203cfef8c8109859d05d0e01 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 10 Feb 2010 20:32:42 -0300 Subject: V4L/DVB: DVB: ngene, fix memset parameters Switch second and third memset parameter to stamp the length buffer bytes by 0xff's, not 255 bytes by low 8 bits of Length. Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, jirislaby@gmail.com, Matthias Benesch , Ralph Metzler , Oliver Endriss Signed-off-by: Jiri Slaby Cc: Matthias Benesch Cc: Ralph Metzler Cc: Oliver Endriss Cc: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ngene/ngene-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index cb5982ed850..0150dfe7cfb 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -564,7 +564,7 @@ static void FillTSBuffer(void *Buffer, int Length, u32 Flags) { u32 *ptr = Buffer; - memset(Buffer, Length, 0xff); + memset(Buffer, 0xff, Length); while (Length > 0) { if (Flags & DF_SWAP32) *ptr = 0x471FFF10; -- cgit v1.2.3 From fa1df55c3f99d32eccf3eeb3c9dad4456ebcf1f4 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Feb 2010 20:05:48 -0300 Subject: V4L/DVB: af9015: support for DigitalNow TinyTwin v2 Add USB ID 1b80:e402 for DigitalNow TinyTwin version 2. Thanks to Trevor Phillips for reporting this. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 4 +++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 47ab2e92c6a..10aaedc0142 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1291,6 +1291,7 @@ static struct usb_device_id af9015_usb_table[] = { /* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1377,7 +1378,8 @@ static struct dvb_usb_device_properties af9015_properties[] = { }, { .name = "DigitalNow TinyTwin DVB-T Receiver", - .cold_ids = {&af9015_usb_table[5], NULL}, + .cold_ids = {&af9015_usb_table[5], + &af9015_usb_table[28], NULL}, .warm_ids = {NULL}, }, { diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 90cdac7ccd8..19e2c98002c 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -138,6 +138,7 @@ #define USB_PID_TWINHAN_VP7021_COLD 0x3207 #define USB_PID_TWINHAN_VP7021_WARM 0x3208 #define USB_PID_TINYTWIN 0x3226 +#define USB_PID_TINYTWIN_2 0xe402 #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 -- cgit v1.2.3 From 809c1e8ae8310a863b147c8571adfb6addeddd43 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Feb 2010 20:07:30 -0300 Subject: V4L/DVB: af9015: support for Leadtek WinFast DTV2000DS Add USB ID 0413:6a04 for Leadtek WinFast DTV2000DS. Thanks to Gavin Ramm for reporting this. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 8 +++++++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 10aaedc0142..d265ae677c0 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1292,6 +1292,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, + {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1564,7 +1565,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 6, /* max 9 */ + .num_device_descs = 7, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", @@ -1598,6 +1599,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[27], NULL}, .warm_ids = {NULL}, }, + { + .name = "Leadtek WinFast DTV2000DS", + .cold_ids = {&af9015_usb_table[29], NULL}, + .warm_ids = {NULL}, + }, } }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 19e2c98002c..250ebf9fd6b 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -250,6 +250,7 @@ #define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361 #define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6 #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 +#define USB_PID_WINFAST_DTV2000DS 0x6a04 #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 -- cgit v1.2.3 From db02d9dc544be25330fe491eddd2766d1fb7e325 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Feb 2010 20:20:41 -0300 Subject: V4L/DVB: af9015: A-Link DTU(m) remote autodetection Autodetect A-Link DTU(m) based eeprom hash and select correct remote. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index d265ae677c0..b926473363e 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -792,6 +792,9 @@ static const struct af9015_setup af9015_setup_hashes[] = { { 0xb8feb708, af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, + { 0xa3703d00, + af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), + af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, { } }; -- cgit v1.2.3 From 58c811df63a7c494639b4fe49d7af8fd0b32019b Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Feb 2010 20:44:12 -0300 Subject: V4L/DVB: af9015: MYGICTV U718 remote autodetection Autodetect MYGICTV U718 from eeprom hash and select remote automatically. Remove old iManufacturer string compare based remote selection logic. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index b926473363e..00b8e2a8228 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -795,6 +795,9 @@ static const struct af9015_setup af9015_setup_hashes[] = { { 0xa3703d00, af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, + { 0x9b7dc64e, + af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv), + af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, { } }; @@ -823,13 +826,7 @@ static void af9015_set_remote_config(struct usb_device *udev, memset(manufacturer, 0, sizeof(manufacturer)); usb_string(udev, udev->descriptor.iManufacturer, manufacturer, sizeof(manufacturer)); - if (!strcmp("Geniatech", manufacturer)) { - /* iManufacturer 1 Geniatech - iProduct 2 AF9015 */ - table = af9015_setup_match( - AF9015_REMOTE_MYGICTV_U718, - af9015_setup_modparam); - } else if (!strcmp("MSI", manufacturer)) { + if (!strcmp("MSI", manufacturer)) { /* iManufacturer 1 MSI iProduct 2 MSI K-VOX */ table = af9015_setup_match( -- cgit v1.2.3 From 8ef4c21130832cb51d5a5940ad3d4b7140720218 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 10 Feb 2010 21:33:12 -0300 Subject: V4L/DVB: af901x: inform NXP TDA18218 tuner as know but not supported There is no driver for new NXP TDA18218 tuner which is used by few recent af9015 designs. af9015 uses number 179 as ID for that tuner. Inform this tuner is not supported when device using that tuner is meet. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 3 +++ drivers/media/dvb/frontends/af9013.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 00b8e2a8228..d7975383d31 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1002,6 +1002,9 @@ static int af9015_read_config(struct usb_device *udev) af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; af9015_af9013_config[i].rf_spec_inv = 1; break; + case AF9013_TUNER_TDA18218: + warn("tuner NXP TDA18218 not supported yet"); + return -ENODEV; default: warn("tuner id:%d not supported, please report!", val); return -ENODEV; diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h index 28b90c91c76..e90fa92b1c1 100644 --- a/drivers/media/dvb/frontends/af9013.h +++ b/drivers/media/dvb/frontends/af9013.h @@ -44,6 +44,7 @@ enum af9013_tuner { AF9013_TUNER_MT2060_2 = 147, /* Microtune */ AF9013_TUNER_TDA18271 = 156, /* NXP */ AF9013_TUNER_QT1010A = 162, /* Quantek */ + AF9013_TUNER_TDA18218 = 179, /* NXP */ }; /* AF9013/5 GPIOs (mostly guessed) -- cgit v1.2.3 From 76f9a820c8672ada12ffa0903652c9e6f2429462 Mon Sep 17 00:00:00 2001 From: Adams Xu Date: Sun, 14 Feb 2010 14:34:07 -0300 Subject: V4L/DVB: AZ6027: Initial import of the driver Signed-off-by: Manu Abaraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 1130 ++++++++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-usb/az6027.h | 14 + 2 files changed, 1144 insertions(+) create mode 100644 drivers/media/dvb/dvb-usb/az6027.c create mode 100644 drivers/media/dvb/dvb-usb/az6027.h (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c new file mode 100644 index 00000000000..3865c928b01 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -0,0 +1,1130 @@ +/* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027) + * receiver. + * + * Copyright (C) 2009 Adams.Xu + * + * 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. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#include "az6027.h" +/* Demodulator */ +#include "stb0899_drv.h" +#include "stb0899_reg.h" +#include "stb0899_cfg.h" +/* Tuner */ +#include "stb6100.h" +#include "stb6100_cfg.h" +#include "dvb_ca_en50221.h" + +/* debug */ +int dvb_usb_az6027_debug; +module_param_named(debug,dvb_usb_az6027_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +struct az6027_device_state { + struct dvb_ca_en50221 ca; + struct mutex ca_mutex; + u8 power_state; +}; + +static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = { + +// 0x0000000b , /* SYSREG */ + { STB0899_DEV_ID , 0x30 }, + { STB0899_DISCNTRL1 , 0x32 }, + { STB0899_DISCNTRL2 , 0x80 }, + { STB0899_DISRX_ST0 , 0x04 }, + { STB0899_DISRX_ST1 , 0x00 }, + { STB0899_DISPARITY , 0x00 }, + { STB0899_DISFIFO , 0x00 }, + { STB0899_DISSTATUS , 0x20 }, + { STB0899_DISF22 , 0x99 }, + { STB0899_DISF22RX , 0xa8 }, + //SYSREG ? + { STB0899_ACRPRESC , 0x11 }, + { STB0899_ACRDIV1 , 0x0a }, + { STB0899_ACRDIV2 , 0x05 }, + { STB0899_DACR1 , 0x00 }, + { STB0899_DACR2 , 0x00 }, + { STB0899_OUTCFG , 0x00 }, + { STB0899_MODECFG , 0x00 }, + { STB0899_IRQSTATUS_3 , 0xfe }, + { STB0899_IRQSTATUS_2 , 0x03 }, + { STB0899_IRQSTATUS_1 , 0x7c }, + { STB0899_IRQSTATUS_0 , 0xf4 }, + { STB0899_IRQMSK_3 , 0xf3 }, + { STB0899_IRQMSK_2 , 0xfc }, + { STB0899_IRQMSK_1 , 0xff }, + { STB0899_IRQMSK_0 , 0xff }, + { STB0899_IRQCFG , 0x00 }, + { STB0899_I2CCFG , 0x88 }, + { STB0899_I2CRPT , 0x58 }, + { STB0899_IOPVALUE5 , 0x00 }, + { STB0899_IOPVALUE4 , 0x33 }, + { STB0899_IOPVALUE3 , 0x6d }, + { STB0899_IOPVALUE2 , 0x90 }, + { STB0899_IOPVALUE1 , 0x60 }, + { STB0899_IOPVALUE0 , 0x00 }, + { STB0899_GPIO00CFG , 0x82 }, + { STB0899_GPIO01CFG , 0x82 }, + { STB0899_GPIO02CFG , 0x82 }, + { STB0899_GPIO03CFG , 0x82 }, + { STB0899_GPIO04CFG , 0x82 }, + { STB0899_GPIO05CFG , 0x82 }, + { STB0899_GPIO06CFG , 0x82 }, + { STB0899_GPIO07CFG , 0x82 }, + { STB0899_GPIO08CFG , 0x82 }, + { STB0899_GPIO09CFG , 0x82 }, + { STB0899_GPIO10CFG , 0x82 }, + { STB0899_GPIO11CFG , 0x82 }, + { STB0899_GPIO12CFG , 0x82 }, + { STB0899_GPIO13CFG , 0x82 }, + { STB0899_GPIO14CFG , 0x82 }, + { STB0899_GPIO15CFG , 0x82 }, + { STB0899_GPIO16CFG , 0x82 }, + { STB0899_GPIO17CFG , 0x82 }, + { STB0899_GPIO18CFG , 0x82 }, + { STB0899_GPIO19CFG , 0x82 }, + { STB0899_GPIO20CFG , 0x82 }, + { STB0899_SDATCFG , 0xb8 }, + { STB0899_SCLTCFG , 0xba }, + { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */ + { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ + { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ + { STB0899_DIRCLKCFG , 0x82 }, + { STB0899_CLKOUT27CFG , 0x7e }, + { STB0899_STDBYCFG , 0x82 }, + { STB0899_CS0CFG , 0x82 }, + { STB0899_CS1CFG , 0x82 }, + { STB0899_DISEQCOCFG , 0x20 }, + { STB0899_GPIO32CFG , 0x82 }, + { STB0899_GPIO33CFG , 0x82 }, + { STB0899_GPIO34CFG , 0x82 }, + { STB0899_GPIO35CFG , 0x82 }, + { STB0899_GPIO36CFG , 0x82 }, + { STB0899_GPIO37CFG , 0x82 }, + { STB0899_GPIO38CFG , 0x82 }, + { STB0899_GPIO39CFG , 0x82 }, + { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ + { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ + { STB0899_FILTCTRL , 0x00 }, + { STB0899_SYSCTRL , 0x01 }, + { STB0899_STOPCLK1 , 0x20 }, + { STB0899_STOPCLK2 , 0x00 }, + { STB0899_INTBUFSTATUS , 0x00 }, + { STB0899_INTBUFCTRL , 0x0a }, + { 0xffff , 0xff }, +}; + +static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { + { STB0899_DEMOD , 0x00 }, + { STB0899_RCOMPC , 0xc9 }, + { STB0899_AGC1CN , 0x01 }, + { STB0899_AGC1REF , 0x10 }, + { STB0899_RTC , 0x23 }, + { STB0899_TMGCFG , 0x4e }, + { STB0899_AGC2REF , 0x34 }, + { STB0899_TLSR , 0x84 }, + { STB0899_CFD , 0xf7 }, + { STB0899_ACLC , 0x87 }, + { STB0899_BCLC , 0x94 }, + { STB0899_EQON , 0x41 }, + { STB0899_LDT , 0xf1 }, + { STB0899_LDT2 , 0xe3 }, + { STB0899_EQUALREF , 0xb4 }, + { STB0899_TMGRAMP , 0x10 }, + { STB0899_TMGTHD , 0x30 }, + { STB0899_IDCCOMP , 0xfd }, + { STB0899_QDCCOMP , 0xff }, + { STB0899_POWERI , 0x0c }, + { STB0899_POWERQ , 0x0f }, + { STB0899_RCOMP , 0x6c }, + { STB0899_AGCIQIN , 0x80 }, + { STB0899_AGC2I1 , 0x06 }, + { STB0899_AGC2I2 , 0x00 }, + { STB0899_TLIR , 0x30 }, + { STB0899_RTF , 0x7f }, + { STB0899_DSTATUS , 0x00 }, + { STB0899_LDI , 0xbc }, + { STB0899_CFRM , 0xea }, + { STB0899_CFRL , 0x31 }, + { STB0899_NIRM , 0x2b }, + { STB0899_NIRL , 0x80 }, + { STB0899_ISYMB , 0x1d }, + { STB0899_QSYMB , 0xa6 }, + { STB0899_SFRH , 0x2f }, + { STB0899_SFRM , 0x68 }, + { STB0899_SFRL , 0x40 }, + { STB0899_SFRUPH , 0x2f }, + { STB0899_SFRUPM , 0x68 }, + { STB0899_SFRUPL , 0x40 }, + { STB0899_EQUAI1 , 0x02 }, + { STB0899_EQUAQ1 , 0xff }, + { STB0899_EQUAI2 , 0x04 }, + { STB0899_EQUAQ2 , 0x05 }, + { STB0899_EQUAI3 , 0x02 }, + { STB0899_EQUAQ3 , 0xfd }, + { STB0899_EQUAI4 , 0x03 }, + { STB0899_EQUAQ4 , 0x07 }, + { STB0899_EQUAI5 , 0x08 }, + { STB0899_EQUAQ5 , 0xf5 }, + { STB0899_DSTATUS2 , 0x00 }, + { STB0899_VSTATUS , 0x00 }, + { STB0899_VERROR , 0x86 }, + { STB0899_IQSWAP , 0x2a }, + { STB0899_ECNT1M , 0x00 }, + { STB0899_ECNT1L , 0x00 }, + { STB0899_ECNT2M , 0x00 }, + { STB0899_ECNT2L , 0x00 }, + { STB0899_ECNT3M , 0x0a }, + { STB0899_ECNT3L , 0xad }, + { STB0899_FECAUTO1 , 0x06 }, + { STB0899_FECM , 0x01 }, + { STB0899_VTH12 , 0xb0 }, + { STB0899_VTH23 , 0x7a }, + { STB0899_VTH34 , 0x58 }, + { STB0899_VTH56 , 0x38 }, + { STB0899_VTH67 , 0x34 }, + { STB0899_VTH78 , 0x24 }, + { STB0899_PRVIT , 0xff }, + { STB0899_VITSYNC , 0x19 }, + { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ + { STB0899_TSULC , 0x42 }, + { STB0899_RSLLC , 0x41 }, + { STB0899_TSLPL , 0x12 }, + { STB0899_TSCFGH , 0x0c }, + { STB0899_TSCFGM , 0x00 }, + { STB0899_TSCFGL , 0x00 }, + { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */ + { STB0899_RSSYNCDEL , 0x00 }, + { STB0899_TSINHDELH , 0x02 }, + { STB0899_TSINHDELM , 0x00 }, + { STB0899_TSINHDELL , 0x00 }, + { STB0899_TSLLSTKM , 0x1b }, + { STB0899_TSLLSTKL , 0xb3 }, + { STB0899_TSULSTKM , 0x00 }, + { STB0899_TSULSTKL , 0x00 }, + { STB0899_PCKLENUL , 0xbc }, + { STB0899_PCKLENLL , 0xcc }, + { STB0899_RSPCKLEN , 0xbd }, + { STB0899_TSSTATUS , 0x90 }, + { STB0899_ERRCTRL1 , 0xb6 }, + { STB0899_ERRCTRL2 , 0x95 }, + { STB0899_ERRCTRL3 , 0x8d }, + { STB0899_DMONMSK1 , 0x27 }, + { STB0899_DMONMSK0 , 0x03 }, + { STB0899_DEMAPVIT , 0x5c }, + { STB0899_PLPARM , 0x19 }, + { STB0899_PDELCTRL , 0x48 }, + { STB0899_PDELCTRL2 , 0x00 }, + { STB0899_BBHCTRL1 , 0x00 }, + { STB0899_BBHCTRL2 , 0x00 }, + { STB0899_HYSTTHRESH , 0x77 }, + { STB0899_MATCSTM , 0x00 }, + { STB0899_MATCSTL , 0x00 }, + { STB0899_UPLCSTM , 0x00 }, + { STB0899_UPLCSTL , 0x00 }, + { STB0899_DFLCSTM , 0x00 }, + { STB0899_DFLCSTL , 0x00 }, + { STB0899_SYNCCST , 0x00 }, + { STB0899_SYNCDCSTM , 0x00 }, + { STB0899_SYNCDCSTL , 0x00 }, + { STB0899_ISI_ENTRY , 0x00 }, + { STB0899_ISI_BIT_EN , 0x00 }, + { STB0899_MATSTRM , 0xf0 }, + { STB0899_MATSTRL , 0x02 }, + { STB0899_UPLSTRM , 0x45 }, + { STB0899_UPLSTRL , 0x60 }, + { STB0899_DFLSTRM , 0xe3 }, + { STB0899_DFLSTRL , 0x00 }, + { STB0899_SYNCSTR , 0x47 }, + { STB0899_SYNCDSTRM , 0x05 }, + { STB0899_SYNCDSTRL , 0x18 }, + { STB0899_CFGPDELSTATUS1 , 0x19 }, + { STB0899_CFGPDELSTATUS2 , 0x2b }, + { STB0899_BBFERRORM , 0x00 }, + { STB0899_BBFERRORL , 0x01 }, + { STB0899_UPKTERRORM , 0x00 }, + { STB0899_UPKTERRORL , 0x00 }, + { 0xffff , 0xff }, +}; + + + +struct stb0899_config az6027_stb0899_config = { + .init_dev = az6027_stb0899_s1_init_1, + .init_s2_demod = stb0899_s2_init_2, + .init_s1_demod = az6027_stb0899_s1_init_3, + .init_s2_fec = stb0899_s2_init_4, + .init_tst = stb0899_s1_init_5, + + .demod_address = 0xd0,//0x68, /* 0xd0 >> 1 */ + + .xtal_freq = 27000000, + .inversion = IQ_SWAP_ON, /* 1 */ + + .lo_clk = 76500000, + .hi_clk = 99000000, + + .esno_ave = STB0899_DVBS2_ESNO_AVE, + .esno_quant = STB0899_DVBS2_ESNO_QUANT, + .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, + .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, + .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, + .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, + .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, + .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, + .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, + + .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, + .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, + .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, + .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, + + .tuner_get_frequency = stb6100_get_frequency, + .tuner_set_frequency = stb6100_set_frequency, + .tuner_set_bandwidth = stb6100_set_bandwidth, + .tuner_get_bandwidth = stb6100_get_bandwidth, + .tuner_set_rfsiggain = NULL, +}; + +struct stb6100_config az6027_stb6100_config = { + .tuner_address = 0xc0, + .refclock = 27000000, +}; + + +/* check for mutex FIXME */ +int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +{ + int ret = -1; + if(mutex_lock_interruptible(&d->usb_mutex)) { + return -EAGAIN; + } + ret = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_IN, + value,index,b,blen, + 2000); + + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EIO; + } else + ret = 0; + + + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + mutex_unlock(&d->usb_mutex); + return ret; +} + +static int az6027_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) +{ + int ret; + deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + if(mutex_lock_interruptible(&d->usb_mutex)) { + return -EAGAIN; + } + + if ((ret = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index,b,blen, + 2000)) != blen) { + warn("usb out operation failed. (%d)",ret); + mutex_unlock(&d->usb_mutex); + return -EIO; + } else{ + mutex_unlock(&d->usb_mutex); + return 0; + } +} + +static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + deb_info("%s %d",__func__,onoff); + req = 0xBC; + value = onoff; + index = 0; + blen =0; + if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) { + warn("usb out operation failed. (%d)",ret); + } + + //info("write CA + return ret; +} + +/* keys for the enclosed remote control */ +static struct dvb_usb_rc_key az6027_rc_keys[] = { + { 0x00, 0x01, KEY_1 }, + { 0x00, 0x02, KEY_2 }, +}; + +/* remote control stuff (does not work with my box) */ +static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + return 0; +} + +/* +int az6027_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 v = onoff; + return az6027_usb_out_op(d,0xBC,v,3,NULL,1); +} +*/ + +static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, + int slot, + int address) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + + int ret; + u8 req; + u16 value; + u16 index; + int blen; + u8 b[12]; + + //info ("%s %d", __func__, slot); + if (0 != slot) + return -EINVAL; + mutex_lock (&state->ca_mutex); + + req = 0xC1; + value = address; + index = 0; + blen = 1; + ret = az6027_usb_in_op(d,req,value,index,b,blen); + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EINVAL; + } else{ + ret = b[0]; + //info("CI MEM 0x%x = %x",address,b[0]); + } + //mdelay(10); + mutex_unlock (&state->ca_mutex); + return ret; +} + +static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, + int slot, + int address, + u8 value) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; + u8 req; + u16 value1; + u16 index; + int blen; + + deb_info ("%s %d", __func__, slot); + if (0 != slot) + return -EINVAL; + + mutex_lock (&state->ca_mutex); + req = 0xC2; + value1 = address; + index = value; + blen =0; + if((ret = az6027_usb_out_op(d,req,value1,index,NULL,blen)) != 0) { + warn("usb out operation failed. (%d)",ret); + } + //mdelay(10); + mutex_unlock (&state->ca_mutex); + + return ret; +} + +static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, + int slot, + u8 address) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + + int ret; + u8 req; + u16 value; + u16 index; + int blen; + u8 b[12]; + + //info ("%s %d", __func__, slot); + if (0 != slot) + return -EINVAL; + mutex_lock (&state->ca_mutex); + + req = 0xC3; + value = address; + index = 0; + blen = 2; + ret = az6027_usb_in_op(d,req,value,index,b,blen); + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EINVAL; + } else{ + if(b[0] == 0) + warn("Read CI IO error"); + ret = b[1]; + deb_info("read cam data = %x from 0x%x",b[1],value); + } + //udelay(350); + mutex_unlock (&state->ca_mutex); + return ret; +} + +static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, + int slot, + u8 address, + u8 value) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; + u8 req; + u16 value1; + u16 index; + int blen; + + //info ("%s %d", __func__, slot); + if (0 != slot) + return -EINVAL; + + mutex_lock (&state->ca_mutex); + req = 0xC4; + value1 = address; + index = value; + blen =0; + if((ret = az6027_usb_out_op(d,req,value1,index,NULL,blen)) != 0) { + warn("usb out operation failed. (%d)",ret); + goto failed; + } + //info("write CAM data(%x) to 0x%x ",index, value1); + //udelay(350); + failed: + mutex_unlock (&state->ca_mutex); + return ret; +} + +static int CI_CamReady(struct dvb_ca_en50221 *ca, + int slot) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + int ret; + u8 req; + u16 value; + u16 index; + int blen; + u8 b[12]; + + req = 0xC8; + value = 0; + index = 0; + blen = 1; + ret = az6027_usb_in_op(d,req,value,index,b,blen); + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EIO; + } else{ + ret = b[0]; + } + return ret; +} + +static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, + int slot) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret,i; + u8 req; + u16 value; + u16 index; + int blen; + + mutex_lock (&state->ca_mutex); + + req = 0xC6; + value = 1; + index = 0; + blen =0; + if((ret = az6027_usb_out_op(d,req,value,index,NULL,blen)) != 0) { + warn("usb out operation failed. (%d)",ret); + goto failed; + } + msleep (500); + req = 0xC6; + value = 0; + index = 0; + blen =0; + if((ret = az6027_usb_out_op(d,req,value,index,NULL,blen)) != 0) { + warn("usb out operation failed. (%d)",ret); + goto failed; + } + + for(i = 0;i < 15;i++) + { + msleep(100); + if(CI_CamReady(ca,slot)) + { + deb_info("CAM Ready"); + break; + } + } + msleep(5000); + + failed: + mutex_unlock (&state->ca_mutex); + + return ret; +} + +static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, + int slot) +{ + // do nothing here. + return 0; +} + +static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, + int slot) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; + u8 req; + u16 value; + u16 index; + int blen; + deb_info("%s", __func__); + mutex_lock (&state->ca_mutex); + req = 0xC7; + value = 1; + index = 0; + blen =0; + if((ret = az6027_usb_out_op(d,req,value,index,NULL,blen)) != 0) + { + warn("usb out operation failed. (%d)",ret); + goto failed; + } + failed: + mutex_unlock (&state->ca_mutex); + + return ret; +} + +static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, + int slot, + int open) +{ + struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; + u8 req; + u16 value; + u16 index; + int blen; + u8 b[12]; + + mutex_lock (&state->ca_mutex); + + req = 0xC5; + value = 0; + index = 0; + blen = 1; + ret = az6027_usb_in_op(d,req,value,index,b,blen); + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); + ret = -EIO; + } else + ret = 0; + if(b[0] == 0) + ret = 0; + else if(b[0] == 1){ + ret = (DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY); + //info("CAM IN slot = %d", slot); + } + + mutex_unlock (&state->ca_mutex); + return ret; +} + + +static void az6027_ci_uninit(struct dvb_usb_device *d) +{ + struct az6027_device_state *state; + + deb_info("%s", __func__); + + if (NULL == d) + return; + + state = (struct az6027_device_state *)d->priv; + if (NULL == state) + return; + + if (NULL == state->ca.data) + return; + + dvb_ca_en50221_release(&state->ca); + + memset(&state->ca, 0, sizeof(state->ca)); +} + + +static int az6027_ci_init(struct dvb_usb_adapter *a) +{ + struct dvb_usb_device *d = a->dev; + struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; + + deb_info ("%s", __func__); + + mutex_init(&state->ca_mutex); + + state->ca.owner = THIS_MODULE; + state->ca.read_attribute_mem = az6027_ci_read_attribute_mem; + state->ca.write_attribute_mem = az6027_ci_write_attribute_mem; + state->ca.read_cam_control = az6027_ci_read_cam_control; + state->ca.write_cam_control = az6027_ci_write_cam_control; + state->ca.slot_reset = az6027_ci_slot_reset; + state->ca.slot_shutdown = az6027_ci_slot_shutdown; + state->ca.slot_ts_enable = az6027_ci_slot_ts_enable; + state->ca.poll_slot_status = az6027_ci_poll_slot_status; + state->ca.data = d; + + ret = dvb_ca_en50221_init (&a->dvb_adap, + &state->ca, + /* flags */ 0, + /* n_slots */ 1); + if (0 != ret) { + err ("Cannot initialize CI: Error %d.", ret); + memset (&state->ca, 0, sizeof (state->ca)); + return ret; + } + + deb_info ("CI initialized."); + + return 0; +} + + +static int az6027_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) +{ + az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); + return 0; +} + + +static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + + struct dvb_usb_adapter *adap = fe->dvb->priv; + u8 buf; + struct i2c_msg i2c_msg = { + .addr = 0x99, + .flags = 0, + .buf = &buf, + .len = 1 + }; + int ret; + switch (voltage) { + case SEC_VOLTAGE_13: + buf = 1;// 2 --18v 1 --13v 0 --off + ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); + break; + case SEC_VOLTAGE_18: + buf = 2;// 2 --18v 1 --13v 0 --off + ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); + break; + case SEC_VOLTAGE_OFF: + buf = 0;// 2 --18v 1 --13v 0 --off + ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); + break; + default: + return -EINVAL; + } + return 0; +} + + +static int az6027_frontend_poweron(struct dvb_usb_adapter *adap) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + + req = 0xBC; + value = 1;//power on + index = 3; + blen =0; + + if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + return -EIO; + return 0; +} +static int az6027_frontend_reset(struct dvb_usb_adapter *adap) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + + //reset demodulator + req = 0xC0; + value = 1;//high + index = 3; + blen =0; + + if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + return -EIO; + + req = 0xC0; + value = 0;//low + index = 3; + blen =0; + msleep_interruptible(200); + if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + return -EIO; + msleep_interruptible(200); + req = 0xC0; + value = 1;//high + index = 3; + blen =0; + + if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + return -EIO; + msleep_interruptible(200); + return 0; +} + +static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap,int onoff) +{ + int ret; + u8 req; + u16 value; + u16 index; + int blen; + //TS through + req = 0xC7; + value = onoff; + index = 0; + blen =0; + + if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) + return -EIO; + return 0; +} + +static int az6027_frontend_attach(struct dvb_usb_adapter *adap) +{ + + az6027_frontend_poweron(adap); + az6027_frontend_reset(adap); + deb_info("adap = %p,dev = %p\n",adap, adap->dev); + adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap); + if (adap->fe) { + deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x",az6027_stb0899_config.demod_address); + if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) { + deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x",az6027_stb6100_config.tuner_address); + adap->fe->ops.set_voltage = az6027_set_voltage; + az6027_ci_init(adap); + } else { + adap->fe = NULL; + } + } + else + warn("no front-end attached\n"); + + + az6027_frontend_tsbypass(adap,0); + + return 0; +} + +static struct dvb_usb_device_properties az6027_properties; + +static void +az6027_usb_disconnect(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata (intf); + az6027_ci_uninit (d); + dvb_usb_device_exit (intf); +} + + +static int az6027_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return dvb_usb_device_init(intf, &az6027_properties, + THIS_MODULE, NULL, adapter_nr); +} + +/* I2C */ +static int az6027_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i=0,j=0,len=0; + int ret; + u16 index; + u16 value; + int length; + u8 req; + u8 data[256]; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + //err("i2c func called\n"); + if (num > 2) + warn("more than 2 i2c messages at a time is not handled yet. TODO."); + + for (i = 0; i < num; i++) { + if(msg[i].addr == 0x99) { + req = 0xBE; + index = 0; + value = msg[i].buf[0] & 0x00ff; + length = 1; + az6027_usb_out_op(d,req,value,index,data,length); + } + if(msg[i].addr == 0xd0){ + /* write/read request */ + if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { +/* + err("i2c read "); + err("addr0 = 0x%x",msg[i].addr); + err("buf0 = 0x%02x 0x%02x",msg[i].buf[0],msg[i].buf[1]); + err("len0 = %d",msg[i].len); + err("addr1 = 0x%x",msg[i+1].addr); + err("buf1 = 0x%02x 0x%02x",msg[i+1].buf[0], *msg[i+1].buf); + err("len1 = %d",msg[i+1].len); + +*/ + req = 0xB9; + index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); + value = msg[i].addr + (msg[i].len << 8); + length = msg[i+1].len + 6; + //err("in: req. %02x, val: %04x, ind: %04x\n",req,value,index); + ret = az6027_usb_in_op(d,req,value,index,data,length); + //err("ret = %d data = %02x %02x",ret,data[5],data[6]); + len = msg[i+1].len; + for (j=0; ji2c_mutex); + + return i; +} + + +static u32 az6027_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm az6027_i2c_algo = { + .master_xfer = az6027_i2c_xfer, + .functionality = az6027_i2c_func, +}; + + +int az6027_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, int *cold) +{ + u8 b[16]; + s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); + + //info("FW GET_VERSION length: %d\n",ret); + + *cold = ret <= 0; + + deb_info("cold: %d\n", *cold); + return 0; +} + + +static struct usb_device_id az6027_usb_table [] = { + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_AZUREWAVE_AZ6027) }, + // { USB_DEVICE(0x0fd9, 0x002a) }, + { 0 }, +}; + +MODULE_DEVICE_TABLE(usb, az6027_usb_table); + +static struct dvb_usb_device_properties az6027_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = CYPRESS_FX2, + //.download_firmware = az6027_download_firmware, + .firmware = "dvb-usb-az6027-03.fw", + .no_reconnect = 1, + + .size_of_priv = sizeof(struct az6027_device_state), + .identify_state = az6027_identify_state, + .num_adapters = 1, + .adapter = { + { + //.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, + + .streaming_ctrl = az6027_streaming_ctrl, + .frontend_attach = az6027_frontend_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 10, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + //.power_ctrl = az6027_power_ctrl, + //.read_mac_address = az6027_read_mac_addr, + + .rc_key_map = az6027_rc_keys, + .rc_key_map_size = ARRAY_SIZE(az6027_rc_keys), + .rc_interval = 400, + .rc_query = az6027_rc_query, + .i2c_algo = &az6027_i2c_algo, + + .num_device_descs = 1, + .devices = { + { .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", + .cold_ids = { &az6027_usb_table[0], NULL }, + .warm_ids = { NULL }, + }, + { NULL }, + } +}; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver az6027_usb_driver = { + .name = "dvb_usb_az6027", + .probe = az6027_usb_probe, + //.disconnect = dvb_usb_device_exit, + .disconnect = az6027_usb_disconnect, + .id_table = az6027_usb_table, +}; + +/* module stuff */ +static int __init az6027_usb_module_init(void) +{ + int result; + if ((result = usb_register(&az6027_usb_driver))) { + err("usb_register failed. (%d)",result); + return result; + } + + return 0; +} + +static void __exit az6027_usb_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&az6027_usb_driver); +} + +module_init(az6027_usb_module_init); +module_exit(az6027_usb_module_exit); + +MODULE_AUTHOR("Adams Xu "); +MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/dvb/dvb-usb/az6027.h new file mode 100644 index 00000000000..76bd28c5c0c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6027.h @@ -0,0 +1,14 @@ +#ifndef _DVB_USB_VP6027_H_ +#define _DVB_USB_VP6027_H_ + +#define DVB_USB_LOG_PREFIX "az6027" +#include "dvb-usb.h" + + +extern int dvb_usb_az6027_debug; +#define deb_info(args...) dprintk(dvb_usb_az6027_debug,0x01,args) +#define deb_xfer(args...) dprintk(dvb_usb_az6027_debug,0x02,args) +#define deb_rc(args...) dprintk(dvb_usb_az6027_debug,0x04,args) +#define deb_fe(args...) dprintk(dvb_usb_az6027_debug,0x08,args) + +#endif -- cgit v1.2.3 From 91d8f7ae6eb8cc1c0f701e6afd0f7095c8091b2a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Feb 2010 14:59:39 -0300 Subject: V4L/DVB: AZ6027: Add driver supported ID's Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 250ebf9fd6b..ae8b57acfe0 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -64,6 +64,8 @@ #define USB_VID_HUMAX_COEX 0x10b9 #define USB_VID_774 0x7a69 #define USB_VID_EVOLUTEPC 0x1e59 +#define USB_VID_AZUREWAVE 0x13d3 +#define USB_VID_TECHNISAT 0x14f7 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -293,5 +295,7 @@ #define USB_PID_FRIIO_WHITE 0x0001 #define USB_PID_TVWAY_PLUS 0x0002 #define USB_PID_SVEON_STV20 0xe39d - +#define USB_PID_AZUREWAVE_AZ6027 0x3275 +#define USB_PID_TERRATEC_DVBS2CI 0x3275 +#define USB_PID_TECHNISAT_USB2_HDCI 0x0002 #endif -- cgit v1.2.3 From bafa50ffb11eca44496332f3ee742144f097f29b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Feb 2010 15:03:39 -0300 Subject: V4L/DVB: AZ6027: Update Build Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 8 ++++++++ drivers/media/dvb/dvb-usb/Makefile | 3 +++ 2 files changed, 11 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 465295b1d14..e5f91f16ffa 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -336,3 +336,11 @@ config DVB_USB_EC168 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. + +config DVB_USB_AZ6027 + tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" + depends on DVB_USB + select DVB_STB0899 if !DVB_FE_CUSTOMISE + select DVB_STB6100 if !DVB_FE_CUSTOMISE + help + Say Y here to support the AZ6027 device diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 72c92cb69a2..1a192453b0e 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -85,6 +85,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o dvb-usb-ec168-objs = ec168.o obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o +dvb-usb-az6027-objs = az6027.o +obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 EXTRA_CFLAGS += -Idrivers/media/common/tuners -- cgit v1.2.3 From 3c3233ec76118634cfd74d35c45d984e74acfc37 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Feb 2010 15:10:54 -0300 Subject: V4L/DVB: AZ6027: Add driver supported ID's Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 3865c928b01..555c8f44079 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -1038,9 +1038,10 @@ int az6027_identify_state(struct usb_device *udev, struct dvb_usb_device_propert static struct usb_device_id az6027_usb_table [] = { - { USB_DEVICE(USB_VID_TERRATEC, USB_PID_AZUREWAVE_AZ6027) }, - // { USB_DEVICE(0x0fd9, 0x002a) }, - { 0 }, + { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI) }, + { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI) }, + { }, }; MODULE_DEVICE_TABLE(usb, az6027_usb_table); -- cgit v1.2.3 From 5f0e1cff5d19935bef1a6a2cdbd7f39b92031726 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Feb 2010 16:58:10 -0300 Subject: V4L/DVB: AZ6027: Fix checkpatch violations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 612 +++++++++++++++++++------------------ drivers/media/dvb/dvb-usb/az6027.h | 8 +- 2 files changed, 320 insertions(+), 300 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 555c8f44079..30fd046d9d0 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -10,18 +10,17 @@ * see Documentation/dvb/README.dvb-usb for more information */ #include "az6027.h" -/* Demodulator */ + #include "stb0899_drv.h" #include "stb0899_reg.h" #include "stb0899_cfg.h" -/* Tuner */ + #include "stb6100.h" #include "stb6100_cfg.h" #include "dvb_ca_en50221.h" -/* debug */ int dvb_usb_az6027_debug; -module_param_named(debug,dvb_usb_az6027_debug, int, 0644); +module_param_named(debug, dvb_usb_az6027_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -34,7 +33,7 @@ struct az6027_device_state { static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = { -// 0x0000000b , /* SYSREG */ + /* 0x0000000b, SYSREG */ { STB0899_DEV_ID , 0x30 }, { STB0899_DISCNTRL1 , 0x32 }, { STB0899_DISCNTRL2 , 0x80 }, @@ -45,7 +44,7 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = { { STB0899_DISSTATUS , 0x20 }, { STB0899_DISF22 , 0x99 }, { STB0899_DISF22RX , 0xa8 }, - //SYSREG ? + /* SYSREG ? */ { STB0899_ACRPRESC , 0x11 }, { STB0899_ACRDIV1 , 0x0a }, { STB0899_ACRDIV2 , 0x05 }, @@ -263,7 +262,7 @@ struct stb0899_config az6027_stb0899_config = { .init_s2_fec = stb0899_s2_init_4, .init_tst = stb0899_s1_init_5, - .demod_address = 0xd0,//0x68, /* 0xd0 >> 1 */ + .demod_address = 0xd0, /* 0x68, 0xd0 >> 1 */ .xtal_freq = 27000000, .inversion = IQ_SWAP_ON, /* 1 */ @@ -303,15 +302,18 @@ struct stb6100_config az6027_stb6100_config = { int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret = -1; - if(mutex_lock_interruptible(&d->usb_mutex)) { + if (mutex_lock_interruptible(&d->usb_mutex)) return -EAGAIN; - } + ret = usb_control_msg(d->udev, - usb_rcvctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_IN, - value,index,b,blen, - 2000); + usb_rcvctrlpipe(d->udev, 0), + req, + USB_TYPE_VENDOR | USB_DIR_IN, + value, + index, + b, + blen, + 2000); if (ret < 0) { warn("usb in operation failed. (%d)", ret); @@ -319,30 +321,40 @@ int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 } else ret = 0; + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); + debug_dump(b, blen, deb_xfer); - deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); - debug_dump(b,blen,deb_xfer); mutex_unlock(&d->usb_mutex); return ret; } -static int az6027_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, - u16 index, u8 *b, int blen) +static int az6027_usb_out_op(struct dvb_usb_device *d, + u8 req, + u16 value, + u16 index, + u8 *b, + int blen) { int ret; - deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); - debug_dump(b,blen,deb_xfer); - if(mutex_lock_interruptible(&d->usb_mutex)) { + + deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); + debug_dump(b, blen, deb_xfer); + + if (mutex_lock_interruptible(&d->usb_mutex)) return -EAGAIN; - } - if ((ret = usb_control_msg(d->udev, - usb_sndctrlpipe(d->udev,0), - req, - USB_TYPE_VENDOR | USB_DIR_OUT, - value,index,b,blen, - 2000)) != blen) { - warn("usb out operation failed. (%d)",ret); + ret = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev, 0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value, + index, + b, + blen, + 2000); + + if (ret != blen) { + warn("usb out operation failed. (%d)", ret); mutex_unlock(&d->usb_mutex); return -EIO; } else{ @@ -358,16 +370,18 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) u16 value; u16 index; int blen; - deb_info("%s %d",__func__,onoff); + + deb_info("%s %d", __func__, onoff); + req = 0xBC; value = onoff; index = 0; - blen =0; - if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) { - warn("usb out operation failed. (%d)",ret); - } - - //info("write CA + blen = 0; + + ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + warn("usb out operation failed. (%d)", ret); + return ret; } @@ -392,8 +406,8 @@ int az6027_power_ctrl(struct dvb_usb_device *d, int onoff) */ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, - int slot, - int address) + int slot, + int address) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; @@ -403,64 +417,65 @@ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, u16 value; u16 index; int blen; - u8 b[12]; - - //info ("%s %d", __func__, slot); - if (0 != slot) + u8 b[12]; + + if (slot != 0) return -EINVAL; - mutex_lock (&state->ca_mutex); + + mutex_lock(&state->ca_mutex); req = 0xC1; value = address; index = 0; blen = 1; - ret = az6027_usb_in_op(d,req,value,index,b,blen); + + ret = az6027_usb_in_op(d, req, value, index, b, blen); if (ret < 0) { warn("usb in operation failed. (%d)", ret); ret = -EINVAL; - } else{ + } else { ret = b[0]; - //info("CI MEM 0x%x = %x",address,b[0]); } - //mdelay(10); - mutex_unlock (&state->ca_mutex); + + mutex_unlock(&state->ca_mutex); return ret; } static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, - int slot, - int address, - u8 value) + int slot, + int address, + u8 value) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; u8 req; u16 value1; u16 index; int blen; - deb_info ("%s %d", __func__, slot); - if (0 != slot) + deb_info("%s %d", __func__, slot); + if (slot != 0) return -EINVAL; - - mutex_lock (&state->ca_mutex); + + mutex_lock(&state->ca_mutex); req = 0xC2; value1 = address; index = value; - blen =0; - if((ret = az6027_usb_out_op(d,req,value1,index,NULL,blen)) != 0) { - warn("usb out operation failed. (%d)",ret); - } - //mdelay(10); - mutex_unlock (&state->ca_mutex); + blen = 0; + ret = az6027_usb_out_op(d, req, value1, index, NULL, blen); + if (ret != 0) + warn("usb out operation failed. (%d)", ret); + + mutex_unlock(&state->ca_mutex); return ret; } static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, - int slot, - u8 address) + int slot, + u8 address) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; @@ -470,81 +485,85 @@ static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, u16 value; u16 index; int blen; - u8 b[12]; - - //info ("%s %d", __func__, slot); - if (0 != slot) + u8 b[12]; + + if (slot != 0) return -EINVAL; - mutex_lock (&state->ca_mutex); + + mutex_lock(&state->ca_mutex); req = 0xC3; value = address; index = 0; blen = 2; - ret = az6027_usb_in_op(d,req,value,index,b,blen); + + ret = az6027_usb_in_op(d, req, value, index, b, blen); if (ret < 0) { warn("usb in operation failed. (%d)", ret); ret = -EINVAL; - } else{ - if(b[0] == 0) + } else { + if (b[0] == 0) warn("Read CI IO error"); + ret = b[1]; - deb_info("read cam data = %x from 0x%x",b[1],value); + deb_info("read cam data = %x from 0x%x", b[1], value); } - //udelay(350); - mutex_unlock (&state->ca_mutex); + + mutex_unlock(&state->ca_mutex); return ret; } static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, - int slot, - u8 address, - u8 value) + int slot, + u8 address, + u8 value) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; u8 req; u16 value1; u16 index; int blen; - //info ("%s %d", __func__, slot); - if (0 != slot) + if (slot != 0) return -EINVAL; - - mutex_lock (&state->ca_mutex); + + mutex_lock(&state->ca_mutex); req = 0xC4; value1 = address; index = value; - blen =0; - if((ret = az6027_usb_out_op(d,req,value1,index,NULL,blen)) != 0) { - warn("usb out operation failed. (%d)",ret); + blen = 0; + + ret = az6027_usb_out_op(d, req, value1, index, NULL, blen); + if (ret != 0) { + warn("usb out operation failed. (%d)", ret); goto failed; } - //info("write CAM data(%x) to 0x%x ",index, value1); - //udelay(350); - failed: - mutex_unlock (&state->ca_mutex); + +failed: + mutex_unlock(&state->ca_mutex); return ret; } -static int CI_CamReady(struct dvb_ca_en50221 *ca, - int slot) +static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + int ret; u8 req; u16 value; u16 index; int blen; - u8 b[12]; + u8 b[12]; req = 0xC8; value = 0; index = 0; blen = 1; - ret = az6027_usb_in_op(d,req,value,index,b,blen); + + ret = az6027_usb_in_op(d, req, value, index, b, blen); if (ret < 0) { warn("usb in operation failed. (%d)", ret); ret = -EIO; @@ -554,91 +573,92 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, return ret; } -static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, - int slot) +static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; - int ret,i; + + int ret, i; u8 req; u16 value; u16 index; int blen; - mutex_lock (&state->ca_mutex); - + mutex_lock(&state->ca_mutex); + req = 0xC6; value = 1; index = 0; - blen =0; - if((ret = az6027_usb_out_op(d,req,value,index,NULL,blen)) != 0) { - warn("usb out operation failed. (%d)",ret); + blen = 0; + + ret = az6027_usb_out_op(d, req, value, index, NULL, blen); + if (ret != 0) { + warn("usb out operation failed. (%d)", ret); goto failed; } - msleep (500); + + msleep(500); req = 0xC6; value = 0; index = 0; - blen =0; - if((ret = az6027_usb_out_op(d,req,value,index,NULL,blen)) != 0) { - warn("usb out operation failed. (%d)",ret); + blen = 0; + + ret = az6027_usb_out_op(d, req, value, index, NULL, blen); + if (ret != 0) { + warn("usb out operation failed. (%d)", ret); goto failed; } - for(i = 0;i < 15;i++) - { + for (i = 0; i < 15; i++) { msleep(100); - if(CI_CamReady(ca,slot)) - { + + if (CI_CamReady(ca, slot)) { deb_info("CAM Ready"); break; } } msleep(5000); - failed: - mutex_unlock (&state->ca_mutex); - +failed: + mutex_unlock(&state->ca_mutex); return ret; } -static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, - int slot) +static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) { - // do nothing here. return 0; } -static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, - int slot) +static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + int ret; u8 req; u16 value; u16 index; int blen; + deb_info("%s", __func__); - mutex_lock (&state->ca_mutex); + mutex_lock(&state->ca_mutex); req = 0xC7; value = 1; index = 0; - blen =0; - if((ret = az6027_usb_out_op(d,req,value,index,NULL,blen)) != 0) - { - warn("usb out operation failed. (%d)",ret); + blen = 0; + + ret = az6027_usb_out_op(d, req, value, index, NULL, blen); + if (ret != 0) { + warn("usb out operation failed. (%d)", ret); goto failed; } - failed: - mutex_unlock (&state->ca_mutex); +failed: + mutex_unlock(&state->ca_mutex); return ret; } -static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, - int slot, - int open) +static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; struct az6027_device_state *state = (struct az6027_device_state *)d->priv; @@ -647,29 +667,31 @@ static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, u16 value; u16 index; int blen; - u8 b[12]; - - mutex_lock (&state->ca_mutex); + u8 b[12]; + + mutex_lock(&state->ca_mutex); req = 0xC5; value = 0; index = 0; blen = 1; - ret = az6027_usb_in_op(d,req,value,index,b,blen); + + ret = az6027_usb_in_op(d, req, value, index, b, blen); if (ret < 0) { warn("usb in operation failed. (%d)", ret); ret = -EIO; } else ret = 0; - if(b[0] == 0) + + if (b[0] == 0) { ret = 0; - else if(b[0] == 1){ - ret = (DVB_CA_EN50221_POLL_CAM_PRESENT | - DVB_CA_EN50221_POLL_CAM_READY); - //info("CAM IN slot = %d", slot); + + } else if (b[0] == 1) { + ret = DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; } - mutex_unlock (&state->ca_mutex); + mutex_unlock(&state->ca_mutex); return ret; } @@ -702,38 +724,38 @@ static int az6027_ci_init(struct dvb_usb_adapter *a) struct az6027_device_state *state = (struct az6027_device_state *)d->priv; int ret; - deb_info ("%s", __func__); + deb_info("%s", __func__); mutex_init(&state->ca_mutex); - state->ca.owner = THIS_MODULE; - state->ca.read_attribute_mem = az6027_ci_read_attribute_mem; - state->ca.write_attribute_mem = az6027_ci_write_attribute_mem; - state->ca.read_cam_control = az6027_ci_read_cam_control; - state->ca.write_cam_control = az6027_ci_write_cam_control; - state->ca.slot_reset = az6027_ci_slot_reset; - state->ca.slot_shutdown = az6027_ci_slot_shutdown; - state->ca.slot_ts_enable = az6027_ci_slot_ts_enable; - state->ca.poll_slot_status = az6027_ci_poll_slot_status; - state->ca.data = d; - - ret = dvb_ca_en50221_init (&a->dvb_adap, - &state->ca, - /* flags */ 0, - /* n_slots */ 1); - if (0 != ret) { - err ("Cannot initialize CI: Error %d.", ret); - memset (&state->ca, 0, sizeof (state->ca)); + state->ca.owner = THIS_MODULE; + state->ca.read_attribute_mem = az6027_ci_read_attribute_mem; + state->ca.write_attribute_mem = az6027_ci_write_attribute_mem; + state->ca.read_cam_control = az6027_ci_read_cam_control; + state->ca.write_cam_control = az6027_ci_write_cam_control; + state->ca.slot_reset = az6027_ci_slot_reset; + state->ca.slot_shutdown = az6027_ci_slot_shutdown; + state->ca.slot_ts_enable = az6027_ci_slot_ts_enable; + state->ca.poll_slot_status = az6027_ci_poll_slot_status; + state->ca.data = d; + + ret = dvb_ca_en50221_init(&a->dvb_adap, + &state->ca, + 0, /* flags */ + 1);/* n_slots */ + if (ret != 0) { + err("Cannot initialize CI: Error %d.", ret); + memset(&state->ca, 0, sizeof(state->ca)); return ret; } - deb_info ("CI initialized."); + deb_info("CI initialized."); return 0; } -static int az6027_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) +static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); return 0; @@ -742,29 +764,39 @@ static int az6027_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - - struct dvb_usb_adapter *adap = fe->dvb->priv; + u8 buf; + int ret; + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct i2c_msg i2c_msg = { .addr = 0x99, .flags = 0, .buf = &buf, .len = 1 }; - int ret; + + /* + * 2 --18v + * 1 --13v + * 0 --off + */ switch (voltage) { case SEC_VOLTAGE_13: - buf = 1;// 2 --18v 1 --13v 0 --off + buf = 1; ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); break; + case SEC_VOLTAGE_18: - buf = 2;// 2 --18v 1 --13v 0 --off + buf = 2; ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); break; + case SEC_VOLTAGE_OFF: - buf = 0;// 2 --18v 1 --13v 0 --off + buf = 0; ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); break; + default: return -EINVAL; } @@ -781,12 +813,14 @@ static int az6027_frontend_poweron(struct dvb_usb_adapter *adap) int blen; req = 0xBC; - value = 1;//power on + value = 1; /* power on */ index = 3; - blen =0; + blen = 0; + + ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + return -EIO; - if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - return -EIO; return 0; } static int az6027_frontend_reset(struct dvb_usb_adapter *adap) @@ -797,49 +831,59 @@ static int az6027_frontend_reset(struct dvb_usb_adapter *adap) u16 index; int blen; - //reset demodulator + /* reset demodulator */ req = 0xC0; - value = 1;//high + value = 1; /* high */ index = 3; - blen =0; + blen = 0; + + ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + return -EIO; - if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - return -EIO; - req = 0xC0; - value = 0;//low + value = 0; /* low */ index = 3; - blen =0; + blen = 0; msleep_interruptible(200); - if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - return -EIO; + + ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + return -EIO; + msleep_interruptible(200); + req = 0xC0; - value = 1;//high + value = 1; /*high */ index = 3; - blen =0; + blen = 0; + + ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + return -EIO; - if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - return -EIO; msleep_interruptible(200); return 0; } -static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap,int onoff) +static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff) { int ret; u8 req; u16 value; u16 index; int blen; - //TS through + + /* TS passthrough */ req = 0xC7; value = onoff; index = 0; - blen =0; + blen = 0; + + ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); + if (ret != 0) + return -EIO; - if((ret = az6027_usb_out_op(adap->dev,req,value,index,NULL,blen)) != 0) - return -EIO; return 0; } @@ -848,164 +892,134 @@ static int az6027_frontend_attach(struct dvb_usb_adapter *adap) az6027_frontend_poweron(adap); az6027_frontend_reset(adap); - deb_info("adap = %p,dev = %p\n",adap, adap->dev); + + deb_info("adap = %p, dev = %p\n", adap, adap->dev); adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap); + if (adap->fe) { - deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x",az6027_stb0899_config.demod_address); + deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address); if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) { - deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x",az6027_stb6100_config.tuner_address); + deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address); adap->fe->ops.set_voltage = az6027_set_voltage; az6027_ci_init(adap); } else { adap->fe = NULL; } - } - else + } else warn("no front-end attached\n"); - - az6027_frontend_tsbypass(adap,0); + az6027_frontend_tsbypass(adap, 0); return 0; } static struct dvb_usb_device_properties az6027_properties; -static void -az6027_usb_disconnect(struct usb_interface *intf) +static void az6027_usb_disconnect(struct usb_interface *intf) { - struct dvb_usb_device *d = usb_get_intfdata (intf); - az6027_ci_uninit (d); - dvb_usb_device_exit (intf); + struct dvb_usb_device *d = usb_get_intfdata(intf); + az6027_ci_uninit(d); + dvb_usb_device_exit(intf); } static int az6027_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { - return dvb_usb_device_init(intf, &az6027_properties, - THIS_MODULE, NULL, adapter_nr); + return dvb_usb_device_init(intf, + &az6027_properties, + THIS_MODULE, + NULL, + adapter_nr); } /* I2C */ -static int az6027_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) +static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); - int i=0,j=0,len=0; + int i = 0, j = 0, len = 0; int ret; u16 index; u16 value; int length; u8 req; u8 data[256]; - + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; - //err("i2c func called\n"); + if (num > 2) warn("more than 2 i2c messages at a time is not handled yet. TODO."); for (i = 0; i < num; i++) { - if(msg[i].addr == 0x99) { + + if (msg[i].addr == 0x99) { req = 0xBE; index = 0; value = msg[i].buf[0] & 0x00ff; length = 1; - az6027_usb_out_op(d,req,value,index,data,length); + az6027_usb_out_op(d, req, value, index, data, length); } - if(msg[i].addr == 0xd0){ + + if (msg[i].addr == 0xd0) { /* write/read request */ - if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { -/* - err("i2c read "); - err("addr0 = 0x%x",msg[i].addr); - err("buf0 = 0x%02x 0x%02x",msg[i].buf[0],msg[i].buf[1]); - err("len0 = %d",msg[i].len); - err("addr1 = 0x%x",msg[i+1].addr); - err("buf1 = 0x%02x 0x%02x",msg[i+1].buf[0], *msg[i+1].buf); - err("len1 = %d",msg[i+1].len); - -*/ + if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) { req = 0xB9; index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); value = msg[i].addr + (msg[i].len << 8); - length = msg[i+1].len + 6; - //err("in: req. %02x, val: %04x, ind: %04x\n",req,value,index); - ret = az6027_usb_in_op(d,req,value,index,data,length); - //err("ret = %d data = %02x %02x",ret,data[5],data[6]); - len = msg[i+1].len; - for (j=0; ji2c_mutex); - + return i; } @@ -1020,15 +1034,21 @@ static struct i2c_algorithm az6027_i2c_algo = { .functionality = az6027_i2c_func, }; - -int az6027_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, int *cold) +int az6027_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, + int *cold) { u8 b[16]; - s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), - 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); - - //info("FW GET_VERSION length: %d\n",ret); + s16 ret = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), + 0xb7, + USB_TYPE_VENDOR | USB_DIR_IN, + 6, + 0, + b, + 6, + USB_CTRL_GET_TIMEOUT); *cold = ret <= 0; @@ -1037,7 +1057,7 @@ int az6027_identify_state(struct usb_device *udev, struct dvb_usb_device_propert } -static struct usb_device_id az6027_usb_table [] = { +static struct usb_device_id az6027_usb_table[] = { { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI) }, { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI) }, @@ -1049,7 +1069,6 @@ MODULE_DEVICE_TABLE(usb, az6027_usb_table); static struct dvb_usb_device_properties az6027_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = CYPRESS_FX2, - //.download_firmware = az6027_download_firmware, .firmware = "dvb-usb-az6027-03.fw", .no_reconnect = 1, @@ -1058,8 +1077,6 @@ static struct dvb_usb_device_properties az6027_properties = { .num_adapters = 1, .adapter = { { - //.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, - .streaming_ctrl = az6027_streaming_ctrl, .frontend_attach = az6027_frontend_attach, @@ -1076,9 +1093,10 @@ static struct dvb_usb_device_properties az6027_properties = { }, } }, - //.power_ctrl = az6027_power_ctrl, - //.read_mac_address = az6027_read_mac_addr, - +/* + .power_ctrl = az6027_power_ctrl, + .read_mac_address = az6027_read_mac_addr, + */ .rc_key_map = az6027_rc_keys, .rc_key_map_size = ARRAY_SIZE(az6027_rc_keys), .rc_interval = 400, @@ -1087,11 +1105,12 @@ static struct dvb_usb_device_properties az6027_properties = { .num_device_descs = 1, .devices = { - { .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", - .cold_ids = { &az6027_usb_table[0], NULL }, - .warm_ids = { NULL }, + { + .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", + .cold_ids = { &az6027_usb_table[0], NULL }, + .warm_ids = { NULL }, }, - { NULL }, + { NULL }, } }; @@ -1099,7 +1118,6 @@ static struct dvb_usb_device_properties az6027_properties = { static struct usb_driver az6027_usb_driver = { .name = "dvb_usb_az6027", .probe = az6027_usb_probe, - //.disconnect = dvb_usb_device_exit, .disconnect = az6027_usb_disconnect, .id_table = az6027_usb_table, }; @@ -1108,8 +1126,10 @@ static struct usb_driver az6027_usb_driver = { static int __init az6027_usb_module_init(void) { int result; - if ((result = usb_register(&az6027_usb_driver))) { - err("usb_register failed. (%d)",result); + + result = usb_register(&az6027_usb_driver); + if (result) { + err("usb_register failed. (%d)", result); return result; } diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/dvb/dvb-usb/az6027.h index 76bd28c5c0c..f3afe17f3f3 100644 --- a/drivers/media/dvb/dvb-usb/az6027.h +++ b/drivers/media/dvb/dvb-usb/az6027.h @@ -6,9 +6,9 @@ extern int dvb_usb_az6027_debug; -#define deb_info(args...) dprintk(dvb_usb_az6027_debug,0x01,args) -#define deb_xfer(args...) dprintk(dvb_usb_az6027_debug,0x02,args) -#define deb_rc(args...) dprintk(dvb_usb_az6027_debug,0x04,args) -#define deb_fe(args...) dprintk(dvb_usb_az6027_debug,0x08,args) +#define deb_info(args...) dprintk(dvb_usb_az6027_debug, 0x01, args) +#define deb_xfer(args...) dprintk(dvb_usb_az6027_debug, 0x02, args) +#define deb_rc(args...) dprintk(dvb_usb_az6027_debug, 0x04, args) +#define deb_fe(args...) dprintk(dvb_usb_az6027_debug, 0x08, args) #endif -- cgit v1.2.3 From 2ed3f0c625faaace7a4dcfbb4e11baa17d993c5f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Feb 2010 21:11:06 -0200 Subject: V4L/DVB: az6027: IR RC keys are using the old struct with 3 parameters, instead of 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/dvb-usb/az6027.c:390: warning: excess elements in struct initializer drivers/media/dvb/dvb-usb/az6027.c:390: warning: (near initialization for ‘az6027_rc_keys[0]’) drivers/media/dvb/dvb-usb/az6027.c:391: warning: excess elements in struct initializer drivers/media/dvb/dvb-usb/az6027.c:391: warning: (near initialization for ‘az6027_rc_keys[1]’) CC: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 30fd046d9d0..e8d5d0508cb 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -387,8 +387,8 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) /* keys for the enclosed remote control */ static struct dvb_usb_rc_key az6027_rc_keys[] = { - { 0x00, 0x01, KEY_1 }, - { 0x00, 0x02, KEY_2 }, + { 0x0001, KEY_1 }, + { 0x0002, KEY_2 }, }; /* remote control stuff (does not work with my box) */ -- cgit v1.2.3 From 917c50090ea3daa4c048b824a2dcb4730b3d7656 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Feb 2010 21:13:19 -0200 Subject: V4L/DVB: az6027: az6027_read_mac_addr is currently unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/dvb-usb/az6027.c:759: warning: ‘az6027_read_mac_addr’ defined but not used While there's some code that uses it, it is currently commented. So, comment also the function itself. CC: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index e8d5d0508cb..919ca94eb41 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -754,13 +754,13 @@ static int az6027_ci_init(struct dvb_usb_adapter *a) return 0; } - +#if 0 static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); return 0; } - +#endif static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { -- cgit v1.2.3 From b00380fcb760070d5bfdc69ed7273084a629db4d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Feb 2010 23:53:04 -0200 Subject: Revert "V4L/DVB: az6027: IR RC keys are using the old struct with 3 parameters, instead of 2" This reverts commit 234497b022c464532976b8a12614819bcf67f41b. Patch were wrongly applied. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 919ca94eb41..b3a59d60574 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -387,8 +387,8 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) /* keys for the enclosed remote control */ static struct dvb_usb_rc_key az6027_rc_keys[] = { - { 0x0001, KEY_1 }, - { 0x0002, KEY_2 }, + { 0x00, 0x01, KEY_1 }, + { 0x00, 0x02, KEY_2 }, }; /* remote control stuff (does not work with my box) */ -- cgit v1.2.3 From 32f8aca4affc9cc5699a8e45b3ce08e76d7b847b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Feb 2010 23:54:07 -0200 Subject: Revert "V4L/DVB: az6027: az6027_read_mac_addr is currently unused" This reverts commit 1e08370814e8902074d59cc57f2b4c1a62f00ee8. Patch were wrongly applied. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index b3a59d60574..30fd046d9d0 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -754,13 +754,13 @@ static int az6027_ci_init(struct dvb_usb_adapter *a) return 0; } -#if 0 + static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); return 0; } -#endif + static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { -- cgit v1.2.3 From 4105ed5df1e16afbbea4c96f8d513bda21248308 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Feb 2010 17:07:28 -0300 Subject: V4L/DVB: AZ6027: Fix build warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/dvb-usb/az6027.c:390: warning: excess elements in struct initializer drivers/media/dvb/dvb-usb/az6027.c:390: warning: (near initialization for ‘az6027_rc_keys[0]’) drivers/media/dvb/dvb-usb/az6027.c:391: warning: excess elements in struct initializer drivers/media/dvb/dvb-usb/az6027.c:391: warning: (near initialization for ‘az6027_rc_keys[1]’) drivers/media/dvb/dvb-usb/az6027.c:759: warning: ‘az6027_read_mac_addr’ defined but not used Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/az6027.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 30fd046d9d0..d7290b2c091 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -387,8 +387,8 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) /* keys for the enclosed remote control */ static struct dvb_usb_rc_key az6027_rc_keys[] = { - { 0x00, 0x01, KEY_1 }, - { 0x00, 0x02, KEY_2 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, }; /* remote control stuff (does not work with my box) */ @@ -754,13 +754,13 @@ static int az6027_ci_init(struct dvb_usb_adapter *a) return 0; } - +/* static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) { az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); return 0; } - +*/ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { -- cgit v1.2.3 From 18718c96e3e10e6b821d32c50adde9fa5cc6565a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 14 Feb 2010 17:36:25 -0300 Subject: V4L/DVB: V4L: dvb-usb, add extra sync to down-up input events Userspace is allowed to coalesce events between SYNCs. And since the code emits UP right after DOWN for the same key, it may be missed (up+down=nothing). Add an extra sync in between UP and DOWN events to disable the coalesce. Signed-off-by: Jiri Slaby Cc: Patrick Boettcher Acked-by: Dmitry Torokhov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700_core.c | 1 + drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 4450214e2c6..4f961d2d181 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -612,6 +612,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) case REMOTE_KEY_REPEAT: deb_info("key repeated\n"); input_event(d->rc_input_dev, EV_KEY, event, 1); + input_sync(d->rc_input_dev); input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); input_sync(d->rc_input_dev); break; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 6b5ded9e7d5..a03ef7efec9 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -107,6 +107,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work) case REMOTE_KEY_REPEAT: deb_rc("key repeated\n"); input_event(d->rc_input_dev, EV_KEY, event, 1); + input_sync(d->rc_input_dev); input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); input_sync(d->rc_input_dev); break; -- cgit v1.2.3 From 7ccf1eea972177064b4df9d5ba68958604781db6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 14 Feb 2010 23:39:32 -0300 Subject: V4L/DVB: dvb: fix sparse warnings Fix sparse warnings in media/dvb/frontends: drivers/media/dvb/frontends/dibx000_common.c:177:13: warning: non-ANSI function declaration of function 'systime' drivers/media/dvb/frontends/tda665x.c:136:55: warning: right shift by bigger than source value [mchehab@redhat.com: removed the change at dib0090 since it got fixed by a previous patch] Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dibx000_common.c | 2 +- drivers/media/dvb/frontends/tda665x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index e6f3d73db9d..980e02f1575 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c @@ -174,7 +174,7 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) EXPORT_SYMBOL(dibx000_exit_i2c_master); -u32 systime() +u32 systime(void) { struct timespec t; diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c index 87d52739c82..c44fefe92d9 100644 --- a/drivers/media/dvb/frontends/tda665x.c +++ b/drivers/media/dvb/frontends/tda665x.c @@ -133,7 +133,7 @@ static int tda665x_set_state(struct dvb_frontend *fe, frequency += config->ref_divider >> 1; frequency /= config->ref_divider; - buf[0] = (u8) (frequency & 0x7f00) >> 8; + buf[0] = (u8) ((frequency & 0x7f00) >> 8); buf[1] = (u8) (frequency & 0x00ff) >> 0; buf[2] = 0x80 | 0x40 | 0x02; buf[3] = 0x00; -- cgit v1.2.3 From 1f39b5834a3c6c9f107b869d38dca0622e913a3d Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 15 Feb 2010 19:30:38 -0300 Subject: V4L/DVB: dvb-usb/opera1: misplaced parenthesis The parenthesis was misplaced, tmp is set to 0 or break occurs, while debugging opera1_usb_i2c_msgxfer() retval was not shown. Signed-off-by: Roel Kluin CC: Marco Gittler Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/opera1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/dvb') diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index d4e23094167..830557696ae 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -138,7 +138,7 @@ static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), msg[i].buf, msg[i].len - )!= msg[i].len)) { + )) != msg[i].len) { break; } if (dvb_usb_opera1_debug & 0x10) -- cgit v1.2.3