brintos

brintos / linux-shallow public Read only

0
0
Text · 28.8 KiB · 7db6d44 Raw
1125 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SMI PCIe driver for DVBSky cards.4 *5 * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>6 */7 8#include "smipcie.h"9#include "m88ds3103.h"10#include "ts2020.h"11#include "m88rs6000t.h"12#include "si2168.h"13#include "si2157.h"14 15DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);16 17static int smi_hw_init(struct smi_dev *dev)18{19	u32 port_mux, port_ctrl, int_stat;20 21	/* set port mux.*/22	port_mux = smi_read(MUX_MODE_CTRL);23	port_mux &= ~(rbPaMSMask);24	port_mux |= rbPaMSDtvNoGpio;25	port_mux &= ~(rbPbMSMask);26	port_mux |= rbPbMSDtvNoGpio;27	port_mux &= ~(0x0f0000);28	port_mux |= 0x50000;29	smi_write(MUX_MODE_CTRL, port_mux);30 31	/* set DTV register.*/32	/* Port A */33	port_ctrl = smi_read(VIDEO_CTRL_STATUS_A);34	port_ctrl &= ~0x01;35	smi_write(VIDEO_CTRL_STATUS_A, port_ctrl);36	port_ctrl = smi_read(MPEG2_CTRL_A);37	port_ctrl &= ~0x40;38	port_ctrl |= 0x80;39	smi_write(MPEG2_CTRL_A, port_ctrl);40	/* Port B */41	port_ctrl = smi_read(VIDEO_CTRL_STATUS_B);42	port_ctrl &= ~0x01;43	smi_write(VIDEO_CTRL_STATUS_B, port_ctrl);44	port_ctrl = smi_read(MPEG2_CTRL_B);45	port_ctrl &= ~0x40;46	port_ctrl |= 0x80;47	smi_write(MPEG2_CTRL_B, port_ctrl);48 49	/* disable and clear interrupt.*/50	smi_write(MSI_INT_ENA_CLR, ALL_INT);51	int_stat = smi_read(MSI_INT_STATUS);52	smi_write(MSI_INT_STATUS_CLR, int_stat);53 54	/* reset demod.*/55	smi_clear(PERIPHERAL_CTRL, 0x0303);56	msleep(50);57	smi_set(PERIPHERAL_CTRL, 0x0101);58	return 0;59}60 61/* i2c bit bus.*/62static void smi_i2c_cfg(struct smi_dev *dev, u32 sw_ctl)63{64	u32 dwCtrl;65 66	dwCtrl = smi_read(sw_ctl);67	dwCtrl &= ~0x18; /* disable output.*/68	dwCtrl |= 0x21; /* reset and software mode.*/69	dwCtrl &= ~0xff00;70	dwCtrl |= 0x6400;71	smi_write(sw_ctl, dwCtrl);72	msleep(20);73	dwCtrl = smi_read(sw_ctl);74	dwCtrl &= ~0x20;75	smi_write(sw_ctl, dwCtrl);76}77 78static void smi_i2c_setsda(struct smi_dev *dev, int state, u32 sw_ctl)79{80	if (state) {81		/* set as input.*/82		smi_clear(sw_ctl, SW_I2C_MSK_DAT_EN);83	} else {84		smi_clear(sw_ctl, SW_I2C_MSK_DAT_OUT);85		/* set as output.*/86		smi_set(sw_ctl, SW_I2C_MSK_DAT_EN);87	}88}89 90static void smi_i2c_setscl(void *data, int state, u32 sw_ctl)91{92	struct smi_dev *dev = data;93 94	if (state) {95		/* set as input.*/96		smi_clear(sw_ctl, SW_I2C_MSK_CLK_EN);97	} else {98		smi_clear(sw_ctl, SW_I2C_MSK_CLK_OUT);99		/* set as output.*/100		smi_set(sw_ctl, SW_I2C_MSK_CLK_EN);101	}102}103 104static int smi_i2c_getsda(void *data, u32 sw_ctl)105{106	struct smi_dev *dev = data;107	/* set as input.*/108	smi_clear(sw_ctl, SW_I2C_MSK_DAT_EN);109	udelay(1);110	return (smi_read(sw_ctl) & SW_I2C_MSK_DAT_IN) ? 1 : 0;111}112 113static int smi_i2c_getscl(void *data, u32 sw_ctl)114{115	struct smi_dev *dev = data;116	/* set as input.*/117	smi_clear(sw_ctl, SW_I2C_MSK_CLK_EN);118	udelay(1);119	return (smi_read(sw_ctl) & SW_I2C_MSK_CLK_IN) ? 1 : 0;120}121/* i2c 0.*/122static void smi_i2c0_setsda(void *data, int state)123{124	struct smi_dev *dev = data;125 126	smi_i2c_setsda(dev, state, I2C_A_SW_CTL);127}128 129static void smi_i2c0_setscl(void *data, int state)130{131	struct smi_dev *dev = data;132 133	smi_i2c_setscl(dev, state, I2C_A_SW_CTL);134}135 136static int smi_i2c0_getsda(void *data)137{138	struct smi_dev *dev = data;139 140	return	smi_i2c_getsda(dev, I2C_A_SW_CTL);141}142 143static int smi_i2c0_getscl(void *data)144{145	struct smi_dev *dev = data;146 147	return	smi_i2c_getscl(dev, I2C_A_SW_CTL);148}149/* i2c 1.*/150static void smi_i2c1_setsda(void *data, int state)151{152	struct smi_dev *dev = data;153 154	smi_i2c_setsda(dev, state, I2C_B_SW_CTL);155}156 157static void smi_i2c1_setscl(void *data, int state)158{159	struct smi_dev *dev = data;160 161	smi_i2c_setscl(dev, state, I2C_B_SW_CTL);162}163 164static int smi_i2c1_getsda(void *data)165{166	struct smi_dev *dev = data;167 168	return	smi_i2c_getsda(dev, I2C_B_SW_CTL);169}170 171static int smi_i2c1_getscl(void *data)172{173	struct smi_dev *dev = data;174 175	return	smi_i2c_getscl(dev, I2C_B_SW_CTL);176}177 178static int smi_i2c_init(struct smi_dev *dev)179{180	int ret;181 182	/* i2c bus 0 */183	smi_i2c_cfg(dev, I2C_A_SW_CTL);184	i2c_set_adapdata(&dev->i2c_bus[0], dev);185	strscpy(dev->i2c_bus[0].name, "SMI-I2C0", sizeof(dev->i2c_bus[0].name));186	dev->i2c_bus[0].owner = THIS_MODULE;187	dev->i2c_bus[0].dev.parent = &dev->pci_dev->dev;188	dev->i2c_bus[0].algo_data = &dev->i2c_bit[0];189	dev->i2c_bit[0].data = dev;190	dev->i2c_bit[0].setsda = smi_i2c0_setsda;191	dev->i2c_bit[0].setscl = smi_i2c0_setscl;192	dev->i2c_bit[0].getsda = smi_i2c0_getsda;193	dev->i2c_bit[0].getscl = smi_i2c0_getscl;194	dev->i2c_bit[0].udelay = 12;195	dev->i2c_bit[0].timeout = 10;196	/* Raise SCL and SDA */197	smi_i2c0_setsda(dev, 1);198	smi_i2c0_setscl(dev, 1);199 200	ret = i2c_bit_add_bus(&dev->i2c_bus[0]);201	if (ret < 0)202		return ret;203 204	/* i2c bus 1 */205	smi_i2c_cfg(dev, I2C_B_SW_CTL);206	i2c_set_adapdata(&dev->i2c_bus[1], dev);207	strscpy(dev->i2c_bus[1].name, "SMI-I2C1", sizeof(dev->i2c_bus[1].name));208	dev->i2c_bus[1].owner = THIS_MODULE;209	dev->i2c_bus[1].dev.parent = &dev->pci_dev->dev;210	dev->i2c_bus[1].algo_data = &dev->i2c_bit[1];211	dev->i2c_bit[1].data = dev;212	dev->i2c_bit[1].setsda = smi_i2c1_setsda;213	dev->i2c_bit[1].setscl = smi_i2c1_setscl;214	dev->i2c_bit[1].getsda = smi_i2c1_getsda;215	dev->i2c_bit[1].getscl = smi_i2c1_getscl;216	dev->i2c_bit[1].udelay = 12;217	dev->i2c_bit[1].timeout = 10;218	/* Raise SCL and SDA */219	smi_i2c1_setsda(dev, 1);220	smi_i2c1_setscl(dev, 1);221 222	ret = i2c_bit_add_bus(&dev->i2c_bus[1]);223	if (ret < 0)224		i2c_del_adapter(&dev->i2c_bus[0]);225 226	return ret;227}228 229static void smi_i2c_exit(struct smi_dev *dev)230{231	i2c_del_adapter(&dev->i2c_bus[0]);232	i2c_del_adapter(&dev->i2c_bus[1]);233}234 235static int smi_read_eeprom(struct i2c_adapter *i2c, u16 reg, u8 *data, u16 size)236{237	int ret;238	u8 b0[2] = { (reg >> 8) & 0xff, reg & 0xff };239 240	struct i2c_msg msg[] = {241		{ .addr = 0x50, .flags = 0,242			.buf = b0, .len = 2 },243		{ .addr = 0x50, .flags = I2C_M_RD,244			.buf = data, .len = size }245	};246 247	ret = i2c_transfer(i2c, msg, 2);248 249	if (ret != 2) {250		dev_err(&i2c->dev, "%s: reg=0x%x (error=%d)\n",251			__func__, reg, ret);252		return ret;253	}254	return ret;255}256 257/* ts port interrupt operations */258static void smi_port_disableInterrupt(struct smi_port *port)259{260	struct smi_dev *dev = port->dev;261 262	smi_write(MSI_INT_ENA_CLR,263		(port->_dmaInterruptCH0 | port->_dmaInterruptCH1));264}265 266static void smi_port_enableInterrupt(struct smi_port *port)267{268	struct smi_dev *dev = port->dev;269 270	smi_write(MSI_INT_ENA_SET,271		(port->_dmaInterruptCH0 | port->_dmaInterruptCH1));272}273 274static void smi_port_clearInterrupt(struct smi_port *port)275{276	struct smi_dev *dev = port->dev;277 278	smi_write(MSI_INT_STATUS_CLR,279		(port->_dmaInterruptCH0 | port->_dmaInterruptCH1));280}281 282/* BH work handler: DMA data to dmx.*/283static void smi_dma_xfer(struct work_struct *t)284{285	struct smi_port *port = from_work(port, t, bh_work);286	struct smi_dev *dev = port->dev;287	u32 intr_status, finishedData, dmaManagement;288	u8 dmaChan0State, dmaChan1State;289 290	intr_status = port->_int_status;291	dmaManagement = smi_read(port->DMA_MANAGEMENT);292	dmaChan0State = (u8)((dmaManagement & 0x00000030) >> 4);293	dmaChan1State = (u8)((dmaManagement & 0x00300000) >> 20);294 295	/* CH-0 DMA interrupt.*/296	if ((intr_status & port->_dmaInterruptCH0) && (dmaChan0State == 0x01)) {297		dev_dbg(&dev->pci_dev->dev,298			"Port[%d]-DMA CH0 engine complete successful !\n",299			port->idx);300		finishedData = smi_read(port->DMA_CHAN0_TRANS_STATE);301		finishedData &= 0x003FFFFF;302		/* value of DMA_PORT0_CHAN0_TRANS_STATE register [21:0]303		 * indicate dma total transfer length and304		 * zero of [21:0] indicate dma total transfer length305		 * equal to 0x400000 (4MB)*/306		if (finishedData == 0)307			finishedData = 0x00400000;308		if (finishedData != SMI_TS_DMA_BUF_SIZE) {309			dev_dbg(&dev->pci_dev->dev,310				"DMA CH0 engine complete length mismatched, finish data=%d !\n",311				finishedData);312		}313		dvb_dmx_swfilter_packets(&port->demux,314			port->cpu_addr[0], (finishedData / 188));315		/*dvb_dmx_swfilter(&port->demux,316			port->cpu_addr[0], finishedData);*/317	}318	/* CH-1 DMA interrupt.*/319	if ((intr_status & port->_dmaInterruptCH1) && (dmaChan1State == 0x01)) {320		dev_dbg(&dev->pci_dev->dev,321			"Port[%d]-DMA CH1 engine complete successful !\n",322			port->idx);323		finishedData = smi_read(port->DMA_CHAN1_TRANS_STATE);324		finishedData &= 0x003FFFFF;325		/* value of DMA_PORT0_CHAN0_TRANS_STATE register [21:0]326		 * indicate dma total transfer length and327		 * zero of [21:0] indicate dma total transfer length328		 * equal to 0x400000 (4MB)*/329		if (finishedData == 0)330			finishedData = 0x00400000;331		if (finishedData != SMI_TS_DMA_BUF_SIZE) {332			dev_dbg(&dev->pci_dev->dev,333				"DMA CH1 engine complete length mismatched, finish data=%d !\n",334				finishedData);335		}336		dvb_dmx_swfilter_packets(&port->demux,337			port->cpu_addr[1], (finishedData / 188));338		/*dvb_dmx_swfilter(&port->demux,339			port->cpu_addr[1], finishedData);*/340	}341	/* restart DMA.*/342	if (intr_status & port->_dmaInterruptCH0)343		dmaManagement |= 0x00000002;344	if (intr_status & port->_dmaInterruptCH1)345		dmaManagement |= 0x00020000;346	smi_write(port->DMA_MANAGEMENT, dmaManagement);347	/* Re-enable interrupts */348	smi_port_enableInterrupt(port);349}350 351static void smi_port_dma_free(struct smi_port *port)352{353	if (port->cpu_addr[0]) {354		dma_free_coherent(&port->dev->pci_dev->dev,355				  SMI_TS_DMA_BUF_SIZE, port->cpu_addr[0],356				  port->dma_addr[0]);357		port->cpu_addr[0] = NULL;358	}359	if (port->cpu_addr[1]) {360		dma_free_coherent(&port->dev->pci_dev->dev,361				  SMI_TS_DMA_BUF_SIZE, port->cpu_addr[1],362				  port->dma_addr[1]);363		port->cpu_addr[1] = NULL;364	}365}366 367static int smi_port_init(struct smi_port *port, int dmaChanUsed)368{369	dev_dbg(&port->dev->pci_dev->dev,370		"%s, port %d, dmaused %d\n", __func__, port->idx, dmaChanUsed);371	port->enable = 0;372	if (port->idx == 0) {373		/* Port A */374		port->_dmaInterruptCH0 = dmaChanUsed & 0x01;375		port->_dmaInterruptCH1 = dmaChanUsed & 0x02;376 377		port->DMA_CHAN0_ADDR_LOW	= DMA_PORTA_CHAN0_ADDR_LOW;378		port->DMA_CHAN0_ADDR_HI		= DMA_PORTA_CHAN0_ADDR_HI;379		port->DMA_CHAN0_TRANS_STATE	= DMA_PORTA_CHAN0_TRANS_STATE;380		port->DMA_CHAN0_CONTROL		= DMA_PORTA_CHAN0_CONTROL;381		port->DMA_CHAN1_ADDR_LOW	= DMA_PORTA_CHAN1_ADDR_LOW;382		port->DMA_CHAN1_ADDR_HI		= DMA_PORTA_CHAN1_ADDR_HI;383		port->DMA_CHAN1_TRANS_STATE	= DMA_PORTA_CHAN1_TRANS_STATE;384		port->DMA_CHAN1_CONTROL		= DMA_PORTA_CHAN1_CONTROL;385		port->DMA_MANAGEMENT		= DMA_PORTA_MANAGEMENT;386	} else {387		/* Port B */388		port->_dmaInterruptCH0 = (dmaChanUsed << 2) & 0x04;389		port->_dmaInterruptCH1 = (dmaChanUsed << 2) & 0x08;390 391		port->DMA_CHAN0_ADDR_LOW	= DMA_PORTB_CHAN0_ADDR_LOW;392		port->DMA_CHAN0_ADDR_HI		= DMA_PORTB_CHAN0_ADDR_HI;393		port->DMA_CHAN0_TRANS_STATE	= DMA_PORTB_CHAN0_TRANS_STATE;394		port->DMA_CHAN0_CONTROL		= DMA_PORTB_CHAN0_CONTROL;395		port->DMA_CHAN1_ADDR_LOW	= DMA_PORTB_CHAN1_ADDR_LOW;396		port->DMA_CHAN1_ADDR_HI		= DMA_PORTB_CHAN1_ADDR_HI;397		port->DMA_CHAN1_TRANS_STATE	= DMA_PORTB_CHAN1_TRANS_STATE;398		port->DMA_CHAN1_CONTROL		= DMA_PORTB_CHAN1_CONTROL;399		port->DMA_MANAGEMENT		= DMA_PORTB_MANAGEMENT;400	}401 402	if (port->_dmaInterruptCH0) {403		port->cpu_addr[0] = dma_alloc_coherent(&port->dev->pci_dev->dev,404						       SMI_TS_DMA_BUF_SIZE,405						       &port->dma_addr[0],406						       GFP_KERNEL);407		if (!port->cpu_addr[0]) {408			dev_err(&port->dev->pci_dev->dev,409				"Port[%d] DMA CH0 memory allocation failed!\n",410				port->idx);411			goto err;412		}413	}414 415	if (port->_dmaInterruptCH1) {416		port->cpu_addr[1] = dma_alloc_coherent(&port->dev->pci_dev->dev,417						       SMI_TS_DMA_BUF_SIZE,418						       &port->dma_addr[1],419						       GFP_KERNEL);420		if (!port->cpu_addr[1]) {421			dev_err(&port->dev->pci_dev->dev,422				"Port[%d] DMA CH1 memory allocation failed!\n",423				port->idx);424			goto err;425		}426	}427 428	smi_port_disableInterrupt(port);429	INIT_WORK(&port->bh_work, smi_dma_xfer);430	disable_work_sync(&port->bh_work);431	port->enable = 1;432	return 0;433err:434	smi_port_dma_free(port);435	return -ENOMEM;436}437 438static void smi_port_exit(struct smi_port *port)439{440	smi_port_disableInterrupt(port);441	cancel_work_sync(&port->bh_work);442	smi_port_dma_free(port);443	port->enable = 0;444}445 446static int smi_port_irq(struct smi_port *port, u32 int_status)447{448	u32 port_req_irq = port->_dmaInterruptCH0 | port->_dmaInterruptCH1;449	int handled = 0;450 451	if (int_status & port_req_irq) {452		smi_port_disableInterrupt(port);453		port->_int_status = int_status;454		smi_port_clearInterrupt(port);455		queue_work(system_bh_wq, &port->bh_work);456		handled = 1;457	}458	return handled;459}460 461static irqreturn_t smi_irq_handler(int irq, void *dev_id)462{463	struct smi_dev *dev = dev_id;464	struct smi_port *port0 = &dev->ts_port[0];465	struct smi_port *port1 = &dev->ts_port[1];466	struct smi_rc *ir = &dev->ir;467	int handled = 0;468 469	u32 intr_status = smi_read(MSI_INT_STATUS);470 471	/* ts0 interrupt.*/472	if (dev->info->ts_0)473		handled += smi_port_irq(port0, intr_status);474 475	/* ts1 interrupt.*/476	if (dev->info->ts_1)477		handled += smi_port_irq(port1, intr_status);478 479	/* ir interrupt.*/480	handled += smi_ir_irq(ir, intr_status);481 482	return IRQ_RETVAL(handled);483}484 485static struct i2c_client *smi_add_i2c_client(struct i2c_adapter *adapter,486			struct i2c_board_info *info)487{488	struct i2c_client *client;489 490	request_module(info->type);491	client = i2c_new_client_device(adapter, info);492	if (!i2c_client_has_driver(client))493		goto err_add_i2c_client;494 495	if (!try_module_get(client->dev.driver->owner)) {496		i2c_unregister_device(client);497		goto err_add_i2c_client;498	}499	return client;500 501err_add_i2c_client:502	client = NULL;503	return client;504}505 506static void smi_del_i2c_client(struct i2c_client *client)507{508	module_put(client->dev.driver->owner);509	i2c_unregister_device(client);510}511 512static const struct m88ds3103_config smi_dvbsky_m88ds3103_cfg = {513	.i2c_addr = 0x68,514	.clock = 27000000,515	.i2c_wr_max = 33,516	.clock_out = 0,517	.ts_mode = M88DS3103_TS_PARALLEL,518	.ts_clk = 16000,519	.ts_clk_pol = 1,520	.agc = 0x99,521	.lnb_hv_pol = 0,522	.lnb_en_pol = 1,523};524 525static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port)526{527	int ret = 0;528	struct smi_dev *dev = port->dev;529	struct i2c_adapter *i2c;530	/* tuner I2C module */531	struct i2c_adapter *tuner_i2c_adapter;532	struct i2c_client *tuner_client;533	struct i2c_board_info tuner_info;534	struct ts2020_config ts2020_config = {};535	memset(&tuner_info, 0, sizeof(struct i2c_board_info));536	i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];537 538	/* attach demod */539	port->fe = dvb_attach(m88ds3103_attach,540			&smi_dvbsky_m88ds3103_cfg, i2c, &tuner_i2c_adapter);541	if (!port->fe) {542		ret = -ENODEV;543		return ret;544	}545	/* attach tuner */546	ts2020_config.fe = port->fe;547	strscpy(tuner_info.type, "ts2020", I2C_NAME_SIZE);548	tuner_info.addr = 0x60;549	tuner_info.platform_data = &ts2020_config;550	tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);551	if (!tuner_client) {552		ret = -ENODEV;553		goto err_tuner_i2c_device;554	}555 556	/* delegate signal strength measurement to tuner */557	port->fe->ops.read_signal_strength =558			port->fe->ops.tuner_ops.get_rf_strength;559 560	port->i2c_client_tuner = tuner_client;561	return ret;562 563err_tuner_i2c_device:564	dvb_frontend_detach(port->fe);565	return ret;566}567 568static const struct m88ds3103_config smi_dvbsky_m88rs6000_cfg = {569	.i2c_addr = 0x69,570	.clock = 27000000,571	.i2c_wr_max = 33,572	.ts_mode = M88DS3103_TS_PARALLEL,573	.ts_clk = 16000,574	.ts_clk_pol = 1,575	.agc = 0x99,576	.lnb_hv_pol = 0,577	.lnb_en_pol = 1,578};579 580static int smi_dvbsky_m88rs6000_fe_attach(struct smi_port *port)581{582	int ret = 0;583	struct smi_dev *dev = port->dev;584	struct i2c_adapter *i2c;585	/* tuner I2C module */586	struct i2c_adapter *tuner_i2c_adapter;587	struct i2c_client *tuner_client;588	struct i2c_board_info tuner_info;589	struct m88rs6000t_config m88rs6000t_config;590 591	memset(&tuner_info, 0, sizeof(struct i2c_board_info));592	i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];593 594	/* attach demod */595	port->fe = dvb_attach(m88ds3103_attach,596			&smi_dvbsky_m88rs6000_cfg, i2c, &tuner_i2c_adapter);597	if (!port->fe) {598		ret = -ENODEV;599		return ret;600	}601	/* attach tuner */602	m88rs6000t_config.fe = port->fe;603	strscpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE);604	tuner_info.addr = 0x21;605	tuner_info.platform_data = &m88rs6000t_config;606	tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);607	if (!tuner_client) {608		ret = -ENODEV;609		goto err_tuner_i2c_device;610	}611 612	/* delegate signal strength measurement to tuner */613	port->fe->ops.read_signal_strength =614			port->fe->ops.tuner_ops.get_rf_strength;615 616	port->i2c_client_tuner = tuner_client;617	return ret;618 619err_tuner_i2c_device:620	dvb_frontend_detach(port->fe);621	return ret;622}623 624static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)625{626	int ret = 0;627	struct smi_dev *dev = port->dev;628	struct i2c_adapter *i2c;629	struct i2c_adapter *tuner_i2c_adapter;630	struct i2c_client *client_tuner, *client_demod;631	struct i2c_board_info client_info;632	struct si2168_config si2168_config;633	struct si2157_config si2157_config;634 635	/* select i2c bus */636	i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];637 638	/* attach demod */639	memset(&si2168_config, 0, sizeof(si2168_config));640	si2168_config.i2c_adapter = &tuner_i2c_adapter;641	si2168_config.fe = &port->fe;642	si2168_config.ts_mode = SI2168_TS_PARALLEL;643 644	memset(&client_info, 0, sizeof(struct i2c_board_info));645	strscpy(client_info.type, "si2168", I2C_NAME_SIZE);646	client_info.addr = 0x64;647	client_info.platform_data = &si2168_config;648 649	client_demod = smi_add_i2c_client(i2c, &client_info);650	if (!client_demod) {651		ret = -ENODEV;652		return ret;653	}654	port->i2c_client_demod = client_demod;655 656	/* attach tuner */657	memset(&si2157_config, 0, sizeof(si2157_config));658	si2157_config.fe = port->fe;659	si2157_config.if_port = 1;660 661	memset(&client_info, 0, sizeof(struct i2c_board_info));662	strscpy(client_info.type, "si2157", I2C_NAME_SIZE);663	client_info.addr = 0x60;664	client_info.platform_data = &si2157_config;665 666	client_tuner = smi_add_i2c_client(tuner_i2c_adapter, &client_info);667	if (!client_tuner) {668		smi_del_i2c_client(port->i2c_client_demod);669		port->i2c_client_demod = NULL;670		ret = -ENODEV;671		return ret;672	}673	port->i2c_client_tuner = client_tuner;674	return ret;675}676 677static int smi_fe_init(struct smi_port *port)678{679	int ret = 0;680	struct smi_dev *dev = port->dev;681	struct dvb_adapter *adap = &port->dvb_adapter;682	u8 mac_ee[16];683 684	dev_dbg(&port->dev->pci_dev->dev,685		"%s: port %d, fe_type = %d\n",686		__func__, port->idx, port->fe_type);687	switch (port->fe_type) {688	case DVBSKY_FE_M88DS3103:689		ret = smi_dvbsky_m88ds3103_fe_attach(port);690		break;691	case DVBSKY_FE_M88RS6000:692		ret = smi_dvbsky_m88rs6000_fe_attach(port);693		break;694	case DVBSKY_FE_SIT2:695		ret = smi_dvbsky_sit2_fe_attach(port);696		break;697	}698	if (ret < 0)699		return ret;700 701	/* register dvb frontend */702	ret = dvb_register_frontend(adap, port->fe);703	if (ret < 0) {704		if (port->i2c_client_tuner)705			smi_del_i2c_client(port->i2c_client_tuner);706		if (port->i2c_client_demod)707			smi_del_i2c_client(port->i2c_client_demod);708		dvb_frontend_detach(port->fe);709		return ret;710	}711	/* init MAC.*/712	ret = smi_read_eeprom(&dev->i2c_bus[0], 0xc0, mac_ee, 16);713	dev_info(&port->dev->pci_dev->dev,714		"%s port %d MAC: %pM\n", dev->info->name,715		port->idx, mac_ee + (port->idx)*8);716	memcpy(adap->proposed_mac, mac_ee + (port->idx)*8, 6);717	return ret;718}719 720static void smi_fe_exit(struct smi_port *port)721{722	dvb_unregister_frontend(port->fe);723	/* remove I2C demod and tuner */724	if (port->i2c_client_tuner)725		smi_del_i2c_client(port->i2c_client_tuner);726	if (port->i2c_client_demod)727		smi_del_i2c_client(port->i2c_client_demod);728	dvb_frontend_detach(port->fe);729}730 731static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,732			    int (*start_feed)(struct dvb_demux_feed *),733			    int (*stop_feed)(struct dvb_demux_feed *),734			    void *priv)735{736	dvbdemux->priv = priv;737 738	dvbdemux->filternum = 256;739	dvbdemux->feednum = 256;740	dvbdemux->start_feed = start_feed;741	dvbdemux->stop_feed = stop_feed;742	dvbdemux->write_to_decoder = NULL;743	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |744				      DMX_SECTION_FILTERING |745				      DMX_MEMORY_BASED_FILTERING);746	return dvb_dmx_init(dvbdemux);747}748 749static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,750			       struct dvb_demux *dvbdemux,751			       struct dmx_frontend *hw_frontend,752			       struct dmx_frontend *mem_frontend,753			       struct dvb_adapter *dvb_adapter)754{755	int ret;756 757	dmxdev->filternum = 256;758	dmxdev->demux = &dvbdemux->dmx;759	dmxdev->capabilities = 0;760	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);761	if (ret < 0)762		return ret;763 764	hw_frontend->source = DMX_FRONTEND_0;765	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);766	mem_frontend->source = DMX_MEMORY_FE;767	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);768	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);769}770 771static u32 smi_config_DMA(struct smi_port *port)772{773	struct smi_dev *dev = port->dev;774	u32 totalLength = 0, dmaMemPtrLow, dmaMemPtrHi, dmaCtlReg;775	u8 chanLatencyTimer = 0, dmaChanEnable = 1, dmaTransStart = 1;776	u32 dmaManagement = 0, tlpTransUnit = DMA_TRANS_UNIT_188;777	u8 tlpTc = 0, tlpTd = 1, tlpEp = 0, tlpAttr = 0;778	u64 mem;779 780	dmaManagement = smi_read(port->DMA_MANAGEMENT);781	/* Setup Channel-0 */782	if (port->_dmaInterruptCH0) {783		totalLength = SMI_TS_DMA_BUF_SIZE;784		mem = port->dma_addr[0];785		dmaMemPtrLow = mem & 0xffffffff;786		dmaMemPtrHi = mem >> 32;787		dmaCtlReg = (totalLength) | (tlpTransUnit << 22) | (tlpTc << 25)788			| (tlpTd << 28) | (tlpEp << 29) | (tlpAttr << 30);789		dmaManagement |= dmaChanEnable | (dmaTransStart << 1)790			| (chanLatencyTimer << 8);791		/* write DMA register, start DMA engine */792		smi_write(port->DMA_CHAN0_ADDR_LOW, dmaMemPtrLow);793		smi_write(port->DMA_CHAN0_ADDR_HI, dmaMemPtrHi);794		smi_write(port->DMA_CHAN0_CONTROL, dmaCtlReg);795	}796	/* Setup Channel-1 */797	if (port->_dmaInterruptCH1) {798		totalLength = SMI_TS_DMA_BUF_SIZE;799		mem = port->dma_addr[1];800		dmaMemPtrLow = mem & 0xffffffff;801		dmaMemPtrHi = mem >> 32;802		dmaCtlReg = (totalLength) | (tlpTransUnit << 22) | (tlpTc << 25)803			| (tlpTd << 28) | (tlpEp << 29) | (tlpAttr << 30);804		dmaManagement |= (dmaChanEnable << 16) | (dmaTransStart << 17)805			| (chanLatencyTimer << 24);806		/* write DMA register, start DMA engine */807		smi_write(port->DMA_CHAN1_ADDR_LOW, dmaMemPtrLow);808		smi_write(port->DMA_CHAN1_ADDR_HI, dmaMemPtrHi);809		smi_write(port->DMA_CHAN1_CONTROL, dmaCtlReg);810	}811	return dmaManagement;812}813 814static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed)815{816	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;817	struct smi_port *port = dvbdmx->priv;818	struct smi_dev *dev = port->dev;819	u32 dmaManagement;820 821	if (port->users++ == 0) {822		dmaManagement = smi_config_DMA(port);823		smi_port_clearInterrupt(port);824		smi_port_enableInterrupt(port);825		smi_write(port->DMA_MANAGEMENT, dmaManagement);826		enable_and_queue_work(system_bh_wq, &port->bh_work);827	}828	return port->users;829}830 831static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed)832{833	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;834	struct smi_port *port = dvbdmx->priv;835	struct smi_dev *dev = port->dev;836 837	if (--port->users)838		return port->users;839 840	disable_work_sync(&port->bh_work);841	smi_port_disableInterrupt(port);842	smi_clear(port->DMA_MANAGEMENT, 0x30003);843	return 0;844}845 846static int smi_dvb_init(struct smi_port *port)847{848	int ret;849	struct dvb_adapter *adap = &port->dvb_adapter;850	struct dvb_demux *dvbdemux = &port->demux;851 852	dev_dbg(&port->dev->pci_dev->dev,853		"%s, port %d\n", __func__, port->idx);854 855	ret = dvb_register_adapter(adap, "SMI_DVB", THIS_MODULE,856				   &port->dev->pci_dev->dev,857				   adapter_nr);858	if (ret < 0) {859		dev_err(&port->dev->pci_dev->dev, "Fail to register DVB adapter.\n");860		return ret;861	}862	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",863				      smi_start_feed,864				      smi_stop_feed, port);865	if (ret < 0)866		goto err_del_dvb_register_adapter;867 868	ret = my_dvb_dmxdev_ts_card_init(&port->dmxdev, &port->demux,869					 &port->hw_frontend,870					 &port->mem_frontend, adap);871	if (ret < 0)872		goto err_del_dvb_dmx;873 874	ret = dvb_net_init(adap, &port->dvbnet, port->dmxdev.demux);875	if (ret < 0)876		goto err_del_dvb_dmxdev;877	return 0;878err_del_dvb_dmxdev:879	dvbdemux->dmx.close(&dvbdemux->dmx);880	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->hw_frontend);881	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->mem_frontend);882	dvb_dmxdev_release(&port->dmxdev);883err_del_dvb_dmx:884	dvb_dmx_release(&port->demux);885err_del_dvb_register_adapter:886	dvb_unregister_adapter(&port->dvb_adapter);887	return ret;888}889 890static void smi_dvb_exit(struct smi_port *port)891{892	struct dvb_demux *dvbdemux = &port->demux;893 894	dvb_net_release(&port->dvbnet);895 896	dvbdemux->dmx.close(&dvbdemux->dmx);897	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->hw_frontend);898	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->mem_frontend);899	dvb_dmxdev_release(&port->dmxdev);900	dvb_dmx_release(&port->demux);901 902	dvb_unregister_adapter(&port->dvb_adapter);903}904 905static int smi_port_attach(struct smi_dev *dev,906		struct smi_port *port, int index)907{908	int ret, dmachs;909 910	port->dev = dev;911	port->idx = index;912	port->fe_type = (index == 0) ? dev->info->fe_0 : dev->info->fe_1;913	dmachs = (index == 0) ? dev->info->ts_0 : dev->info->ts_1;914	/* port init.*/915	ret = smi_port_init(port, dmachs);916	if (ret < 0)917		return ret;918	/* dvb init.*/919	ret = smi_dvb_init(port);920	if (ret < 0)921		goto err_del_port_init;922	/* fe init.*/923	ret = smi_fe_init(port);924	if (ret < 0)925		goto err_del_dvb_init;926	return 0;927err_del_dvb_init:928	smi_dvb_exit(port);929err_del_port_init:930	smi_port_exit(port);931	return ret;932}933 934static void smi_port_detach(struct smi_port *port)935{936	smi_fe_exit(port);937	smi_dvb_exit(port);938	smi_port_exit(port);939}940 941static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)942{943	struct smi_dev *dev;944	int ret = -ENOMEM;945 946	if (pci_enable_device(pdev) < 0)947		return -ENODEV;948 949	dev = kzalloc(sizeof(struct smi_dev), GFP_KERNEL);950	if (!dev) {951		ret = -ENOMEM;952		goto err_pci_disable_device;953	}954 955	dev->pci_dev = pdev;956	pci_set_drvdata(pdev, dev);957	dev->info = (struct smi_cfg_info *) id->driver_data;958	dev_info(&dev->pci_dev->dev,959		"card detected: %s\n", dev->info->name);960 961	dev->nr = dev->info->type;962	dev->lmmio = ioremap(pci_resource_start(dev->pci_dev, 0),963			    pci_resource_len(dev->pci_dev, 0));964	if (!dev->lmmio) {965		ret = -ENOMEM;966		goto err_kfree;967	}968 969	/* should we set to 32bit DMA? */970	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));971	if (ret < 0)972		goto err_pci_iounmap;973 974	pci_set_master(pdev);975 976	ret = smi_hw_init(dev);977	if (ret < 0)978		goto err_pci_iounmap;979 980	ret = smi_i2c_init(dev);981	if (ret < 0)982		goto err_pci_iounmap;983 984	if (dev->info->ts_0) {985		ret = smi_port_attach(dev, &dev->ts_port[0], 0);986		if (ret < 0)987			goto err_del_i2c_adaptor;988	}989 990	if (dev->info->ts_1) {991		ret = smi_port_attach(dev, &dev->ts_port[1], 1);992		if (ret < 0)993			goto err_del_port0_attach;994	}995 996	ret = smi_ir_init(dev);997	if (ret < 0)998		goto err_del_port1_attach;999 1000#ifdef CONFIG_PCI_MSI /* to do msi interrupt.???*/1001	if (pci_msi_enabled())1002		ret = pci_enable_msi(dev->pci_dev);1003	if (ret)1004		dev_info(&dev->pci_dev->dev, "MSI not available.\n");1005#endif1006 1007	ret = request_irq(dev->pci_dev->irq, smi_irq_handler,1008			   IRQF_SHARED, "SMI_PCIE", dev);1009	if (ret < 0)1010		goto err_del_ir;1011 1012	smi_ir_start(&dev->ir);1013	return 0;1014 1015err_del_ir:1016	smi_ir_exit(dev);1017err_del_port1_attach:1018	if (dev->info->ts_1)1019		smi_port_detach(&dev->ts_port[1]);1020err_del_port0_attach:1021	if (dev->info->ts_0)1022		smi_port_detach(&dev->ts_port[0]);1023err_del_i2c_adaptor:1024	smi_i2c_exit(dev);1025err_pci_iounmap:1026	iounmap(dev->lmmio);1027err_kfree:1028	pci_set_drvdata(pdev, NULL);1029	kfree(dev);1030err_pci_disable_device:1031	pci_disable_device(pdev);1032	return ret;1033}1034 1035static void smi_remove(struct pci_dev *pdev)1036{1037	struct smi_dev *dev = pci_get_drvdata(pdev);1038 1039	smi_write(MSI_INT_ENA_CLR, ALL_INT);1040	free_irq(dev->pci_dev->irq, dev);1041#ifdef CONFIG_PCI_MSI1042	pci_disable_msi(dev->pci_dev);1043#endif1044	if (dev->info->ts_1)1045		smi_port_detach(&dev->ts_port[1]);1046	if (dev->info->ts_0)1047		smi_port_detach(&dev->ts_port[0]);1048 1049	smi_ir_exit(dev);1050	smi_i2c_exit(dev);1051	iounmap(dev->lmmio);1052	pci_set_drvdata(pdev, NULL);1053	pci_disable_device(pdev);1054	kfree(dev);1055}1056 1057/* DVBSky cards */1058static const struct smi_cfg_info dvbsky_s950_cfg = {1059	.type = SMI_DVBSKY_S950,1060	.name = "DVBSky S950 V3",1061	.ts_0 = SMI_TS_NULL,1062	.ts_1 = SMI_TS_DMA_BOTH,1063	.fe_0 = DVBSKY_FE_NULL,1064	.fe_1 = DVBSKY_FE_M88DS3103,1065	.rc_map = RC_MAP_DVBSKY,1066};1067 1068static const struct smi_cfg_info dvbsky_s952_cfg = {1069	.type = SMI_DVBSKY_S952,1070	.name = "DVBSky S952 V3",1071	.ts_0 = SMI_TS_DMA_BOTH,1072	.ts_1 = SMI_TS_DMA_BOTH,1073	.fe_0 = DVBSKY_FE_M88RS6000,1074	.fe_1 = DVBSKY_FE_M88RS6000,1075	.rc_map = RC_MAP_DVBSKY,1076};1077 1078static const struct smi_cfg_info dvbsky_t9580_cfg = {1079	.type = SMI_DVBSKY_T9580,1080	.name = "DVBSky T9580 V3",1081	.ts_0 = SMI_TS_DMA_BOTH,1082	.ts_1 = SMI_TS_DMA_BOTH,1083	.fe_0 = DVBSKY_FE_SIT2,1084	.fe_1 = DVBSKY_FE_M88DS3103,1085	.rc_map = RC_MAP_DVBSKY,1086};1087 1088static const struct smi_cfg_info technotrend_s2_4200_cfg = {1089	.type = SMI_TECHNOTREND_S2_4200,1090	.name = "TechnoTrend TT-budget S2-4200 Twin",1091	.ts_0 = SMI_TS_DMA_BOTH,1092	.ts_1 = SMI_TS_DMA_BOTH,1093	.fe_0 = DVBSKY_FE_M88RS6000,1094	.fe_1 = DVBSKY_FE_M88RS6000,1095	.rc_map = RC_MAP_TT_1500,1096};1097 1098/* PCI IDs */1099#define SMI_ID(_subvend, _subdev, _driverdata) {	\1100	.vendor      = SMI_VID,    .device    = SMI_PID, \1101	.subvendor   = _subvend, .subdevice = _subdev, \1102	.driver_data = (unsigned long)&_driverdata }1103 1104static const struct pci_device_id smi_id_table[] = {1105	SMI_ID(0x4254, 0x0550, dvbsky_s950_cfg),1106	SMI_ID(0x4254, 0x0552, dvbsky_s952_cfg),1107	SMI_ID(0x4254, 0x5580, dvbsky_t9580_cfg),1108	SMI_ID(0x13c2, 0x3016, technotrend_s2_4200_cfg),1109	{0}1110};1111MODULE_DEVICE_TABLE(pci, smi_id_table);1112 1113static struct pci_driver smipcie_driver = {1114	.name = "SMI PCIe driver",1115	.id_table = smi_id_table,1116	.probe = smi_probe,1117	.remove = smi_remove,1118};1119 1120module_pci_driver(smipcie_driver);1121 1122MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");1123MODULE_DESCRIPTION("SMI PCIe driver");1124MODULE_LICENSE("GPL");1125