Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
// SPDX-License-Identifier: GPL-2.0
/*
* c8sectpfe-common.c - C8SECTPFE STi DVB driver
*
* Copyright (c) STMicroelectronics 2015
*
* Author: Peter Griffin <peter.griffin@linaro.org>
*
*/
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dvb/dmx.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <media/dmxdev.h>
#include <media/dvbdev.h>
#include <media/dvb_demux.h>
#include <media/dvb_frontend.h>
#include <media/dvb_net.h>
#include "c8sectpfe-common.h"
#include "c8sectpfe-core.h"
#include "c8sectpfe-dvb.h"
static int register_dvb(struct stdemux *demux, struct dvb_adapter *adap,
<------><------><------><------>void *start_feed, void *stop_feed,
<------><------><------><------>struct c8sectpfei *fei)
{
<------>int result;
<------>demux->dvb_demux.dmx.capabilities = DMX_TS_FILTERING |
<------><------><------><------><------>DMX_SECTION_FILTERING |
<------><------><------><------><------>DMX_MEMORY_BASED_FILTERING;
<------>demux->dvb_demux.priv = demux;
<------>demux->dvb_demux.filternum = C8SECTPFE_MAXCHANNEL;
<------>demux->dvb_demux.feednum = C8SECTPFE_MAXCHANNEL;
<------>demux->dvb_demux.start_feed = start_feed;
<------>demux->dvb_demux.stop_feed = stop_feed;
<------>demux->dvb_demux.write_to_decoder = NULL;
<------>result = dvb_dmx_init(&demux->dvb_demux);
<------>if (result < 0) {
<------><------>dev_err(fei->dev, "dvb_dmx_init failed (errno = %d)\n",
<------><------><------>result);
<------><------>goto err_dmx;
<------>}
<------>demux->dmxdev.filternum = demux->dvb_demux.filternum;
<------>demux->dmxdev.demux = &demux->dvb_demux.dmx;
<------>demux->dmxdev.capabilities = 0;
<------>result = dvb_dmxdev_init(&demux->dmxdev, adap);
<------>if (result < 0) {
<------><------>dev_err(fei->dev, "dvb_dmxdev_init failed (errno = %d)\n",
<------><------><------>result);
<------><------>goto err_dmxdev;
<------>}
<------>demux->hw_frontend.source = DMX_FRONTEND_0 + demux->tsin_index;
<------>result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------>&demux->hw_frontend);
<------>if (result < 0) {
<------><------>dev_err(fei->dev, "add_frontend failed (errno = %d)\n", result);
<------><------>goto err_fe_hw;
<------>}
<------>demux->mem_frontend.source = DMX_MEMORY_FE;
<------>result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------>&demux->mem_frontend);
<------>if (result < 0) {
<------><------>dev_err(fei->dev, "add_frontend failed (%d)\n", result);
<------><------>goto err_fe_mem;
<------>}
<------>result = demux->dvb_demux.dmx.connect_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------><------>&demux->hw_frontend);
<------>if (result < 0) {
<------><------>dev_err(fei->dev, "connect_frontend (%d)\n", result);
<------><------>goto err_fe_con;
<------>}
<------>return 0;
err_fe_con:
<------>demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------> &demux->mem_frontend);
err_fe_mem:
<------>demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------> &demux->hw_frontend);
err_fe_hw:
<------>dvb_dmxdev_release(&demux->dmxdev);
err_dmxdev:
<------>dvb_dmx_release(&demux->dvb_demux);
err_dmx:
<------>return result;
}
static void unregister_dvb(struct stdemux *demux)
{
<------>demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------> &demux->mem_frontend);
<------>demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
<------><------><------><------><------><------> &demux->hw_frontend);
<------>dvb_dmxdev_release(&demux->dmxdev);
<------>dvb_dmx_release(&demux->dvb_demux);
}
static struct c8sectpfe *c8sectpfe_create(struct c8sectpfei *fei,
<------><------><------><------>void *start_feed,
<------><------><------><------>void *stop_feed)
{
<------>struct c8sectpfe *c8sectpfe;
<------>int result;
<------>int i, j;
<------>short int ids[] = { -1 };
<------>c8sectpfe = kzalloc(sizeof(struct c8sectpfe), GFP_KERNEL);
<------>if (!c8sectpfe)
<------><------>goto err1;
<------>mutex_init(&c8sectpfe->lock);
<------>c8sectpfe->device = fei->dev;
<------>result = dvb_register_adapter(&c8sectpfe->adapter, "STi c8sectpfe",
<------><------><------><------><------>THIS_MODULE, fei->dev, ids);
<------>if (result < 0) {
<------><------>dev_err(fei->dev, "dvb_register_adapter failed (errno = %d)\n",
<------><------><------>result);
<------><------>goto err2;
<------>}
<------>c8sectpfe->adapter.priv = fei;
<------>for (i = 0; i < fei->tsin_count; i++) {
<------><------>c8sectpfe->demux[i].tsin_index = i;
<------><------>c8sectpfe->demux[i].c8sectpfei = fei;
<------><------>result = register_dvb(&c8sectpfe->demux[i], &c8sectpfe->adapter,
<------><------><------><------>start_feed, stop_feed, fei);
<------><------>if (result < 0) {
<------><------><------>dev_err(fei->dev,
<------><------><------><------>"register_dvb feed=%d failed (errno = %d)\n",
<------><------><------><------>result, i);
<------><------><------>/* we take a all or nothing approach */
<------><------><------>for (j = 0; j < i; j++)
<------><------><------><------>unregister_dvb(&c8sectpfe->demux[j]);
<------><------><------>goto err3;
<------><------>}
<------>}
<------>c8sectpfe->num_feeds = fei->tsin_count;
<------>return c8sectpfe;
err3:
<------>dvb_unregister_adapter(&c8sectpfe->adapter);
err2:
<------>kfree(c8sectpfe);
err1:
<------>return NULL;
};
static void c8sectpfe_delete(struct c8sectpfe *c8sectpfe)
{
<------>int i;
<------>if (!c8sectpfe)
<------><------>return;
<------>for (i = 0; i < c8sectpfe->num_feeds; i++)
<------><------>unregister_dvb(&c8sectpfe->demux[i]);
<------>dvb_unregister_adapter(&c8sectpfe->adapter);
<------>kfree(c8sectpfe);
};
void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe,
<------><------><------><------><------>struct c8sectpfei *fei)
{
<------>int n;
<------>struct channel_info *tsin;
<------>for (n = 0; n < fei->tsin_count; n++) {
<------><------>tsin = fei->channel_data[n];
<------><------>if (tsin) {
<------><------><------>if (tsin->frontend) {
<------><------><------><------>dvb_unregister_frontend(tsin->frontend);
<------><------><------><------>dvb_frontend_detach(tsin->frontend);
<------><------><------>}
<------><------><------>i2c_put_adapter(tsin->i2c_adapter);
<------><------><------>if (tsin->i2c_client) {
<------><------><------><------>module_put(tsin->i2c_client->dev.driver->owner);
<------><------><------><------>i2c_unregister_device(tsin->i2c_client);
<------><------><------>}
<------><------>}
<------>}
<------>c8sectpfe_delete(c8sectpfe);
};
int c8sectpfe_tuner_register_frontend(struct c8sectpfe **c8sectpfe,
<------><------><------><------>struct c8sectpfei *fei,
<------><------><------><------>void *start_feed,
<------><------><------><------>void *stop_feed)
{
<------>struct channel_info *tsin;
<------>struct dvb_frontend *frontend;
<------>int n, res;
<------>*c8sectpfe = c8sectpfe_create(fei, start_feed, stop_feed);
<------>if (!*c8sectpfe)
<------><------>return -ENOMEM;
<------>for (n = 0; n < fei->tsin_count; n++) {
<------><------>tsin = fei->channel_data[n];
<------><------>res = c8sectpfe_frontend_attach(&frontend, *c8sectpfe, tsin, n);
<------><------>if (res)
<------><------><------>goto err;
<------><------>res = dvb_register_frontend(&c8sectpfe[0]->adapter, frontend);
<------><------>if (res < 0) {
<------><------><------>dev_err(fei->dev, "dvb_register_frontend failed (%d)\n",
<------><------><------><------>res);
<------><------><------>goto err;
<------><------>}
<------><------>tsin->frontend = frontend;
<------>}
<------>return 0;
err:
<------>c8sectpfe_tuner_unregister_frontend(*c8sectpfe, fei);
<------>return res;
}