Re: [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
Hi Mauro, Thanks for reviewing. On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote: > Em Wed, 24 Jun 2015 16:11:05 +0100 > Peter Griffin escreveu: > > > This patch adds support for the c8sectpfe input HW found on > > STiH407/410 SoC's. > > > > It currently supports the TS input block, memdma engine > > and hw PID filtering blocks of the C8SECTPFE subsystem. > > > > The driver creates one LinuxDVB adapter, and a > > demux/dvr/frontend set of devices for each tsin channel > > which is specificed in the DT. It has been tested with > > multiple tsin channels tuned, locked, and grabbing TS > > simultaneously. > > > > Signed-off-by: Peter Griffin > > --- > > drivers/media/tsin/c8sectpfe/c8sectpfe-core.c | 1105 > > + > > drivers/media/tsin/c8sectpfe/c8sectpfe-core.h | 288 +++ > > 2 files changed, 1393 insertions(+) > > create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > > create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h > > > > diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > > b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > > new file mode 100644 > > index 000..fbbe323 > > --- /dev/null > > +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > > @@ -0,0 +1,1105 @@ > > +/* > > + * c8sectpfe-core.c - C8SECTPFE STi DVB driver > > + * > > + * Copyright (c) STMicroelectronics 2015 > > + * > > + * Author:Peter Bennett > > + * Peter Griffin > > + * > > + * 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; either version 2 of > > + * the License, or (at your option) any later version. > > + */ > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "c8sectpfe-core.h" > > +#include "c8sectpfe-common.h" > > +#include "c8sectpfe-debugfs.h" > > +#include "dmxdev.h" > > +#include "dvb_demux.h" > > +#include "dvb_frontend.h" > > +#include "dvb_net.h" > > + > > +#define FIRMWARE_MEMDMA "pti_memdma_h407.elf" > > +MODULE_FIRMWARE(FIRMWARE_MEMDMA); > > + > > +#define PID_TABLE_SIZE 1024 > > +#define POLL_20_HZ_DIV 20 /* poll at 20 Hz */ > > + > > +static int load_slim_core_fw(struct c8sectpfei *fei); > > + > > +#define TS_PKT_SIZE 188 > > +#define HEADER_SIZE (4) > > +#define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE) > > + > > +#define FEI_ALIGNMENT (32) > > +/* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */ > > +#define FEI_BUFFER_SIZE (8*PACKET_SIZE*340) > > + > > +#define FIFO_LEN 1024 > > + > > +static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei) > > +{ > > + struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei; > > + struct channel_info *channel; > > + int chan_num; > > + > > + /* iterate through input block channels */ > > + for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) { > > + channel = fei->channel_data[chan_num]; > > + > > + /* is this descriptor initialised and TP enabled */ > > + if (channel->irec && readl((void __iomem *) > > + &channel->irec->tp_enable)) > > + tasklet_schedule(&channel->tsklet); > > + } > > + > > + fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV); > > Please use the macros for jiffies conversions. In this case, I guess > you want to use ms_to_jiffies(), right? Fixed in V2. > > > + add_timer(&fei->timer); > > +} > > + > > +static void channel_swdemux_tsklet(unsigned long data) > > +{ > > + struct channel_info *channel = (struct channel_info *)data; > > + struct c8sectpfei *fei = channel->fei; > > + struct tpentry *ptrblk; > > + unsigned long wp, rp; > > + int pos, num_packets, n, size; > > + u8 *buf; > > + > > + BUG_ON(!channel); > > + BUG_ON(!channel->irec); > > Please avoid using BUG_ON() except when the machine will be on some > unstable state. In this case, I guess you could just do: > > if (unlikely(!channel || !channel->irec) > return; Yes ok, I have removed the BUG_ON's in v2 > > > + > > + ptrblk = &channel->irec->ptr_data[0]; > > + > > + wp = readl((void __iomem *)&ptrblk->dma_bus_wp); > > + rp = readl((void __iomem *)&ptrblk->dma_bus_rp); > > Why do you need those typecasts? We try to avoid typecasts in the Kernel, > doing it only where really needed. Same for other usages. You should > probably declare those DMA buffers as __iomem *, and avoid the casts. Ok, I've fixed this in V2. > > > + > > + pos = rp - channel->back_buffer_busaddr; > > + > > + /* has it wrapped */ > > + if (wp < rp) > > + wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE; > > + > > + size
Re: [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
Em Wed, 24 Jun 2015 16:11:05 +0100 Peter Griffin escreveu: > This patch adds support for the c8sectpfe input HW found on > STiH407/410 SoC's. > > It currently supports the TS input block, memdma engine > and hw PID filtering blocks of the C8SECTPFE subsystem. > > The driver creates one LinuxDVB adapter, and a > demux/dvr/frontend set of devices for each tsin channel > which is specificed in the DT. It has been tested with > multiple tsin channels tuned, locked, and grabbing TS > simultaneously. > > Signed-off-by: Peter Griffin > --- > drivers/media/tsin/c8sectpfe/c8sectpfe-core.c | 1105 > + > drivers/media/tsin/c8sectpfe/c8sectpfe-core.h | 288 +++ > 2 files changed, 1393 insertions(+) > create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h > > diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > new file mode 100644 > index 000..fbbe323 > --- /dev/null > +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c > @@ -0,0 +1,1105 @@ > +/* > + * c8sectpfe-core.c - C8SECTPFE STi DVB driver > + * > + * Copyright (c) STMicroelectronics 2015 > + * > + * Author:Peter Bennett > + * Peter Griffin > + * > + * 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; either version 2 of > + * the License, or (at your option) any later version. > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "c8sectpfe-core.h" > +#include "c8sectpfe-common.h" > +#include "c8sectpfe-debugfs.h" > +#include "dmxdev.h" > +#include "dvb_demux.h" > +#include "dvb_frontend.h" > +#include "dvb_net.h" > + > +#define FIRMWARE_MEMDMA "pti_memdma_h407.elf" > +MODULE_FIRMWARE(FIRMWARE_MEMDMA); > + > +#define PID_TABLE_SIZE 1024 > +#define POLL_20_HZ_DIV 20 /* poll at 20 Hz */ > + > +static int load_slim_core_fw(struct c8sectpfei *fei); > + > +#define TS_PKT_SIZE 188 > +#define HEADER_SIZE (4) > +#define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE) > + > +#define FEI_ALIGNMENT (32) > +/* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */ > +#define FEI_BUFFER_SIZE (8*PACKET_SIZE*340) > + > +#define FIFO_LEN 1024 > + > +static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei) > +{ > + struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei; > + struct channel_info *channel; > + int chan_num; > + > + /* iterate through input block channels */ > + for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) { > + channel = fei->channel_data[chan_num]; > + > + /* is this descriptor initialised and TP enabled */ > + if (channel->irec && readl((void __iomem *) > + &channel->irec->tp_enable)) > + tasklet_schedule(&channel->tsklet); > + } > + > + fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV); Please use the macros for jiffies conversions. In this case, I guess you want to use ms_to_jiffies(), right? > + add_timer(&fei->timer); > +} > + > +static void channel_swdemux_tsklet(unsigned long data) > +{ > + struct channel_info *channel = (struct channel_info *)data; > + struct c8sectpfei *fei = channel->fei; > + struct tpentry *ptrblk; > + unsigned long wp, rp; > + int pos, num_packets, n, size; > + u8 *buf; > + > + BUG_ON(!channel); > + BUG_ON(!channel->irec); Please avoid using BUG_ON() except when the machine will be on some unstable state. In this case, I guess you could just do: if (unlikely(!channel || !channel->irec) return; > + > + ptrblk = &channel->irec->ptr_data[0]; > + > + wp = readl((void __iomem *)&ptrblk->dma_bus_wp); > + rp = readl((void __iomem *)&ptrblk->dma_bus_rp); Why do you need those typecasts? We try to avoid typecasts in the Kernel, doing it only where really needed. Same for other usages. You should probably declare those DMA buffers as __iomem *, and avoid the casts. > + > + pos = rp - channel->back_buffer_busaddr; > + > + /* has it wrapped */ > + if (wp < rp) > + wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE; > + > + size = wp - rp; > + num_packets = size / PACKET_SIZE; > + > + /* manage cache so data is visible to CPU */ > + dma_sync_single_for_cpu(fei->dev, > + rp, > + size, > + DMA_FROM_DEVICE); > + > + buf = (u8 *) channel->back_buffer_aligned; > + > + dev_dbg(fei->dev, > + "chan=%d channel=%p num_pac
[PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
This patch adds support for the c8sectpfe input HW found on STiH407/410 SoC's. It currently supports the TS input block, memdma engine and hw PID filtering blocks of the C8SECTPFE subsystem. The driver creates one LinuxDVB adapter, and a demux/dvr/frontend set of devices for each tsin channel which is specificed in the DT. It has been tested with multiple tsin channels tuned, locked, and grabbing TS simultaneously. Signed-off-by: Peter Griffin --- drivers/media/tsin/c8sectpfe/c8sectpfe-core.c | 1105 + drivers/media/tsin/c8sectpfe/c8sectpfe-core.h | 288 +++ 2 files changed, 1393 insertions(+) create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c new file mode 100644 index 000..fbbe323 --- /dev/null +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c @@ -0,0 +1,1105 @@ +/* + * c8sectpfe-core.c - C8SECTPFE STi DVB driver + * + * Copyright (c) STMicroelectronics 2015 + * + * Author:Peter Bennett + * Peter Griffin + * + * 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; either version 2 of + * the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c8sectpfe-core.h" +#include "c8sectpfe-common.h" +#include "c8sectpfe-debugfs.h" +#include "dmxdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#define FIRMWARE_MEMDMA "pti_memdma_h407.elf" +MODULE_FIRMWARE(FIRMWARE_MEMDMA); + +#define PID_TABLE_SIZE 1024 +#define POLL_20_HZ_DIV 20 /* poll at 20 Hz */ + +static int load_slim_core_fw(struct c8sectpfei *fei); + +#define TS_PKT_SIZE 188 +#define HEADER_SIZE (4) +#define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE) + +#define FEI_ALIGNMENT (32) +/* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */ +#define FEI_BUFFER_SIZE (8*PACKET_SIZE*340) + +#define FIFO_LEN 1024 + +static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei) +{ + struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei; + struct channel_info *channel; + int chan_num; + + /* iterate through input block channels */ + for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) { + channel = fei->channel_data[chan_num]; + + /* is this descriptor initialised and TP enabled */ + if (channel->irec && readl((void __iomem *) + &channel->irec->tp_enable)) + tasklet_schedule(&channel->tsklet); + } + + fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV); + add_timer(&fei->timer); +} + +static void channel_swdemux_tsklet(unsigned long data) +{ + struct channel_info *channel = (struct channel_info *)data; + struct c8sectpfei *fei = channel->fei; + struct tpentry *ptrblk; + unsigned long wp, rp; + int pos, num_packets, n, size; + u8 *buf; + + BUG_ON(!channel); + BUG_ON(!channel->irec); + + ptrblk = &channel->irec->ptr_data[0]; + + wp = readl((void __iomem *)&ptrblk->dma_bus_wp); + rp = readl((void __iomem *)&ptrblk->dma_bus_rp); + + pos = rp - channel->back_buffer_busaddr; + + /* has it wrapped */ + if (wp < rp) + wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE; + + size = wp - rp; + num_packets = size / PACKET_SIZE; + + /* manage cache so data is visible to CPU */ + dma_sync_single_for_cpu(fei->dev, + rp, + size, + DMA_FROM_DEVICE); + + buf = (u8 *) channel->back_buffer_aligned; + + dev_dbg(fei->dev, + "chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\t" + "rp=0x%lx, wp=0x%lx\n", + channel->tsin_id, channel, num_packets, buf, pos, rp, wp); + + for (n = 0; n < num_packets; n++) { + dvb_dmx_swfilter_packets( + &fei->c8sectpfe[0]-> + demux[channel->demux_mapping].dvb_demux, + &buf[pos], 1); + + pos += PACKET_SIZE; + } + + /* advance the read pointer */ + if (wp == (channel->back_buffer_busaddr + FEI_BUFFER_SIZE)) + writel(channel->back_buffer_busaddr, + (void __iomem *)&ptrblk->dma_bus_rp); + else + writel(wp, (void __iomem *)&ptrblk->dma_bus_rp); +} + +static int c8sectpfe_start_feed(struct d