MLK-23394-2: XUVI/PPM: driver initial version.
Initial version of XUVI/PPM driver source code. The driver is based on DVB core. It will work with XUVI/PPM FW to provide TS stream filtering and demux. Signed-off-by: Bing Song <bing.song@nxp.com> Reviewed-by: Jian Li <jian.li@nxp.com> Reviewed-by: Zhou Peng <eagle.zhou@nxp.com>5.4-rM2-2.2.x-imx-squashed
parent
92490d1837
commit
dd1846596f
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# DVB device configuration
|
||||
#
|
||||
|
||||
menu "XUVI/PPM HW TS filter and demux"
|
||||
depends on ARCH_MXC
|
||||
|
||||
config MXC_IMX_DMX_HW
|
||||
tristate "Enable HW Implementation based on XUVI/PPM"
|
||||
default y
|
||||
help
|
||||
Hardware demux driver implementation using PPM
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,3 @@
|
|||
obj-$(CONFIG_MXC_IMX_DMX_HW) += xuvi_pm.o
|
||||
obj-$(CONFIG_MXC_IMX_DMX_HW) += xuvi_mu.o
|
||||
obj-$(CONFIG_MXC_IMX_DMX_HW) += ppm.o
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright 2019-2020 NXP
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file ppm.h
|
||||
*
|
||||
* copyright here may be changed later
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef __PPM_H__
|
||||
#define __PPM_H__
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include "media/demux.h"
|
||||
|
||||
#define CONFIG_PROC_FS 1
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
|
||||
#include "media/dvbdev.h"
|
||||
#include "media/dmxdev.h"
|
||||
#include "media/demux.h"
|
||||
#include "media/dvb_demux.h"
|
||||
#include "media/dvb_frontend.h"
|
||||
#include "media/dvb_net.h"
|
||||
|
||||
#define VID_API_COMMAND_LIMIT 64
|
||||
#define PPM_MESSAGE_LIMIT 256
|
||||
#define MSG_WORD_LENGTH 3
|
||||
#define PPM_MAX_INSTANCE 2
|
||||
#define PPM_TS_188 0
|
||||
#define PPM_TS_204 1
|
||||
#define BUF_NUM 36
|
||||
#define BUF_SIZE (1*1024*1024)
|
||||
#define LOG_OFFSET (2*1024*1024)
|
||||
#define MSG_SIZE 4
|
||||
#define MU_CHANNEL 8
|
||||
#define PPM_WATCHDOG_INTERVAL_MS 1000
|
||||
|
||||
#define M0FW_FILENAME "imx/xuvi/vpu_fw_imx8_xuvi.bin"
|
||||
|
||||
enum {
|
||||
INIT_DONE = 1,
|
||||
RPC_BUF_OFFSET,
|
||||
/*PRINT_BUF_OFFSET, */
|
||||
BOOT_ADDRESS,
|
||||
COMMAND,
|
||||
EVENT,
|
||||
BUF_TO = 16,
|
||||
BUF_FROM,
|
||||
ADD_PID,
|
||||
RM_PID,
|
||||
STOP,
|
||||
HARD_FAULT,
|
||||
DRAIN_DONE,
|
||||
FLUSH_DONE,
|
||||
SNAP_SHOT
|
||||
};
|
||||
|
||||
struct event_msg {
|
||||
u32 idx;
|
||||
u32 msgnum;
|
||||
u32 msgid;
|
||||
u32 msgdata[MSG_SIZE];
|
||||
};
|
||||
|
||||
struct ppm_buf_list {
|
||||
struct list_head list;
|
||||
void *vir;
|
||||
u32 phy;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct print_buf_desc {
|
||||
u32 start_h_phy;
|
||||
u32 start_h_vir;
|
||||
u32 start_m;
|
||||
u32 bytes;
|
||||
u32 read;
|
||||
u32 write;
|
||||
char buffer[0];
|
||||
};
|
||||
|
||||
struct xuvi_mu_chan {
|
||||
struct ppm_dev *dev;
|
||||
int idx;
|
||||
struct mbox_client cl;
|
||||
struct mbox_chan *ch;
|
||||
};
|
||||
|
||||
struct ppm_ctx;
|
||||
struct ppm_dev {
|
||||
struct device *generic_dev;
|
||||
struct video_device *pppm_decoder_dev;
|
||||
struct platform_device *plat_dev;
|
||||
struct firmware *pfw;
|
||||
void *fw_space_vir;
|
||||
u32 fw_space_phy;
|
||||
u32 boot_size;
|
||||
struct mutex dev_mutex;
|
||||
struct mutex dev_ins_mutex;
|
||||
struct mutex cmd_mutex;
|
||||
bool fw_is_ready;
|
||||
bool fw_started;
|
||||
struct completion fw_start_comp;
|
||||
struct completion snap_done_comp;
|
||||
struct delayed_work watchdog;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct msg_work;
|
||||
struct clk *ppm_clk;
|
||||
struct ppm_buf_list bufs[BUF_NUM];
|
||||
struct list_head buf_list;
|
||||
struct mutex buf_list_lock;
|
||||
struct ppm_buf_list out_bufs[BUF_NUM];
|
||||
struct kfifo msg_fifo;
|
||||
|
||||
struct print_buf_desc *print_buf;
|
||||
|
||||
void __iomem *regs_base;
|
||||
void __iomem *csr_base;
|
||||
struct wait_queue_head buffer_wq;
|
||||
struct ppm_ctx *ctx[PPM_MAX_INSTANCE];
|
||||
|
||||
bool suspend;
|
||||
|
||||
struct xuvi_mu_chan mu_chans[MU_CHANNEL];
|
||||
struct device *pd_vpu;
|
||||
struct device *pd_ts;
|
||||
struct device *pd_mu;
|
||||
struct device_link *pd_vpu_link;
|
||||
struct device_link *pd_ts_link;
|
||||
struct device_link *pd_mu_link;
|
||||
};
|
||||
|
||||
struct ppm_ctx {
|
||||
struct ppm_dev *dev;
|
||||
|
||||
/* DVB stuff */
|
||||
struct dvb_adapter dvb_adapter;
|
||||
struct dvb_frontend *fe;
|
||||
struct dvb_demux demux;
|
||||
struct dmxdev dmxdev;
|
||||
struct dmx_frontend fe_hw;
|
||||
struct dmx_frontend fe_mem;
|
||||
struct dvb_net dvbnet;
|
||||
|
||||
int idx;
|
||||
struct kfifo msg_fifo;
|
||||
struct mutex instance_mutex;
|
||||
struct work_struct instance_work;
|
||||
struct workqueue_struct *instance_wq;
|
||||
struct completion stop_comp;
|
||||
struct completion eos_comp;
|
||||
bool start_flag;
|
||||
bool wait_abort_done;
|
||||
bool wait_rst_done;
|
||||
bool fw_stopped;
|
||||
bool stop_start;
|
||||
bool fw_finished;
|
||||
bool eos_stop_received;
|
||||
bool eos_stop_added;
|
||||
bool ctx_released;
|
||||
bool hang_status;
|
||||
bool instance_activated;
|
||||
u8 feeds;
|
||||
};
|
||||
|
||||
#endif // __PPM_H__ //
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 2020 NXP
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* @file xuvi_mu.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xuvi_mu.h"
|
||||
|
||||
static void xuvi_rx_callback(struct mbox_client *c, void *msg)
|
||||
{
|
||||
struct xuvi_mu_chan *mu_chan =
|
||||
container_of(c, struct xuvi_mu_chan, cl);
|
||||
struct ppm_dev *dev = mu_chan->dev;
|
||||
static uint32_t msg_mu[4], msg_mask;
|
||||
u32 *data = msg;
|
||||
|
||||
msg_mu[mu_chan->idx] = *data;
|
||||
msg_mask |= 1 << mu_chan->idx;
|
||||
|
||||
if (msg_mask == 0xF) {
|
||||
msg_mask = 0;
|
||||
if (kfifo_in(&dev->msg_fifo, msg_mu, sizeof(uint32_t) * 4)
|
||||
!= sizeof(uint32_t) * 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_work(dev->workqueue, &dev->msg_work);
|
||||
}
|
||||
}
|
||||
|
||||
int xuvi_mu_request(struct ppm_dev *dev)
|
||||
{
|
||||
struct xuvi_mu_chan *mu_chan;
|
||||
struct mbox_client *cl;
|
||||
char *chan_name;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MU_CHANNEL; i++) {
|
||||
if (i < 4)
|
||||
chan_name = kasprintf(GFP_KERNEL, "ts_tx%d", i);
|
||||
else
|
||||
chan_name =
|
||||
kasprintf(GFP_KERNEL, "ts_rx%d", i - 4);
|
||||
|
||||
if (!chan_name)
|
||||
return -ENOMEM;
|
||||
|
||||
mu_chan = &dev->mu_chans[i];
|
||||
cl = &mu_chan->cl;
|
||||
cl->dev = &dev->plat_dev->dev;
|
||||
if (i == 1 || i == 2 || i == 3) {
|
||||
cl->tx_block = false;
|
||||
} else {
|
||||
cl->tx_block = true;
|
||||
cl->tx_tout = 1000;
|
||||
}
|
||||
cl->knows_txdone = false;
|
||||
cl->rx_callback = xuvi_rx_callback;
|
||||
|
||||
mu_chan->dev = dev;
|
||||
mu_chan->idx = i % 4;
|
||||
mu_chan->ch = mbox_request_channel_byname(cl, chan_name);
|
||||
if (IS_ERR(mu_chan->ch)) {
|
||||
ret = PTR_ERR(mu_chan->ch);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
printk
|
||||
("Failed to request mbox chan %s ret %d\n",
|
||||
chan_name, ret);
|
||||
kfree(chan_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
kfree(chan_name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void xuvi_mu_free(struct ppm_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MU_CHANNEL; i++) {
|
||||
if (dev->mu_chans[i].ch && !IS_ERR(dev->mu_chans[i].ch))
|
||||
mbox_free_channel(dev->mu_chans[i].ch);
|
||||
dev->mu_chans[i].ch = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void xuvi_mu_send_msg(struct ppm_dev *dev, uint32_t value0,
|
||||
uint32_t value1, uint32_t value2, uint32_t value3)
|
||||
{
|
||||
mbox_send_message(dev->mu_chans[3].ch, &value3);
|
||||
mbox_send_message(dev->mu_chans[2].ch, &value2);
|
||||
mbox_send_message(dev->mu_chans[1].ch, &value1);
|
||||
mbox_send_message(dev->mu_chans[0].ch, &value0);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2020 NXP
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* @file xuvi_mu.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _XUVI_MU_H_
|
||||
#define _XUVI_MU_H_
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mx8_mu.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mailbox_client.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
#include "ppm.h"
|
||||
|
||||
int xuvi_mu_request(struct ppm_dev *dev);
|
||||
void xuvi_mu_free(struct ppm_dev *dev);
|
||||
void xuvi_mu_send_msg(struct ppm_dev *dev, uint32_t value0,
|
||||
uint32_t value1, uint32_t value2, uint32_t value3);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright 2020 NXP
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* @file xuvi_pm.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xuvi_pm.h"
|
||||
#define vpu_err printk
|
||||
int xuvi_attach_pm_domains(struct ppm_dev *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dev->pd_vpu =
|
||||
dev_pm_domain_attach_by_name(&dev->plat_dev->dev, "vpu");
|
||||
if (IS_ERR(dev->pd_vpu)) {
|
||||
vpu_err("error: %s unable to get vpu power domain\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(dev->pd_vpu);
|
||||
goto err;
|
||||
}
|
||||
dev->pd_vpu_link =
|
||||
device_link_add(&dev->plat_dev->dev, dev->pd_vpu,
|
||||
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |
|
||||
DL_FLAG_RPM_ACTIVE);
|
||||
if (IS_ERR(dev->pd_vpu_link)) {
|
||||
vpu_err("error: %s unable to link vpu power domain\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(dev->pd_vpu_link);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev->pd_ts =
|
||||
dev_pm_domain_attach_by_name(&dev->plat_dev->dev, "vputs");
|
||||
if (IS_ERR(dev->pd_ts)) {
|
||||
vpu_err("error: %s unable to get vpu ts power domain\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(dev->pd_ts);
|
||||
goto err;
|
||||
}
|
||||
dev->pd_ts_link = device_link_add(&dev->plat_dev->dev, dev->pd_ts,
|
||||
DL_FLAG_STATELESS |
|
||||
DL_FLAG_PM_RUNTIME |
|
||||
DL_FLAG_RPM_ACTIVE);
|
||||
if (IS_ERR(dev->pd_ts_link)) {
|
||||
vpu_err("error: %s unable to link vpu ts power domain\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(dev->pd_ts_link);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev->pd_mu =
|
||||
dev_pm_domain_attach_by_name(&dev->plat_dev->dev, "vpumu3");
|
||||
if (IS_ERR(dev->pd_mu)) {
|
||||
vpu_err("error: %s unable to get vpu mu0 power domain\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(dev->pd_mu);
|
||||
goto err;
|
||||
}
|
||||
dev->pd_mu_link = device_link_add(&dev->plat_dev->dev, dev->pd_mu,
|
||||
DL_FLAG_STATELESS |
|
||||
DL_FLAG_PM_RUNTIME |
|
||||
DL_FLAG_RPM_ACTIVE);
|
||||
if (IS_ERR(dev->pd_mu_link)) {
|
||||
vpu_err("error: %s unable to link vpu mu0 power domain\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(dev->pd_mu_link);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
err:
|
||||
xuvi_detach_pm_domains(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void xuvi_detach_pm_domains(struct ppm_dev *dev)
|
||||
{
|
||||
if (dev->pd_vpu_link && !IS_ERR(dev->pd_vpu_link))
|
||||
device_link_del(dev->pd_vpu_link);
|
||||
if (dev->pd_vpu && !IS_ERR(dev->pd_vpu))
|
||||
dev_pm_domain_detach(dev->pd_vpu, true);
|
||||
|
||||
if (dev->pd_ts_link && !IS_ERR(dev->pd_ts_link))
|
||||
device_link_del(dev->pd_ts_link);
|
||||
if (dev->pd_ts && !IS_ERR(dev->pd_ts))
|
||||
dev_pm_domain_detach(dev->pd_ts, true);
|
||||
|
||||
if (dev->pd_mu_link && !IS_ERR(dev->pd_mu_link))
|
||||
device_link_del(dev->pd_mu_link);
|
||||
if (dev->pd_mu && !IS_ERR(dev->pd_mu))
|
||||
dev_pm_domain_detach(dev->pd_mu, true);
|
||||
|
||||
dev->pd_vpu = NULL;
|
||||
dev->pd_vpu_link = NULL;
|
||||
dev->pd_ts = NULL;
|
||||
dev->pd_ts_link = NULL;
|
||||
dev->pd_mu = NULL;
|
||||
dev->pd_mu_link = NULL;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2020 NXP
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* @file xuvi_pm.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _XUVI_PM_H_
|
||||
#define _XUVI_PM_H_
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "ppm.h"
|
||||
|
||||
int xuvi_attach_pm_domains(struct ppm_dev *dev);
|
||||
void xuvi_detach_pm_domains(struct ppm_dev *dev);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue