brintos

brintos / linux-shallow public Read only

0
0
Text · 7.0 KiB · 398e32f Raw
291 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3	Mantis PCI bridge driver4	Copyright (C) Manu Abraham (abraham.manu@gmail.com)5 6*/7 8#include <linux/kernel.h>9#include <linux/bitops.h>10 11#include <linux/signal.h>12#include <linux/sched.h>13#include <linux/interrupt.h>14#include <linux/pci.h>15#include <linux/i2c.h>16 17#include <media/dmxdev.h>18#include <media/dvbdev.h>19#include <media/dvb_demux.h>20#include <media/dvb_frontend.h>21#include <media/dvb_net.h>22 23#include "mantis_common.h"24#include "mantis_dma.h"25#include "mantis_ca.h"26#include "mantis_ioc.h"27#include "mantis_dvb.h"28 29DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);30 31int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)32{33	struct mantis_hwconfig *config = mantis->hwconfig;34 35	switch (power) {36	case POWER_ON:37		dprintk(MANTIS_DEBUG, 1, "Power ON");38		mantis_gpio_set_bits(mantis, config->power, POWER_ON);39		msleep(100);40		mantis_gpio_set_bits(mantis, config->power, POWER_ON);41		msleep(100);42		break;43 44	case POWER_OFF:45		dprintk(MANTIS_DEBUG, 1, "Power OFF");46		mantis_gpio_set_bits(mantis, config->power, POWER_OFF);47		msleep(100);48		break;49 50	default:51		dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);52		return -1;53	}54 55	return 0;56}57EXPORT_SYMBOL_GPL(mantis_frontend_power);58 59void mantis_frontend_soft_reset(struct mantis_pci *mantis)60{61	struct mantis_hwconfig *config = mantis->hwconfig;62 63	dprintk(MANTIS_DEBUG, 1, "Frontend RESET");64	mantis_gpio_set_bits(mantis, config->reset, 0);65	msleep(100);66	mantis_gpio_set_bits(mantis, config->reset, 0);67	msleep(100);68	mantis_gpio_set_bits(mantis, config->reset, 1);69	msleep(100);70	mantis_gpio_set_bits(mantis, config->reset, 1);71	msleep(100);72 73	return;74}75EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);76 77static int mantis_frontend_shutdown(struct mantis_pci *mantis)78{79	int err;80 81	mantis_frontend_soft_reset(mantis);82	err = mantis_frontend_power(mantis, POWER_OFF);83	if (err != 0) {84		dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);85		return 1;86	}87 88	return 0;89}90 91static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)92{93	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;94	struct mantis_pci *mantis = dvbdmx->priv;95 96	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");97	if (!dvbdmx->dmx.frontend) {98		dprintk(MANTIS_DEBUG, 1, "no frontend ?");99		return -EINVAL;100	}101 102	mantis->feeds++;103	dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d",	mantis->feeds);104 105	if (mantis->feeds == 1)	 {106		dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");107		mantis_dma_start(mantis);108		enable_and_queue_work(system_bh_wq, &mantis->bh_work);109	}110 111	return mantis->feeds;112}113 114static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)115{116	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;117	struct mantis_pci *mantis = dvbdmx->priv;118 119	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");120	if (!dvbdmx->dmx.frontend) {121		dprintk(MANTIS_DEBUG, 1, "no frontend ?");122		return -EINVAL;123	}124 125	mantis->feeds--;126	if (mantis->feeds == 0) {127		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");128		disable_work_sync(&mantis->bh_work);129		mantis_dma_stop(mantis);130	}131 132	return 0;133}134 135int mantis_dvb_init(struct mantis_pci *mantis)136{137	struct mantis_hwconfig *config = mantis->hwconfig;138	int result;139 140	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");141 142	result = dvb_register_adapter(&mantis->dvb_adapter,143				      "Mantis DVB adapter",144				      THIS_MODULE,145				      &mantis->pdev->dev,146				      adapter_nr);147 148	if (result < 0) {149 150		dprintk(MANTIS_ERROR, 1, "Error registering adapter");151		return -ENODEV;152	}153 154	mantis->dvb_adapter.priv	= mantis;155	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|156					 DMX_SECTION_FILTERING	|157					 DMX_MEMORY_BASED_FILTERING;158 159	mantis->demux.priv		= mantis;160	mantis->demux.filternum		= 256;161	mantis->demux.feednum		= 256;162	mantis->demux.start_feed	= mantis_dvb_start_feed;163	mantis->demux.stop_feed		= mantis_dvb_stop_feed;164	mantis->demux.write_to_decoder	= NULL;165 166	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");167	result = dvb_dmx_init(&mantis->demux);168	if (result < 0) {169		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);170 171		goto err0;172	}173 174	mantis->dmxdev.filternum	= 256;175	mantis->dmxdev.demux		= &mantis->demux.dmx;176	mantis->dmxdev.capabilities	= 0;177	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");178 179	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);180	if (result < 0) {181 182		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);183		goto err1;184	}185 186	mantis->fe_hw.source		= DMX_FRONTEND_0;187	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);188	if (result < 0) {189 190		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);191		goto err2;192	}193 194	mantis->fe_mem.source		= DMX_MEMORY_FE;195	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);196	if (result < 0) {197		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);198		goto err3;199	}200 201	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);202	if (result < 0) {203		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);204		goto err4;205	}206 207	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);208	INIT_WORK(&mantis->bh_work, mantis_dma_xfer);209	disable_work_sync(&mantis->bh_work);210	if (mantis->hwconfig) {211		result = config->frontend_init(mantis, mantis->fe);212		if (result < 0) {213			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");214			goto err5;215		} else {216			if (mantis->fe == NULL) {217				result = -ENOMEM;218				dprintk(MANTIS_ERROR, 1, "FE <NULL>");219				goto err5;220			}221			result = dvb_register_frontend(&mantis->dvb_adapter, mantis->fe);222			if (result) {223				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");224 225				if (mantis->fe->ops.release)226					mantis->fe->ops.release(mantis->fe);227 228				mantis->fe = NULL;229				goto err5;230			}231		}232	}233 234	return 0;235 236	/* Error conditions ..	*/237err5:238	cancel_work_sync(&mantis->bh_work);239	dvb_net_release(&mantis->dvbnet);240	if (mantis->fe) {241		dvb_unregister_frontend(mantis->fe);242		dvb_frontend_detach(mantis->fe);243	}244err4:245	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);246 247err3:248	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);249 250err2:251	dvb_dmxdev_release(&mantis->dmxdev);252 253err1:254	dvb_dmx_release(&mantis->demux);255 256err0:257	dvb_unregister_adapter(&mantis->dvb_adapter);258 259	return result;260}261EXPORT_SYMBOL_GPL(mantis_dvb_init);262 263int mantis_dvb_exit(struct mantis_pci *mantis)264{265	int err;266 267	if (mantis->fe) {268		/* mantis_ca_exit(mantis); */269		err = mantis_frontend_shutdown(mantis);270		if (err != 0)271			dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);272		dvb_unregister_frontend(mantis->fe);273		dvb_frontend_detach(mantis->fe);274	}275 276	cancel_work_sync(&mantis->bh_work);277	dvb_net_release(&mantis->dvbnet);278 279	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);280	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);281 282	dvb_dmxdev_release(&mantis->dmxdev);283	dvb_dmx_release(&mantis->demux);284 285	dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");286	dvb_unregister_adapter(&mantis->dvb_adapter);287 288	return 0;289}290EXPORT_SYMBOL_GPL(mantis_dvb_exit);291