Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: c8sectpfe: remove support of STi c8sectpfe driver

STi c8sectpfe device is only used on B2120 boards, which support has
been withdrawn in commit dee546e1adef ("ARM: sti: drop B2120 board
support").

Signed-off-by: Raphael Gallais-Pou <rgallaispou@gmail.com>
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Raphael Gallais-Pou and committed by
Hans Verkuil
2282f761 2a0935ac

-2329
-1
MAINTAINERS
··· 3437 3437 F: drivers/cpufreq/sti-cpufreq.c 3438 3438 F: drivers/dma/st_fdma* 3439 3439 F: drivers/i2c/busses/i2c-st.c 3440 - F: drivers/media/platform/st/sti/c8sectpfe/ 3441 3440 F: drivers/media/rc/st_rc.c 3442 3441 F: drivers/mmc/host/sdhci-st.c 3443 3442 F: drivers/phy/st/phy-miphy28lp.c
-1
drivers/media/platform/st/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 3 3 obj-y += sti/bdisp/ 4 - obj-y += sti/c8sectpfe/ 5 4 obj-y += sti/delta/ 6 5 obj-y += sti/hva/ 7 6 obj-y += stm32/
-1
drivers/media/platform/st/sti/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 source "drivers/media/platform/st/sti/bdisp/Kconfig" 3 - source "drivers/media/platform/st/sti/c8sectpfe/Kconfig" 4 3 source "drivers/media/platform/st/sti/delta/Kconfig" 5 4 source "drivers/media/platform/st/sti/hva/Kconfig"
-1
drivers/media/platform/st/sti/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-y += bdisp/ 3 - obj-y += c8sectpfe/ 4 3 obj-y += delta/ 5 4 obj-y += hva/ 6 5 obj-y += stm32/
-28
drivers/media/platform/st/sti/c8sectpfe/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - config DVB_C8SECTPFE 3 - tristate "STMicroelectronics C8SECTPFE DVB support" 4 - depends on DVB_PLATFORM_DRIVERS 5 - depends on PINCTRL && DVB_CORE && I2C 6 - depends on ARCH_STI || ARCH_MULTIPLATFORM || COMPILE_TEST 7 - select FW_LOADER 8 - select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT 9 - select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT 10 - select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT 11 - select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT 12 - select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT 13 - select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT 14 - select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT 15 - 16 - help 17 - This adds support for DVB front-end cards connected 18 - to TS inputs of STiH407/410 SoC. 19 - 20 - The driver currently supports C8SECTPFE's TS input block, 21 - memdma engine, and HW PID filtering. 22 - 23 - Supported DVB front-end cards are: 24 - - STMicroelectronics DVB-T B2100A (STV0367 + TDA18212) 25 - - STMicroelectronics DVB-S/S2 STV0903 + STV6110 + LNBP24 board 26 - 27 - To compile this driver as a module, choose M here: the 28 - module will be called c8sectpfe.
-11
drivers/media/platform/st/sti/c8sectpfe/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o 3 - 4 - ifneq ($(CONFIG_DEBUG_FS),) 5 - c8sectpfe-y += c8sectpfe-debugfs.o 6 - endif 7 - 8 - obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o 9 - 10 - ccflags-y += -I $(srctree)/drivers/media/dvb-frontends/ 11 - ccflags-y += -I $(srctree)/drivers/media/tuners/
-262
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-common.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * c8sectpfe-common.c - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author: Peter Griffin <peter.griffin@linaro.org> 8 - * 9 - */ 10 - #include <linux/completion.h> 11 - #include <linux/delay.h> 12 - #include <linux/device.h> 13 - #include <linux/dvb/dmx.h> 14 - #include <linux/errno.h> 15 - #include <linux/init.h> 16 - #include <linux/interrupt.h> 17 - #include <linux/io.h> 18 - #include <linux/ioport.h> 19 - #include <linux/module.h> 20 - #include <linux/slab.h> 21 - #include <linux/time.h> 22 - #include <linux/wait.h> 23 - 24 - #include <media/dmxdev.h> 25 - #include <media/dvbdev.h> 26 - #include <media/dvb_demux.h> 27 - #include <media/dvb_frontend.h> 28 - #include <media/dvb_net.h> 29 - 30 - #include "c8sectpfe-common.h" 31 - #include "c8sectpfe-core.h" 32 - #include "c8sectpfe-dvb.h" 33 - 34 - static int register_dvb(struct stdemux *demux, struct dvb_adapter *adap, 35 - void *start_feed, void *stop_feed, 36 - struct c8sectpfei *fei) 37 - { 38 - int result; 39 - 40 - demux->dvb_demux.dmx.capabilities = DMX_TS_FILTERING | 41 - DMX_SECTION_FILTERING | 42 - DMX_MEMORY_BASED_FILTERING; 43 - 44 - demux->dvb_demux.priv = demux; 45 - demux->dvb_demux.filternum = C8SECTPFE_MAXCHANNEL; 46 - demux->dvb_demux.feednum = C8SECTPFE_MAXCHANNEL; 47 - 48 - demux->dvb_demux.start_feed = start_feed; 49 - demux->dvb_demux.stop_feed = stop_feed; 50 - demux->dvb_demux.write_to_decoder = NULL; 51 - 52 - result = dvb_dmx_init(&demux->dvb_demux); 53 - if (result < 0) { 54 - dev_err(fei->dev, "dvb_dmx_init failed (errno = %d)\n", 55 - result); 56 - goto err_dmx; 57 - } 58 - 59 - demux->dmxdev.filternum = demux->dvb_demux.filternum; 60 - demux->dmxdev.demux = &demux->dvb_demux.dmx; 61 - demux->dmxdev.capabilities = 0; 62 - 63 - result = dvb_dmxdev_init(&demux->dmxdev, adap); 64 - if (result < 0) { 65 - dev_err(fei->dev, "dvb_dmxdev_init failed (errno = %d)\n", 66 - result); 67 - 68 - goto err_dmxdev; 69 - } 70 - 71 - demux->hw_frontend.source = DMX_FRONTEND_0 + demux->tsin_index; 72 - 73 - result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx, 74 - &demux->hw_frontend); 75 - if (result < 0) { 76 - dev_err(fei->dev, "add_frontend failed (errno = %d)\n", result); 77 - goto err_fe_hw; 78 - } 79 - 80 - demux->mem_frontend.source = DMX_MEMORY_FE; 81 - result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx, 82 - &demux->mem_frontend); 83 - if (result < 0) { 84 - dev_err(fei->dev, "add_frontend failed (%d)\n", result); 85 - goto err_fe_mem; 86 - } 87 - 88 - result = demux->dvb_demux.dmx.connect_frontend(&demux->dvb_demux.dmx, 89 - &demux->hw_frontend); 90 - if (result < 0) { 91 - dev_err(fei->dev, "connect_frontend (%d)\n", result); 92 - goto err_fe_con; 93 - } 94 - 95 - return 0; 96 - 97 - err_fe_con: 98 - demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx, 99 - &demux->mem_frontend); 100 - err_fe_mem: 101 - demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx, 102 - &demux->hw_frontend); 103 - err_fe_hw: 104 - dvb_dmxdev_release(&demux->dmxdev); 105 - err_dmxdev: 106 - dvb_dmx_release(&demux->dvb_demux); 107 - err_dmx: 108 - return result; 109 - 110 - } 111 - 112 - static void unregister_dvb(struct stdemux *demux) 113 - { 114 - 115 - demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx, 116 - &demux->mem_frontend); 117 - 118 - demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx, 119 - &demux->hw_frontend); 120 - 121 - dvb_dmxdev_release(&demux->dmxdev); 122 - 123 - dvb_dmx_release(&demux->dvb_demux); 124 - } 125 - 126 - static struct c8sectpfe *c8sectpfe_create(struct c8sectpfei *fei, 127 - void *start_feed, 128 - void *stop_feed) 129 - { 130 - struct c8sectpfe *c8sectpfe; 131 - int result; 132 - int i, j; 133 - 134 - short int ids[] = { -1 }; 135 - 136 - c8sectpfe = kzalloc(sizeof(struct c8sectpfe), GFP_KERNEL); 137 - if (!c8sectpfe) 138 - goto err1; 139 - 140 - mutex_init(&c8sectpfe->lock); 141 - 142 - c8sectpfe->device = fei->dev; 143 - 144 - result = dvb_register_adapter(&c8sectpfe->adapter, "STi c8sectpfe", 145 - THIS_MODULE, fei->dev, ids); 146 - if (result < 0) { 147 - dev_err(fei->dev, "dvb_register_adapter failed (errno = %d)\n", 148 - result); 149 - goto err2; 150 - } 151 - 152 - c8sectpfe->adapter.priv = fei; 153 - 154 - for (i = 0; i < fei->tsin_count; i++) { 155 - 156 - c8sectpfe->demux[i].tsin_index = i; 157 - c8sectpfe->demux[i].c8sectpfei = fei; 158 - 159 - result = register_dvb(&c8sectpfe->demux[i], &c8sectpfe->adapter, 160 - start_feed, stop_feed, fei); 161 - if (result < 0) { 162 - dev_err(fei->dev, 163 - "register_dvb feed=%d failed (errno = %d)\n", 164 - result, i); 165 - 166 - /* we take a all or nothing approach */ 167 - for (j = 0; j < i; j++) 168 - unregister_dvb(&c8sectpfe->demux[j]); 169 - goto err3; 170 - } 171 - } 172 - 173 - c8sectpfe->num_feeds = fei->tsin_count; 174 - 175 - return c8sectpfe; 176 - err3: 177 - dvb_unregister_adapter(&c8sectpfe->adapter); 178 - err2: 179 - kfree(c8sectpfe); 180 - err1: 181 - return NULL; 182 - }; 183 - 184 - static void c8sectpfe_delete(struct c8sectpfe *c8sectpfe) 185 - { 186 - int i; 187 - 188 - if (!c8sectpfe) 189 - return; 190 - 191 - for (i = 0; i < c8sectpfe->num_feeds; i++) 192 - unregister_dvb(&c8sectpfe->demux[i]); 193 - 194 - dvb_unregister_adapter(&c8sectpfe->adapter); 195 - 196 - kfree(c8sectpfe); 197 - }; 198 - 199 - void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe, 200 - struct c8sectpfei *fei) 201 - { 202 - int n; 203 - struct channel_info *tsin; 204 - 205 - for (n = 0; n < fei->tsin_count; n++) { 206 - 207 - tsin = fei->channel_data[n]; 208 - 209 - if (tsin) { 210 - if (tsin->frontend) { 211 - dvb_unregister_frontend(tsin->frontend); 212 - dvb_frontend_detach(tsin->frontend); 213 - } 214 - 215 - i2c_put_adapter(tsin->i2c_adapter); 216 - 217 - if (tsin->i2c_client) { 218 - module_put(tsin->i2c_client->dev.driver->owner); 219 - i2c_unregister_device(tsin->i2c_client); 220 - } 221 - } 222 - } 223 - 224 - c8sectpfe_delete(c8sectpfe); 225 - }; 226 - 227 - int c8sectpfe_tuner_register_frontend(struct c8sectpfe **c8sectpfe, 228 - struct c8sectpfei *fei, 229 - void *start_feed, 230 - void *stop_feed) 231 - { 232 - struct channel_info *tsin; 233 - struct dvb_frontend *frontend; 234 - int n, res; 235 - 236 - *c8sectpfe = c8sectpfe_create(fei, start_feed, stop_feed); 237 - if (!*c8sectpfe) 238 - return -ENOMEM; 239 - 240 - for (n = 0; n < fei->tsin_count; n++) { 241 - tsin = fei->channel_data[n]; 242 - 243 - res = c8sectpfe_frontend_attach(&frontend, *c8sectpfe, tsin, n); 244 - if (res) 245 - goto err; 246 - 247 - res = dvb_register_frontend(&c8sectpfe[0]->adapter, frontend); 248 - if (res < 0) { 249 - dev_err(fei->dev, "dvb_register_frontend failed (%d)\n", 250 - res); 251 - goto err; 252 - } 253 - 254 - tsin->frontend = frontend; 255 - } 256 - 257 - return 0; 258 - 259 - err: 260 - c8sectpfe_tuner_unregister_frontend(*c8sectpfe, fei); 261 - return res; 262 - }
-60
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-common.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * c8sectpfe-common.h - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author: Peter Griffin <peter.griffin@linaro.org> 8 - * 9 - */ 10 - #ifndef _C8SECTPFE_COMMON_H_ 11 - #define _C8SECTPFE_COMMON_H_ 12 - 13 - #include <linux/dvb/dmx.h> 14 - #include <linux/dvb/frontend.h> 15 - #include <linux/gpio.h> 16 - 17 - #include <media/dmxdev.h> 18 - #include <media/dvb_demux.h> 19 - #include <media/dvb_frontend.h> 20 - #include <media/dvb_net.h> 21 - 22 - /* Maximum number of channels */ 23 - #define C8SECTPFE_MAXADAPTER (4) 24 - #define C8SECTPFE_MAXCHANNEL 64 25 - #define STPTI_MAXCHANNEL 64 26 - 27 - #define MAX_INPUTBLOCKS 7 28 - 29 - struct c8sectpfe; 30 - struct stdemux; 31 - 32 - struct stdemux { 33 - struct dvb_demux dvb_demux; 34 - struct dmxdev dmxdev; 35 - struct dmx_frontend hw_frontend; 36 - struct dmx_frontend mem_frontend; 37 - int tsin_index; 38 - int running_feed_count; 39 - struct c8sectpfei *c8sectpfei; 40 - }; 41 - 42 - struct c8sectpfe { 43 - struct stdemux demux[MAX_INPUTBLOCKS]; 44 - struct mutex lock; 45 - struct dvb_adapter adapter; 46 - struct device *device; 47 - int mapping; 48 - int num_feeds; 49 - }; 50 - 51 - /* Channel registration */ 52 - int c8sectpfe_tuner_register_frontend(struct c8sectpfe **c8sectpfe, 53 - struct c8sectpfei *fei, 54 - void *start_feed, 55 - void *stop_feed); 56 - 57 - void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe, 58 - struct c8sectpfei *fei); 59 - 60 - #endif
-1158
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * c8sectpfe-core.c - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author:Peter Bennett <peter.bennett@st.com> 8 - * Peter Griffin <peter.griffin@linaro.org> 9 - * 10 - */ 11 - #include <linux/atomic.h> 12 - #include <linux/clk.h> 13 - #include <linux/completion.h> 14 - #include <linux/delay.h> 15 - #include <linux/device.h> 16 - #include <linux/dma-mapping.h> 17 - #include <linux/dvb/dmx.h> 18 - #include <linux/dvb/frontend.h> 19 - #include <linux/err.h> 20 - #include <linux/errno.h> 21 - #include <linux/firmware.h> 22 - #include <linux/gpio/consumer.h> 23 - #include <linux/init.h> 24 - #include <linux/interrupt.h> 25 - #include <linux/io.h> 26 - #include <linux/module.h> 27 - #include <linux/of_platform.h> 28 - #include <linux/pinctrl/consumer.h> 29 - #include <linux/pinctrl/pinctrl.h> 30 - #include <linux/platform_device.h> 31 - #include <linux/slab.h> 32 - #include <linux/time.h> 33 - #include <linux/usb.h> 34 - #include <linux/wait.h> 35 - 36 - #include "c8sectpfe-common.h" 37 - #include "c8sectpfe-core.h" 38 - #include "c8sectpfe-debugfs.h" 39 - 40 - #include <media/dmxdev.h> 41 - #include <media/dvb_demux.h> 42 - #include <media/dvb_frontend.h> 43 - #include <media/dvb_net.h> 44 - 45 - #define FIRMWARE_MEMDMA "pti_memdma_h407.elf" 46 - MODULE_FIRMWARE(FIRMWARE_MEMDMA); 47 - 48 - #define PID_TABLE_SIZE 1024 49 - #define POLL_MSECS 50 50 - 51 - static int load_c8sectpfe_fw(struct c8sectpfei *fei); 52 - 53 - #define TS_PKT_SIZE 188 54 - #define HEADER_SIZE (4) 55 - #define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE) 56 - 57 - #define FEI_ALIGNMENT (32) 58 - /* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */ 59 - #define FEI_BUFFER_SIZE (8*PACKET_SIZE*340) 60 - 61 - #define FIFO_LEN 1024 62 - 63 - static void c8sectpfe_timer_interrupt(struct timer_list *t) 64 - { 65 - struct c8sectpfei *fei = timer_container_of(fei, t, timer); 66 - struct channel_info *channel; 67 - int chan_num; 68 - 69 - /* iterate through input block channels */ 70 - for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) { 71 - channel = fei->channel_data[chan_num]; 72 - 73 - /* is this descriptor initialised and TP enabled */ 74 - if (channel->irec && readl(channel->irec + DMA_PRDS_TPENABLE)) 75 - queue_work(system_bh_wq, &channel->bh_work); 76 - } 77 - 78 - fei->timer.expires = jiffies + msecs_to_jiffies(POLL_MSECS); 79 - add_timer(&fei->timer); 80 - } 81 - 82 - static void channel_swdemux_bh_work(struct work_struct *t) 83 - { 84 - struct channel_info *channel = from_work(channel, t, bh_work); 85 - struct c8sectpfei *fei; 86 - unsigned long wp, rp; 87 - int pos, num_packets, n, size; 88 - u8 *buf; 89 - 90 - if (unlikely(!channel || !channel->irec)) 91 - return; 92 - 93 - fei = channel->fei; 94 - 95 - wp = readl(channel->irec + DMA_PRDS_BUSWP_TP(0)); 96 - rp = readl(channel->irec + DMA_PRDS_BUSRP_TP(0)); 97 - 98 - pos = rp - channel->back_buffer_busaddr; 99 - 100 - /* has it wrapped */ 101 - if (wp < rp) 102 - wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE; 103 - 104 - size = wp - rp; 105 - num_packets = size / PACKET_SIZE; 106 - 107 - /* manage cache so data is visible to CPU */ 108 - dma_sync_single_for_cpu(fei->dev, 109 - rp, 110 - size, 111 - DMA_FROM_DEVICE); 112 - 113 - buf = channel->back_buffer_aligned; 114 - 115 - dev_dbg(fei->dev, 116 - "chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\trp=0x%lx, wp=0x%lx\n", 117 - channel->tsin_id, channel, num_packets, buf, pos, rp, wp); 118 - 119 - for (n = 0; n < num_packets; n++) { 120 - dvb_dmx_swfilter_packets( 121 - &fei->c8sectpfe[0]-> 122 - demux[channel->demux_mapping].dvb_demux, 123 - &buf[pos], 1); 124 - 125 - pos += PACKET_SIZE; 126 - } 127 - 128 - /* advance the read pointer */ 129 - if (wp == (channel->back_buffer_busaddr + FEI_BUFFER_SIZE)) 130 - writel(channel->back_buffer_busaddr, channel->irec + 131 - DMA_PRDS_BUSRP_TP(0)); 132 - else 133 - writel(wp, channel->irec + DMA_PRDS_BUSRP_TP(0)); 134 - } 135 - 136 - static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) 137 - { 138 - struct dvb_demux *demux = dvbdmxfeed->demux; 139 - struct stdemux *stdemux = demux->priv; 140 - struct c8sectpfei *fei = stdemux->c8sectpfei; 141 - struct channel_info *channel; 142 - u32 tmp; 143 - unsigned long *bitmap; 144 - int ret; 145 - 146 - switch (dvbdmxfeed->type) { 147 - case DMX_TYPE_TS: 148 - break; 149 - case DMX_TYPE_SEC: 150 - break; 151 - default: 152 - dev_err(fei->dev, "%s:%d Error bailing\n" 153 - , __func__, __LINE__); 154 - return -EINVAL; 155 - } 156 - 157 - if (dvbdmxfeed->type == DMX_TYPE_TS) { 158 - switch (dvbdmxfeed->pes_type) { 159 - case DMX_PES_VIDEO: 160 - case DMX_PES_AUDIO: 161 - case DMX_PES_TELETEXT: 162 - case DMX_PES_PCR: 163 - case DMX_PES_OTHER: 164 - break; 165 - default: 166 - dev_err(fei->dev, "%s:%d Error bailing\n" 167 - , __func__, __LINE__); 168 - return -EINVAL; 169 - } 170 - } 171 - 172 - if (!atomic_read(&fei->fw_loaded)) { 173 - ret = load_c8sectpfe_fw(fei); 174 - if (ret) 175 - return ret; 176 - } 177 - 178 - mutex_lock(&fei->lock); 179 - 180 - channel = fei->channel_data[stdemux->tsin_index]; 181 - 182 - bitmap = channel->pid_buffer_aligned; 183 - 184 - /* 8192 is a special PID */ 185 - if (dvbdmxfeed->pid == 8192) { 186 - tmp = readl(fei->io + C8SECTPFE_IB_PID_SET(channel->tsin_id)); 187 - tmp &= ~C8SECTPFE_PID_ENABLE; 188 - writel(tmp, fei->io + C8SECTPFE_IB_PID_SET(channel->tsin_id)); 189 - 190 - } else { 191 - bitmap_set(bitmap, dvbdmxfeed->pid, 1); 192 - } 193 - 194 - /* manage cache so PID bitmap is visible to HW */ 195 - dma_sync_single_for_device(fei->dev, 196 - channel->pid_buffer_busaddr, 197 - PID_TABLE_SIZE, 198 - DMA_TO_DEVICE); 199 - 200 - channel->active = 1; 201 - 202 - if (fei->global_feed_count == 0) { 203 - fei->timer.expires = jiffies + 204 - msecs_to_jiffies(msecs_to_jiffies(POLL_MSECS)); 205 - 206 - add_timer(&fei->timer); 207 - } 208 - 209 - if (stdemux->running_feed_count == 0) { 210 - 211 - dev_dbg(fei->dev, "Starting channel=%p\n", channel); 212 - 213 - INIT_WORK(&channel->bh_work, channel_swdemux_bh_work); 214 - 215 - /* Reset the internal inputblock sram pointers */ 216 - writel(channel->fifo, 217 - fei->io + C8SECTPFE_IB_BUFF_STRT(channel->tsin_id)); 218 - writel(channel->fifo + FIFO_LEN - 1, 219 - fei->io + C8SECTPFE_IB_BUFF_END(channel->tsin_id)); 220 - 221 - writel(channel->fifo, 222 - fei->io + C8SECTPFE_IB_READ_PNT(channel->tsin_id)); 223 - writel(channel->fifo, 224 - fei->io + C8SECTPFE_IB_WRT_PNT(channel->tsin_id)); 225 - 226 - 227 - /* reset read / write memdma ptrs for this channel */ 228 - writel(channel->back_buffer_busaddr, channel->irec + 229 - DMA_PRDS_BUSBASE_TP(0)); 230 - 231 - tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1; 232 - writel(tmp, channel->irec + DMA_PRDS_BUSTOP_TP(0)); 233 - 234 - writel(channel->back_buffer_busaddr, channel->irec + 235 - DMA_PRDS_BUSWP_TP(0)); 236 - 237 - /* Issue a reset and enable InputBlock */ 238 - writel(C8SECTPFE_SYS_ENABLE | C8SECTPFE_SYS_RESET 239 - , fei->io + C8SECTPFE_IB_SYS(channel->tsin_id)); 240 - 241 - /* and enable the tp */ 242 - writel(0x1, channel->irec + DMA_PRDS_TPENABLE); 243 - 244 - dev_dbg(fei->dev, "%s:%d Starting DMA feed on stdemux=%p\n" 245 - , __func__, __LINE__, stdemux); 246 - } 247 - 248 - stdemux->running_feed_count++; 249 - fei->global_feed_count++; 250 - 251 - mutex_unlock(&fei->lock); 252 - 253 - return 0; 254 - } 255 - 256 - static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 257 - { 258 - 259 - struct dvb_demux *demux = dvbdmxfeed->demux; 260 - struct stdemux *stdemux = demux->priv; 261 - struct c8sectpfei *fei = stdemux->c8sectpfei; 262 - struct channel_info *channel; 263 - int idlereq; 264 - u32 tmp; 265 - int ret; 266 - unsigned long *bitmap; 267 - 268 - if (!atomic_read(&fei->fw_loaded)) { 269 - ret = load_c8sectpfe_fw(fei); 270 - if (ret) 271 - return ret; 272 - } 273 - 274 - mutex_lock(&fei->lock); 275 - 276 - channel = fei->channel_data[stdemux->tsin_index]; 277 - 278 - bitmap = channel->pid_buffer_aligned; 279 - 280 - if (dvbdmxfeed->pid == 8192) { 281 - tmp = readl(fei->io + C8SECTPFE_IB_PID_SET(channel->tsin_id)); 282 - tmp |= C8SECTPFE_PID_ENABLE; 283 - writel(tmp, fei->io + C8SECTPFE_IB_PID_SET(channel->tsin_id)); 284 - } else { 285 - bitmap_clear(bitmap, dvbdmxfeed->pid, 1); 286 - } 287 - 288 - /* manage cache so data is visible to HW */ 289 - dma_sync_single_for_device(fei->dev, 290 - channel->pid_buffer_busaddr, 291 - PID_TABLE_SIZE, 292 - DMA_TO_DEVICE); 293 - 294 - if (--stdemux->running_feed_count == 0) { 295 - 296 - channel = fei->channel_data[stdemux->tsin_index]; 297 - 298 - /* TP re-configuration on page 168 of functional spec */ 299 - 300 - /* disable IB (prevents more TS data going to memdma) */ 301 - writel(0, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id)); 302 - 303 - /* disable this channels descriptor */ 304 - writel(0, channel->irec + DMA_PRDS_TPENABLE); 305 - 306 - disable_work_sync(&channel->bh_work); 307 - 308 - /* now request memdma channel goes idle */ 309 - idlereq = (1 << channel->tsin_id) | IDLEREQ; 310 - writel(idlereq, fei->io + DMA_IDLE_REQ); 311 - 312 - /* wait for idle irq handler to signal completion */ 313 - ret = wait_for_completion_timeout(&channel->idle_completion, 314 - msecs_to_jiffies(100)); 315 - 316 - if (ret == 0) 317 - dev_warn(fei->dev, 318 - "Timeout waiting for idle irq on tsin%d\n", 319 - channel->tsin_id); 320 - 321 - reinit_completion(&channel->idle_completion); 322 - 323 - /* reset read / write ptrs for this channel */ 324 - 325 - writel(channel->back_buffer_busaddr, 326 - channel->irec + DMA_PRDS_BUSBASE_TP(0)); 327 - 328 - tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1; 329 - writel(tmp, channel->irec + DMA_PRDS_BUSTOP_TP(0)); 330 - 331 - writel(channel->back_buffer_busaddr, 332 - channel->irec + DMA_PRDS_BUSWP_TP(0)); 333 - 334 - dev_dbg(fei->dev, 335 - "%s:%d stopping DMA feed on stdemux=%p channel=%d\n", 336 - __func__, __LINE__, stdemux, channel->tsin_id); 337 - 338 - /* turn off all PIDS in the bitmap */ 339 - memset(channel->pid_buffer_aligned, 0, PID_TABLE_SIZE); 340 - 341 - /* manage cache so data is visible to HW */ 342 - dma_sync_single_for_device(fei->dev, 343 - channel->pid_buffer_busaddr, 344 - PID_TABLE_SIZE, 345 - DMA_TO_DEVICE); 346 - 347 - channel->active = 0; 348 - } 349 - 350 - if (--fei->global_feed_count == 0) { 351 - dev_dbg(fei->dev, "%s:%d global_feed_count=%d\n" 352 - , __func__, __LINE__, fei->global_feed_count); 353 - 354 - timer_delete(&fei->timer); 355 - } 356 - 357 - mutex_unlock(&fei->lock); 358 - 359 - return 0; 360 - } 361 - 362 - static struct channel_info *find_channel(struct c8sectpfei *fei, int tsin_num) 363 - { 364 - int i; 365 - 366 - for (i = 0; i < C8SECTPFE_MAX_TSIN_CHAN; i++) { 367 - if (!fei->channel_data[i]) 368 - continue; 369 - 370 - if (fei->channel_data[i]->tsin_id == tsin_num) 371 - return fei->channel_data[i]; 372 - } 373 - 374 - return NULL; 375 - } 376 - 377 - static void c8sectpfe_getconfig(struct c8sectpfei *fei) 378 - { 379 - struct c8sectpfe_hw *hw = &fei->hw_stats; 380 - 381 - hw->num_ib = readl(fei->io + SYS_CFG_NUM_IB); 382 - hw->num_mib = readl(fei->io + SYS_CFG_NUM_MIB); 383 - hw->num_swts = readl(fei->io + SYS_CFG_NUM_SWTS); 384 - hw->num_tsout = readl(fei->io + SYS_CFG_NUM_TSOUT); 385 - hw->num_ccsc = readl(fei->io + SYS_CFG_NUM_CCSC); 386 - hw->num_ram = readl(fei->io + SYS_CFG_NUM_RAM); 387 - hw->num_tp = readl(fei->io + SYS_CFG_NUM_TP); 388 - 389 - dev_info(fei->dev, "C8SECTPFE hw supports the following:\n"); 390 - dev_info(fei->dev, "Input Blocks: %d\n", hw->num_ib); 391 - dev_info(fei->dev, "Merged Input Blocks: %d\n", hw->num_mib); 392 - dev_info(fei->dev, "Software Transport Stream Inputs: %d\n" 393 - , hw->num_swts); 394 - dev_info(fei->dev, "Transport Stream Output: %d\n", hw->num_tsout); 395 - dev_info(fei->dev, "Cable Card Converter: %d\n", hw->num_ccsc); 396 - dev_info(fei->dev, "RAMs supported by C8SECTPFE: %d\n", hw->num_ram); 397 - dev_info(fei->dev, "Tango TPs supported by C8SECTPFE: %d\n" 398 - , hw->num_tp); 399 - } 400 - 401 - static irqreturn_t c8sectpfe_idle_irq_handler(int irq, void *priv) 402 - { 403 - struct c8sectpfei *fei = priv; 404 - struct channel_info *chan; 405 - int bit; 406 - unsigned long tmp = readl(fei->io + DMA_IDLE_REQ); 407 - 408 - /* page 168 of functional spec: Clear the idle request 409 - by writing 0 to the C8SECTPFE_DMA_IDLE_REQ register. */ 410 - 411 - /* signal idle completion */ 412 - for_each_set_bit(bit, &tmp, fei->hw_stats.num_ib) { 413 - 414 - chan = find_channel(fei, bit); 415 - 416 - if (chan) 417 - complete(&chan->idle_completion); 418 - } 419 - 420 - writel(0, fei->io + DMA_IDLE_REQ); 421 - 422 - return IRQ_HANDLED; 423 - } 424 - 425 - 426 - static void free_input_block(struct c8sectpfei *fei, struct channel_info *tsin) 427 - { 428 - if (!fei || !tsin) 429 - return; 430 - 431 - if (tsin->back_buffer_busaddr) 432 - if (!dma_mapping_error(fei->dev, tsin->back_buffer_busaddr)) 433 - dma_unmap_single(fei->dev, tsin->back_buffer_busaddr, 434 - FEI_BUFFER_SIZE, DMA_BIDIRECTIONAL); 435 - 436 - kfree(tsin->back_buffer_start); 437 - 438 - if (tsin->pid_buffer_busaddr) 439 - if (!dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr)) 440 - dma_unmap_single(fei->dev, tsin->pid_buffer_busaddr, 441 - PID_TABLE_SIZE, DMA_BIDIRECTIONAL); 442 - 443 - kfree(tsin->pid_buffer_start); 444 - } 445 - 446 - #define MAX_NAME 20 447 - 448 - static int configure_memdma_and_inputblock(struct c8sectpfei *fei, 449 - struct channel_info *tsin) 450 - { 451 - int ret; 452 - u32 tmp; 453 - char tsin_pin_name[MAX_NAME]; 454 - 455 - if (!fei || !tsin) 456 - return -EINVAL; 457 - 458 - dev_dbg(fei->dev, "%s:%d Configuring channel=%p tsin=%d\n" 459 - , __func__, __LINE__, tsin, tsin->tsin_id); 460 - 461 - init_completion(&tsin->idle_completion); 462 - 463 - tsin->back_buffer_start = kzalloc(FEI_BUFFER_SIZE + FEI_ALIGNMENT, GFP_KERNEL); 464 - if (!tsin->back_buffer_start) { 465 - ret = -ENOMEM; 466 - goto err_unmap; 467 - } 468 - 469 - /* Ensure backbuffer is 32byte aligned */ 470 - tsin->back_buffer_aligned = tsin->back_buffer_start + FEI_ALIGNMENT; 471 - 472 - tsin->back_buffer_aligned = PTR_ALIGN(tsin->back_buffer_aligned, FEI_ALIGNMENT); 473 - 474 - tsin->back_buffer_busaddr = dma_map_single(fei->dev, 475 - tsin->back_buffer_aligned, 476 - FEI_BUFFER_SIZE, 477 - DMA_BIDIRECTIONAL); 478 - 479 - if (dma_mapping_error(fei->dev, tsin->back_buffer_busaddr)) { 480 - dev_err(fei->dev, "failed to map back_buffer\n"); 481 - ret = -EFAULT; 482 - goto err_unmap; 483 - } 484 - 485 - /* 486 - * The pid buffer can be configured (in hw) for byte or bit 487 - * per pid. By powers of deduction we conclude stih407 family 488 - * is configured (at SoC design stage) for bit per pid. 489 - */ 490 - tsin->pid_buffer_start = kzalloc(PID_TABLE_SIZE + PID_TABLE_SIZE, GFP_KERNEL); 491 - if (!tsin->pid_buffer_start) { 492 - ret = -ENOMEM; 493 - goto err_unmap; 494 - } 495 - 496 - /* 497 - * PID buffer needs to be aligned to size of the pid table 498 - * which at bit per pid is 1024 bytes (8192 pids / 8). 499 - * PIDF_BASE register enforces this alignment when writing 500 - * the register. 501 - */ 502 - 503 - tsin->pid_buffer_aligned = tsin->pid_buffer_start + PID_TABLE_SIZE; 504 - 505 - tsin->pid_buffer_aligned = PTR_ALIGN(tsin->pid_buffer_aligned, PID_TABLE_SIZE); 506 - 507 - tsin->pid_buffer_busaddr = dma_map_single(fei->dev, 508 - tsin->pid_buffer_aligned, 509 - PID_TABLE_SIZE, 510 - DMA_BIDIRECTIONAL); 511 - 512 - if (dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr)) { 513 - dev_err(fei->dev, "failed to map pid_bitmap\n"); 514 - ret = -EFAULT; 515 - goto err_unmap; 516 - } 517 - 518 - /* manage cache so pid bitmap is visible to HW */ 519 - dma_sync_single_for_device(fei->dev, 520 - tsin->pid_buffer_busaddr, 521 - PID_TABLE_SIZE, 522 - DMA_TO_DEVICE); 523 - 524 - snprintf(tsin_pin_name, MAX_NAME, "tsin%d-%s", tsin->tsin_id, 525 - (tsin->serial_not_parallel ? "serial" : "parallel")); 526 - 527 - tsin->pstate = pinctrl_lookup_state(fei->pinctrl, tsin_pin_name); 528 - if (IS_ERR(tsin->pstate)) { 529 - dev_err(fei->dev, "%s: pinctrl_lookup_state couldn't find %s state\n" 530 - , __func__, tsin_pin_name); 531 - ret = PTR_ERR(tsin->pstate); 532 - goto err_unmap; 533 - } 534 - 535 - ret = pinctrl_select_state(fei->pinctrl, tsin->pstate); 536 - 537 - if (ret) { 538 - dev_err(fei->dev, "%s: pinctrl_select_state failed\n" 539 - , __func__); 540 - goto err_unmap; 541 - } 542 - 543 - /* Enable this input block */ 544 - tmp = readl(fei->io + SYS_INPUT_CLKEN); 545 - tmp |= BIT(tsin->tsin_id); 546 - writel(tmp, fei->io + SYS_INPUT_CLKEN); 547 - 548 - if (tsin->serial_not_parallel) 549 - tmp |= C8SECTPFE_SERIAL_NOT_PARALLEL; 550 - 551 - if (tsin->invert_ts_clk) 552 - tmp |= C8SECTPFE_INVERT_TSCLK; 553 - 554 - if (tsin->async_not_sync) 555 - tmp |= C8SECTPFE_ASYNC_NOT_SYNC; 556 - 557 - tmp |= C8SECTPFE_ALIGN_BYTE_SOP | C8SECTPFE_BYTE_ENDIANNESS_MSB; 558 - 559 - writel(tmp, fei->io + C8SECTPFE_IB_IP_FMT_CFG(tsin->tsin_id)); 560 - 561 - writel(C8SECTPFE_SYNC(0x9) | 562 - C8SECTPFE_DROP(0x9) | 563 - C8SECTPFE_TOKEN(0x47), 564 - fei->io + C8SECTPFE_IB_SYNCLCKDRP_CFG(tsin->tsin_id)); 565 - 566 - writel(TS_PKT_SIZE, fei->io + C8SECTPFE_IB_PKT_LEN(tsin->tsin_id)); 567 - 568 - /* Place the FIFO's at the end of the irec descriptors */ 569 - 570 - tsin->fifo = (tsin->tsin_id * FIFO_LEN); 571 - 572 - writel(tsin->fifo, fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id)); 573 - writel(tsin->fifo + FIFO_LEN - 1, 574 - fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id)); 575 - 576 - writel(tsin->fifo, fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id)); 577 - writel(tsin->fifo, fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id)); 578 - 579 - writel(tsin->pid_buffer_busaddr, 580 - fei->io + PIDF_BASE(tsin->tsin_id)); 581 - 582 - dev_dbg(fei->dev, "chan=%d PIDF_BASE=0x%x pid_bus_addr=%pad\n", 583 - tsin->tsin_id, readl(fei->io + PIDF_BASE(tsin->tsin_id)), 584 - &tsin->pid_buffer_busaddr); 585 - 586 - /* Configure and enable HW PID filtering */ 587 - 588 - /* 589 - * The PID value is created by assembling the first 8 bytes of 590 - * the TS packet into a 64-bit word in big-endian format. A 591 - * slice of that 64-bit word is taken from 592 - * (PID_OFFSET+PID_NUM_BITS-1) to PID_OFFSET. 593 - */ 594 - tmp = (C8SECTPFE_PID_ENABLE | C8SECTPFE_PID_NUMBITS(13) 595 - | C8SECTPFE_PID_OFFSET(40)); 596 - 597 - writel(tmp, fei->io + C8SECTPFE_IB_PID_SET(tsin->tsin_id)); 598 - 599 - dev_dbg(fei->dev, "chan=%d setting wp: %d, rp: %d, buf: %d-%d\n", 600 - tsin->tsin_id, 601 - readl(fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id)), 602 - readl(fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id)), 603 - readl(fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id)), 604 - readl(fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id))); 605 - 606 - /* Get base addpress of pointer record block from DMEM */ 607 - tsin->irec = fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 608 - readl(fei->io + DMA_PTRREC_BASE); 609 - 610 - /* fill out pointer record data structure */ 611 - 612 - /* advance pointer record block to our channel */ 613 - tsin->irec += (tsin->tsin_id * DMA_PRDS_SIZE); 614 - 615 - writel(tsin->fifo, tsin->irec + DMA_PRDS_MEMBASE); 616 - 617 - writel(tsin->fifo + FIFO_LEN - 1, tsin->irec + DMA_PRDS_MEMTOP); 618 - 619 - writel((188 + 7)&~7, tsin->irec + DMA_PRDS_PKTSIZE); 620 - 621 - writel(0x1, tsin->irec + DMA_PRDS_TPENABLE); 622 - 623 - /* read/write pointers with physical bus address */ 624 - 625 - writel(tsin->back_buffer_busaddr, tsin->irec + DMA_PRDS_BUSBASE_TP(0)); 626 - 627 - tmp = tsin->back_buffer_busaddr + FEI_BUFFER_SIZE - 1; 628 - writel(tmp, tsin->irec + DMA_PRDS_BUSTOP_TP(0)); 629 - 630 - writel(tsin->back_buffer_busaddr, tsin->irec + DMA_PRDS_BUSWP_TP(0)); 631 - writel(tsin->back_buffer_busaddr, tsin->irec + DMA_PRDS_BUSRP_TP(0)); 632 - 633 - /* initialize bh work */ 634 - INIT_WORK(&tsin->bh_work, channel_swdemux_bh_work); 635 - 636 - return 0; 637 - 638 - err_unmap: 639 - free_input_block(fei, tsin); 640 - return ret; 641 - } 642 - 643 - static irqreturn_t c8sectpfe_error_irq_handler(int irq, void *priv) 644 - { 645 - struct c8sectpfei *fei = priv; 646 - 647 - dev_err(fei->dev, "%s: error handling not yet implemented\n" 648 - , __func__); 649 - 650 - /* 651 - * TODO FIXME we should detect some error conditions here 652 - * and ideally do something about them! 653 - */ 654 - 655 - return IRQ_HANDLED; 656 - } 657 - 658 - static int c8sectpfe_probe(struct platform_device *pdev) 659 - { 660 - struct device *dev = &pdev->dev; 661 - struct device_node *np = dev->of_node; 662 - struct c8sectpfei *fei; 663 - struct resource *res; 664 - int ret, index = 0; 665 - struct channel_info *tsin; 666 - 667 - /* Allocate the c8sectpfei structure */ 668 - fei = devm_kzalloc(dev, sizeof(struct c8sectpfei), GFP_KERNEL); 669 - if (!fei) 670 - return -ENOMEM; 671 - 672 - fei->dev = dev; 673 - 674 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "c8sectpfe"); 675 - fei->io = devm_ioremap_resource(dev, res); 676 - if (IS_ERR(fei->io)) 677 - return PTR_ERR(fei->io); 678 - 679 - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 680 - "c8sectpfe-ram"); 681 - fei->sram = devm_ioremap_resource(dev, res); 682 - if (IS_ERR(fei->sram)) 683 - return PTR_ERR(fei->sram); 684 - 685 - fei->sram_size = resource_size(res); 686 - 687 - fei->idle_irq = platform_get_irq_byname(pdev, "c8sectpfe-idle-irq"); 688 - if (fei->idle_irq < 0) 689 - return fei->idle_irq; 690 - 691 - fei->error_irq = platform_get_irq_byname(pdev, "c8sectpfe-error-irq"); 692 - if (fei->error_irq < 0) 693 - return fei->error_irq; 694 - 695 - platform_set_drvdata(pdev, fei); 696 - 697 - fei->c8sectpfeclk = devm_clk_get_enabled(dev, "c8sectpfe"); 698 - if (IS_ERR(fei->c8sectpfeclk)) { 699 - dev_err(dev, "Failed to enable c8sectpfe clock\n"); 700 - return PTR_ERR(fei->c8sectpfeclk); 701 - } 702 - 703 - /* to save power disable all IP's (on by default) */ 704 - writel(0, fei->io + SYS_INPUT_CLKEN); 705 - 706 - /* Enable memdma clock */ 707 - writel(MEMDMAENABLE, fei->io + SYS_OTHER_CLKEN); 708 - 709 - /* clear internal sram */ 710 - memset_io(fei->sram, 0x0, fei->sram_size); 711 - 712 - c8sectpfe_getconfig(fei); 713 - 714 - ret = devm_request_irq(dev, fei->idle_irq, c8sectpfe_idle_irq_handler, 715 - 0, "c8sectpfe-idle-irq", fei); 716 - if (ret) { 717 - dev_err(dev, "Can't register c8sectpfe-idle-irq IRQ.\n"); 718 - return ret; 719 - } 720 - 721 - ret = devm_request_irq(dev, fei->error_irq, 722 - c8sectpfe_error_irq_handler, 0, 723 - "c8sectpfe-error-irq", fei); 724 - if (ret) { 725 - dev_err(dev, "Can't register c8sectpfe-error-irq IRQ.\n"); 726 - return ret; 727 - } 728 - 729 - fei->tsin_count = of_get_child_count(np); 730 - 731 - if (fei->tsin_count > C8SECTPFE_MAX_TSIN_CHAN || 732 - fei->tsin_count > fei->hw_stats.num_ib) { 733 - 734 - dev_err(dev, "More tsin declared than exist on SoC!\n"); 735 - return -EINVAL; 736 - } 737 - 738 - fei->pinctrl = devm_pinctrl_get(dev); 739 - 740 - if (IS_ERR(fei->pinctrl)) { 741 - dev_err(dev, "Error getting tsin pins\n"); 742 - return PTR_ERR(fei->pinctrl); 743 - } 744 - 745 - for_each_child_of_node_scoped(np, child) { 746 - struct device_node *i2c_bus; 747 - 748 - fei->channel_data[index] = devm_kzalloc(dev, 749 - sizeof(struct channel_info), 750 - GFP_KERNEL); 751 - 752 - if (!fei->channel_data[index]) 753 - return -ENOMEM; 754 - 755 - tsin = fei->channel_data[index]; 756 - 757 - tsin->fei = fei; 758 - 759 - ret = of_property_read_u32(child, "tsin-num", &tsin->tsin_id); 760 - if (ret) { 761 - dev_err(&pdev->dev, "No tsin_num found\n"); 762 - return ret; 763 - } 764 - 765 - /* sanity check value */ 766 - if (tsin->tsin_id > fei->hw_stats.num_ib) { 767 - dev_err(&pdev->dev, 768 - "tsin-num %d specified greater than number\n\tof input block hw in SoC! (%d)", 769 - tsin->tsin_id, fei->hw_stats.num_ib); 770 - return -EINVAL; 771 - } 772 - 773 - tsin->invert_ts_clk = of_property_read_bool(child, 774 - "invert-ts-clk"); 775 - 776 - tsin->serial_not_parallel = of_property_read_bool(child, 777 - "serial-not-parallel"); 778 - 779 - tsin->async_not_sync = of_property_read_bool(child, 780 - "async-not-sync"); 781 - 782 - ret = of_property_read_u32(child, "dvb-card", 783 - &tsin->dvb_card); 784 - if (ret) { 785 - dev_err(&pdev->dev, "No dvb-card found\n"); 786 - return ret; 787 - } 788 - 789 - i2c_bus = of_parse_phandle(child, "i2c-bus", 0); 790 - if (!i2c_bus) { 791 - dev_err(&pdev->dev, "No i2c-bus found\n"); 792 - return -ENODEV; 793 - } 794 - tsin->i2c_adapter = 795 - of_find_i2c_adapter_by_node(i2c_bus); 796 - of_node_put(i2c_bus); 797 - if (!tsin->i2c_adapter) { 798 - dev_err(&pdev->dev, "No i2c adapter found\n"); 799 - return -ENODEV; 800 - } 801 - 802 - /* Acquire reset GPIO and activate it */ 803 - tsin->rst_gpio = devm_fwnode_gpiod_get(dev, 804 - of_fwnode_handle(child), 805 - "reset", GPIOD_OUT_HIGH, 806 - "NIM reset"); 807 - ret = PTR_ERR_OR_ZERO(tsin->rst_gpio); 808 - if (ret && ret != -EBUSY) { 809 - dev_err(dev, "Can't request tsin%d reset gpio\n", 810 - fei->channel_data[index]->tsin_id); 811 - return ret; 812 - } 813 - 814 - if (!ret) { 815 - /* wait for the chip to reset */ 816 - usleep_range(3500, 5000); 817 - /* release the reset line */ 818 - gpiod_set_value_cansleep(tsin->rst_gpio, 0); 819 - usleep_range(3000, 5000); 820 - } 821 - 822 - tsin->demux_mapping = index; 823 - 824 - dev_dbg(fei->dev, 825 - "channel=%p n=%d tsin_num=%d, invert-ts-clk=%d\n\tserial-not-parallel=%d pkt-clk-valid=%d dvb-card=%d\n", 826 - fei->channel_data[index], index, 827 - tsin->tsin_id, tsin->invert_ts_clk, 828 - tsin->serial_not_parallel, tsin->async_not_sync, 829 - tsin->dvb_card); 830 - 831 - index++; 832 - } 833 - 834 - /* Setup timer interrupt */ 835 - timer_setup(&fei->timer, c8sectpfe_timer_interrupt, 0); 836 - 837 - mutex_init(&fei->lock); 838 - 839 - /* Get the configuration information about the tuners */ 840 - ret = c8sectpfe_tuner_register_frontend(&fei->c8sectpfe[0], 841 - (void *)fei, 842 - c8sectpfe_start_feed, 843 - c8sectpfe_stop_feed); 844 - if (ret) { 845 - dev_err(dev, "c8sectpfe_tuner_register_frontend failed (%d)\n", 846 - ret); 847 - return ret; 848 - } 849 - 850 - c8sectpfe_debugfs_init(fei); 851 - 852 - return 0; 853 - } 854 - 855 - static void c8sectpfe_remove(struct platform_device *pdev) 856 - { 857 - struct c8sectpfei *fei = platform_get_drvdata(pdev); 858 - struct channel_info *channel; 859 - int i; 860 - 861 - wait_for_completion(&fei->fw_ack); 862 - 863 - c8sectpfe_tuner_unregister_frontend(fei->c8sectpfe[0], fei); 864 - 865 - /* 866 - * Now loop through and un-configure each of the InputBlock resources 867 - */ 868 - for (i = 0; i < fei->tsin_count; i++) { 869 - channel = fei->channel_data[i]; 870 - free_input_block(fei, channel); 871 - } 872 - 873 - c8sectpfe_debugfs_exit(fei); 874 - 875 - dev_info(fei->dev, "Stopping memdma SLIM core\n"); 876 - if (readl(fei->io + DMA_CPU_RUN)) 877 - writel(0x0, fei->io + DMA_CPU_RUN); 878 - 879 - /* unclock all internal IP's */ 880 - if (readl(fei->io + SYS_INPUT_CLKEN)) 881 - writel(0, fei->io + SYS_INPUT_CLKEN); 882 - 883 - if (readl(fei->io + SYS_OTHER_CLKEN)) 884 - writel(0, fei->io + SYS_OTHER_CLKEN); 885 - } 886 - 887 - 888 - static int configure_channels(struct c8sectpfei *fei) 889 - { 890 - int index = 0, ret; 891 - struct device_node *np = fei->dev->of_node; 892 - 893 - /* iterate round each tsin and configure memdma descriptor and IB hw */ 894 - for_each_child_of_node_scoped(np, child) { 895 - ret = configure_memdma_and_inputblock(fei, 896 - fei->channel_data[index]); 897 - if (ret) { 898 - dev_err(fei->dev, 899 - "configure_memdma_and_inputblock failed\n"); 900 - goto err_unmap; 901 - } 902 - index++; 903 - } 904 - 905 - return 0; 906 - 907 - err_unmap: 908 - while (--index >= 0) 909 - free_input_block(fei, fei->channel_data[index]); 910 - 911 - return ret; 912 - } 913 - 914 - static int 915 - c8sectpfe_elf_sanity_check(struct c8sectpfei *fei, const struct firmware *fw) 916 - { 917 - struct elf32_hdr *ehdr; 918 - char class; 919 - 920 - if (!fw) { 921 - dev_err(fei->dev, "failed to load %s\n", FIRMWARE_MEMDMA); 922 - return -EINVAL; 923 - } 924 - 925 - if (fw->size < sizeof(struct elf32_hdr)) { 926 - dev_err(fei->dev, "Image is too small\n"); 927 - return -EINVAL; 928 - } 929 - 930 - ehdr = (struct elf32_hdr *)fw->data; 931 - 932 - /* We only support ELF32 at this point */ 933 - class = ehdr->e_ident[EI_CLASS]; 934 - if (class != ELFCLASS32) { 935 - dev_err(fei->dev, "Unsupported class: %d\n", class); 936 - return -EINVAL; 937 - } 938 - 939 - if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { 940 - dev_err(fei->dev, "Unsupported firmware endianness\n"); 941 - return -EINVAL; 942 - } 943 - 944 - if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) { 945 - dev_err(fei->dev, "Image is too small\n"); 946 - return -EINVAL; 947 - } 948 - 949 - if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { 950 - dev_err(fei->dev, "Image is corrupted (bad magic)\n"); 951 - return -EINVAL; 952 - } 953 - 954 - /* Check ELF magic */ 955 - ehdr = (Elf32_Ehdr *)fw->data; 956 - if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || 957 - ehdr->e_ident[EI_MAG1] != ELFMAG1 || 958 - ehdr->e_ident[EI_MAG2] != ELFMAG2 || 959 - ehdr->e_ident[EI_MAG3] != ELFMAG3) { 960 - dev_err(fei->dev, "Invalid ELF magic\n"); 961 - return -EINVAL; 962 - } 963 - 964 - if (ehdr->e_type != ET_EXEC) { 965 - dev_err(fei->dev, "Unsupported ELF header type\n"); 966 - return -EINVAL; 967 - } 968 - 969 - if (ehdr->e_phoff > fw->size) { 970 - dev_err(fei->dev, "Firmware size is too small\n"); 971 - return -EINVAL; 972 - } 973 - 974 - return 0; 975 - } 976 - 977 - 978 - static void load_imem_segment(struct c8sectpfei *fei, Elf32_Phdr *phdr, 979 - const struct firmware *fw, u8 __iomem *dest, 980 - int seg_num) 981 - { 982 - const u8 *imem_src = fw->data + phdr->p_offset; 983 - int i; 984 - 985 - /* 986 - * For IMEM segments, the segment contains 24-bit 987 - * instructions which must be padded to 32-bit 988 - * instructions before being written. The written 989 - * segment is padded with NOP instructions. 990 - */ 991 - 992 - dev_dbg(fei->dev, 993 - "Loading IMEM segment %d 0x%08x\n\t (0x%x bytes) -> 0x%p (0x%x bytes)\n", 994 - seg_num, phdr->p_paddr, phdr->p_filesz, dest, 995 - phdr->p_memsz + phdr->p_memsz / 3); 996 - 997 - for (i = 0; i < phdr->p_filesz; i++) { 998 - 999 - writeb(readb((void __iomem *)imem_src), (void __iomem *)dest); 1000 - 1001 - /* Every 3 bytes, add an additional 1002 - * padding zero in destination */ 1003 - if (i % 3 == 2) { 1004 - dest++; 1005 - writeb(0x00, (void __iomem *)dest); 1006 - } 1007 - 1008 - dest++; 1009 - imem_src++; 1010 - } 1011 - } 1012 - 1013 - static void load_dmem_segment(struct c8sectpfei *fei, Elf32_Phdr *phdr, 1014 - const struct firmware *fw, u8 __iomem *dst, int seg_num) 1015 - { 1016 - /* 1017 - * For DMEM segments copy the segment data from the ELF 1018 - * file and pad segment with zeroes 1019 - */ 1020 - 1021 - dev_dbg(fei->dev, 1022 - "Loading DMEM segment %d 0x%08x\n\t(0x%x bytes) -> 0x%p (0x%x bytes)\n", 1023 - seg_num, phdr->p_paddr, phdr->p_filesz, 1024 - dst, phdr->p_memsz); 1025 - 1026 - memcpy((void __force *)dst, (void *)fw->data + phdr->p_offset, 1027 - phdr->p_filesz); 1028 - 1029 - memset((void __force *)dst + phdr->p_filesz, 0, 1030 - phdr->p_memsz - phdr->p_filesz); 1031 - } 1032 - 1033 - static int load_slim_core_fw(const struct firmware *fw, struct c8sectpfei *fei) 1034 - { 1035 - Elf32_Ehdr *ehdr; 1036 - Elf32_Phdr *phdr; 1037 - u8 __iomem *dst; 1038 - int err = 0, i; 1039 - 1040 - if (!fw || !fei) 1041 - return -EINVAL; 1042 - 1043 - ehdr = (Elf32_Ehdr *)fw->data; 1044 - phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff); 1045 - 1046 - /* go through the available ELF segments */ 1047 - for (i = 0; i < ehdr->e_phnum; i++, phdr++) { 1048 - 1049 - /* Only consider LOAD segments */ 1050 - if (phdr->p_type != PT_LOAD) 1051 - continue; 1052 - 1053 - /* 1054 - * Check segment is contained within the fw->data buffer 1055 - */ 1056 - if (phdr->p_offset + phdr->p_filesz > fw->size) { 1057 - dev_err(fei->dev, 1058 - "Segment %d is outside of firmware file\n", i); 1059 - err = -EINVAL; 1060 - break; 1061 - } 1062 - 1063 - /* 1064 - * MEMDMA IMEM has executable flag set, otherwise load 1065 - * this segment into DMEM. 1066 - * 1067 - */ 1068 - 1069 - if (phdr->p_flags & PF_X) { 1070 - dst = (u8 __iomem *) fei->io + DMA_MEMDMA_IMEM; 1071 - /* 1072 - * The Slim ELF file uses 32-bit word addressing for 1073 - * load offsets. 1074 - */ 1075 - dst += (phdr->p_paddr & 0xFFFFF) * sizeof(unsigned int); 1076 - load_imem_segment(fei, phdr, fw, dst, i); 1077 - } else { 1078 - dst = (u8 __iomem *) fei->io + DMA_MEMDMA_DMEM; 1079 - /* 1080 - * The Slim ELF file uses 32-bit word addressing for 1081 - * load offsets. 1082 - */ 1083 - dst += (phdr->p_paddr & 0xFFFFF) * sizeof(unsigned int); 1084 - load_dmem_segment(fei, phdr, fw, dst, i); 1085 - } 1086 - } 1087 - 1088 - return err; 1089 - } 1090 - 1091 - static int load_c8sectpfe_fw(struct c8sectpfei *fei) 1092 - { 1093 - const struct firmware *fw; 1094 - int err; 1095 - 1096 - dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA); 1097 - 1098 - err = request_firmware(&fw, FIRMWARE_MEMDMA, fei->dev); 1099 - if (err) 1100 - return err; 1101 - 1102 - err = c8sectpfe_elf_sanity_check(fei, fw); 1103 - if (err) { 1104 - dev_err(fei->dev, "c8sectpfe_elf_sanity_check failed err=(%d)\n" 1105 - , err); 1106 - release_firmware(fw); 1107 - return err; 1108 - } 1109 - 1110 - err = load_slim_core_fw(fw, fei); 1111 - release_firmware(fw); 1112 - if (err) { 1113 - dev_err(fei->dev, "load_slim_core_fw failed err=(%d)\n", err); 1114 - return err; 1115 - } 1116 - 1117 - /* now the firmware is loaded configure the input blocks */ 1118 - err = configure_channels(fei); 1119 - if (err) { 1120 - dev_err(fei->dev, "configure_channels failed err=(%d)\n", err); 1121 - return err; 1122 - } 1123 - 1124 - /* 1125 - * STBus target port can access IMEM and DMEM ports 1126 - * without waiting for CPU 1127 - */ 1128 - writel(0x1, fei->io + DMA_PER_STBUS_SYNC); 1129 - 1130 - dev_info(fei->dev, "Boot the memdma SLIM core\n"); 1131 - writel(0x1, fei->io + DMA_CPU_RUN); 1132 - 1133 - atomic_set(&fei->fw_loaded, 1); 1134 - 1135 - return 0; 1136 - } 1137 - 1138 - static const struct of_device_id c8sectpfe_match[] = { 1139 - { .compatible = "st,stih407-c8sectpfe" }, 1140 - { /* sentinel */ }, 1141 - }; 1142 - MODULE_DEVICE_TABLE(of, c8sectpfe_match); 1143 - 1144 - static struct platform_driver c8sectpfe_driver = { 1145 - .driver = { 1146 - .name = "c8sectpfe", 1147 - .of_match_table = c8sectpfe_match, 1148 - }, 1149 - .probe = c8sectpfe_probe, 1150 - .remove = c8sectpfe_remove, 1151 - }; 1152 - 1153 - module_platform_driver(c8sectpfe_driver); 1154 - 1155 - MODULE_AUTHOR("Peter Bennett <peter.bennett@st.com>"); 1156 - MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>"); 1157 - MODULE_DESCRIPTION("C8SECTPFE STi DVB Driver"); 1158 - MODULE_LICENSE("GPL");
-287
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * c8sectpfe-core.h - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author:Peter Bennett <peter.bennett@st.com> 8 - * Peter Griffin <peter.griffin@linaro.org> 9 - * 10 - */ 11 - #ifndef _C8SECTPFE_CORE_H_ 12 - #define _C8SECTPFE_CORE_H_ 13 - 14 - #define C8SECTPFEI_MAXCHANNEL 16 15 - #define C8SECTPFEI_MAXADAPTER 3 16 - 17 - #define C8SECTPFE_MAX_TSIN_CHAN 8 18 - 19 - struct gpio_desc; 20 - 21 - struct channel_info { 22 - 23 - int tsin_id; 24 - bool invert_ts_clk; 25 - bool serial_not_parallel; 26 - bool async_not_sync; 27 - int i2c; 28 - int dvb_card; 29 - 30 - struct gpio_desc *rst_gpio; 31 - 32 - struct i2c_adapter *i2c_adapter; 33 - struct i2c_adapter *tuner_i2c; 34 - struct i2c_adapter *lnb_i2c; 35 - struct i2c_client *i2c_client; 36 - struct dvb_frontend *frontend; 37 - 38 - struct pinctrl_state *pstate; 39 - 40 - int demux_mapping; 41 - int active; 42 - 43 - void *back_buffer_start; 44 - void *back_buffer_aligned; 45 - dma_addr_t back_buffer_busaddr; 46 - 47 - void *pid_buffer_start; 48 - void *pid_buffer_aligned; 49 - dma_addr_t pid_buffer_busaddr; 50 - 51 - unsigned long fifo; 52 - 53 - struct completion idle_completion; 54 - struct work_struct bh_work; 55 - 56 - struct c8sectpfei *fei; 57 - void __iomem *irec; 58 - 59 - }; 60 - 61 - struct c8sectpfe_hw { 62 - int num_ib; 63 - int num_mib; 64 - int num_swts; 65 - int num_tsout; 66 - int num_ccsc; 67 - int num_ram; 68 - int num_tp; 69 - }; 70 - 71 - struct c8sectpfei { 72 - 73 - struct device *dev; 74 - struct pinctrl *pinctrl; 75 - 76 - struct dentry *root; 77 - struct debugfs_regset32 *regset; 78 - struct completion fw_ack; 79 - atomic_t fw_loaded; 80 - 81 - int tsin_count; 82 - 83 - struct c8sectpfe_hw hw_stats; 84 - 85 - struct c8sectpfe *c8sectpfe[C8SECTPFEI_MAXADAPTER]; 86 - 87 - int mapping[C8SECTPFEI_MAXCHANNEL]; 88 - 89 - struct mutex lock; 90 - 91 - struct timer_list timer; /* timer interrupts for outputs */ 92 - 93 - void __iomem *io; 94 - void __iomem *sram; 95 - 96 - unsigned long sram_size; 97 - 98 - struct channel_info *channel_data[C8SECTPFE_MAX_TSIN_CHAN]; 99 - 100 - struct clk *c8sectpfeclk; 101 - int nima_rst_gpio; 102 - int nimb_rst_gpio; 103 - 104 - int idle_irq; 105 - int error_irq; 106 - 107 - int global_feed_count; 108 - }; 109 - 110 - /* C8SECTPFE SYS Regs list */ 111 - 112 - #define SYS_INPUT_ERR_STATUS 0x0 113 - #define SYS_OTHER_ERR_STATUS 0x8 114 - #define SYS_INPUT_ERR_MASK 0x10 115 - #define SYS_OTHER_ERR_MASK 0x18 116 - #define SYS_DMA_ROUTE 0x20 117 - #define SYS_INPUT_CLKEN 0x30 118 - #define IBENABLE_MASK 0x7F 119 - 120 - #define SYS_OTHER_CLKEN 0x38 121 - #define TSDMAENABLE BIT(1) 122 - #define MEMDMAENABLE BIT(0) 123 - 124 - #define SYS_CFG_NUM_IB 0x200 125 - #define SYS_CFG_NUM_MIB 0x204 126 - #define SYS_CFG_NUM_SWTS 0x208 127 - #define SYS_CFG_NUM_TSOUT 0x20C 128 - #define SYS_CFG_NUM_CCSC 0x210 129 - #define SYS_CFG_NUM_RAM 0x214 130 - #define SYS_CFG_NUM_TP 0x218 131 - 132 - /* Input Block Regs */ 133 - 134 - #define C8SECTPFE_INPUTBLK_OFFSET 0x1000 135 - #define C8SECTPFE_CHANNEL_OFFSET(x) ((x*0x40) + C8SECTPFE_INPUTBLK_OFFSET) 136 - 137 - #define C8SECTPFE_IB_IP_FMT_CFG(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x00) 138 - #define C8SECTPFE_IGNORE_ERR_AT_SOP BIT(7) 139 - #define C8SECTPFE_IGNORE_ERR_IN_PKT BIT(6) 140 - #define C8SECTPFE_IGNORE_ERR_IN_BYTE BIT(5) 141 - #define C8SECTPFE_INVERT_TSCLK BIT(4) 142 - #define C8SECTPFE_ALIGN_BYTE_SOP BIT(3) 143 - #define C8SECTPFE_ASYNC_NOT_SYNC BIT(2) 144 - #define C8SECTPFE_BYTE_ENDIANNESS_MSB BIT(1) 145 - #define C8SECTPFE_SERIAL_NOT_PARALLEL BIT(0) 146 - 147 - #define C8SECTPFE_IB_SYNCLCKDRP_CFG(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x04) 148 - #define C8SECTPFE_SYNC(x) (x & 0xf) 149 - #define C8SECTPFE_DROP(x) ((x<<4) & 0xf) 150 - #define C8SECTPFE_TOKEN(x) ((x<<8) & 0xff00) 151 - #define C8SECTPFE_SLDENDIANNESS BIT(16) 152 - 153 - #define C8SECTPFE_IB_TAGBYTES_CFG(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x08) 154 - #define C8SECTPFE_TAG_HEADER(x) (x << 16) 155 - #define C8SECTPFE_TAG_COUNTER(x) ((x<<1) & 0x7fff) 156 - #define C8SECTPFE_TAG_ENABLE BIT(0) 157 - 158 - #define C8SECTPFE_IB_PID_SET(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x0C) 159 - #define C8SECTPFE_PID_OFFSET(x) (x & 0x3f) 160 - #define C8SECTPFE_PID_NUMBITS(x) ((x << 6) & 0xfff) 161 - #define C8SECTPFE_PID_ENABLE BIT(31) 162 - 163 - #define C8SECTPFE_IB_PKT_LEN(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x10) 164 - 165 - #define C8SECTPFE_IB_BUFF_STRT(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x14) 166 - #define C8SECTPFE_IB_BUFF_END(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x18) 167 - #define C8SECTPFE_IB_READ_PNT(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x1C) 168 - #define C8SECTPFE_IB_WRT_PNT(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x20) 169 - 170 - #define C8SECTPFE_IB_PRI_THRLD(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x24) 171 - #define C8SECTPFE_PRI_VALUE(x) (x & 0x7fffff) 172 - #define C8SECTPFE_PRI_LOWPRI(x) ((x & 0xf) << 24) 173 - #define C8SECTPFE_PRI_HIGHPRI(x) ((x & 0xf) << 28) 174 - 175 - #define C8SECTPFE_IB_STAT(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x28) 176 - #define C8SECTPFE_STAT_FIFO_OVERFLOW(x) (x & 0x1) 177 - #define C8SECTPFE_STAT_BUFFER_OVERFLOW(x) (x & 0x2) 178 - #define C8SECTPFE_STAT_OUTOFORDERRP(x) (x & 0x4) 179 - #define C8SECTPFE_STAT_PID_OVERFLOW(x) (x & 0x8) 180 - #define C8SECTPFE_STAT_PKT_OVERFLOW(x) (x & 0x10) 181 - #define C8SECTPFE_STAT_ERROR_PACKETS(x) ((x >> 8) & 0xf) 182 - #define C8SECTPFE_STAT_SHORT_PACKETS(x) ((x >> 12) & 0xf) 183 - 184 - #define C8SECTPFE_IB_MASK(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x2C) 185 - #define C8SECTPFE_MASK_FIFO_OVERFLOW BIT(0) 186 - #define C8SECTPFE_MASK_BUFFER_OVERFLOW BIT(1) 187 - #define C8SECTPFE_MASK_OUTOFORDERRP(x) BIT(2) 188 - #define C8SECTPFE_MASK_PID_OVERFLOW(x) BIT(3) 189 - #define C8SECTPFE_MASK_PKT_OVERFLOW(x) BIT(4) 190 - #define C8SECTPFE_MASK_ERROR_PACKETS(x) ((x & 0xf) << 8) 191 - #define C8SECTPFE_MASK_SHORT_PACKETS(x) ((x & 0xf) >> 12) 192 - 193 - #define C8SECTPFE_IB_SYS(x) (C8SECTPFE_CHANNEL_OFFSET(x) + 0x30) 194 - #define C8SECTPFE_SYS_RESET BIT(1) 195 - #define C8SECTPFE_SYS_ENABLE BIT(0) 196 - 197 - /* 198 - * Pointer record data structure required for each input block 199 - * see Table 82 on page 167 of functional specification. 200 - */ 201 - 202 - #define DMA_PRDS_MEMBASE 0x0 /* Internal sram base address */ 203 - #define DMA_PRDS_MEMTOP 0x4 /* Internal sram top address */ 204 - 205 - /* 206 - * TS packet size, including tag bytes added by input block, 207 - * rounded up to the next multiple of 8 bytes. The packet size, 208 - * including any tagging bytes and rounded up to the nearest 209 - * multiple of 8 bytes must be less than 255 bytes. 210 - */ 211 - #define DMA_PRDS_PKTSIZE 0x8 212 - #define DMA_PRDS_TPENABLE 0xc 213 - 214 - #define TP0_OFFSET 0x10 215 - #define DMA_PRDS_BUSBASE_TP(x) ((0x10*x) + TP0_OFFSET) 216 - #define DMA_PRDS_BUSTOP_TP(x) ((0x10*x) + TP0_OFFSET + 0x4) 217 - #define DMA_PRDS_BUSWP_TP(x) ((0x10*x) + TP0_OFFSET + 0x8) 218 - #define DMA_PRDS_BUSRP_TP(x) ((0x10*x) + TP0_OFFSET + 0xc) 219 - 220 - #define DMA_PRDS_SIZE (0x20) 221 - 222 - #define DMA_MEMDMA_OFFSET 0x4000 223 - #define DMA_IMEM_OFFSET 0x0 224 - #define DMA_DMEM_OFFSET 0x4000 225 - #define DMA_CPU 0x8000 226 - #define DMA_PER_OFFSET 0xb000 227 - 228 - #define DMA_MEMDMA_DMEM (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET) 229 - #define DMA_MEMDMA_IMEM (DMA_MEMDMA_OFFSET + DMA_IMEM_OFFSET) 230 - 231 - /* XP70 Slim core regs */ 232 - #define DMA_CPU_ID (DMA_MEMDMA_OFFSET + DMA_CPU + 0x0) 233 - #define DMA_CPU_VCR (DMA_MEMDMA_OFFSET + DMA_CPU + 0x4) 234 - #define DMA_CPU_RUN (DMA_MEMDMA_OFFSET + DMA_CPU + 0x8) 235 - #define DMA_CPU_CLOCKGATE (DMA_MEMDMA_OFFSET + DMA_CPU + 0xc) 236 - #define DMA_CPU_PC (DMA_MEMDMA_OFFSET + DMA_CPU + 0x20) 237 - 238 - /* Enable Interrupt for a IB */ 239 - #define DMA_PER_TPn_DREQ_MASK (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd00) 240 - /* Ack interrupt by setting corresponding bit */ 241 - #define DMA_PER_TPn_DACK_SET (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd80) 242 - #define DMA_PER_TPn_DREQ (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe00) 243 - #define DMA_PER_TPn_DACK (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe80) 244 - #define DMA_PER_DREQ_MODE (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf80) 245 - #define DMA_PER_STBUS_SYNC (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf88) 246 - #define DMA_PER_STBUS_ACCESS (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf8c) 247 - #define DMA_PER_STBUS_ADDRESS (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf90) 248 - #define DMA_PER_IDLE_INT (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfa8) 249 - #define DMA_PER_PRIORITY (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfac) 250 - #define DMA_PER_MAX_OPCODE (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb0) 251 - #define DMA_PER_MAX_CHUNK (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb4) 252 - #define DMA_PER_PAGE_SIZE (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfbc) 253 - #define DMA_PER_MBOX_STATUS (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc0) 254 - #define DMA_PER_MBOX_SET (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc8) 255 - #define DMA_PER_MBOX_CLEAR (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd0) 256 - #define DMA_PER_MBOX_MASK (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd8) 257 - #define DMA_PER_INJECT_PKT_SRC (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe0) 258 - #define DMA_PER_INJECT_PKT_DEST (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe4) 259 - #define DMA_PER_INJECT_PKT_ADDR (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe8) 260 - #define DMA_PER_INJECT_PKT (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfec) 261 - #define DMA_PER_PAT_PTR_INIT (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff0) 262 - #define DMA_PER_PAT_PTR (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff4) 263 - #define DMA_PER_SLEEP_MASK (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff8) 264 - #define DMA_PER_SLEEP_COUNTER (DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xffc) 265 - /* #define DMA_RF_CPUREGn DMA_RFBASEADDR n=0 to 15) slim regsa */ 266 - 267 - /* The following are from DMA_DMEM_BaseAddress */ 268 - #define DMA_FIRMWARE_VERSION (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x0) 269 - #define DMA_PTRREC_BASE (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x4) 270 - #define DMA_PTRREC_INPUT_OFFSET (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x8) 271 - #define DMA_ERRREC_BASE (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0xc) 272 - #define DMA_ERROR_RECORD(n) ((n*4) + DMA_ERRREC_BASE + 0x4) 273 - #define DMA_IDLE_REQ (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x10) 274 - #define IDLEREQ BIT(31) 275 - 276 - #define DMA_FIRMWARE_CONFIG (DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x14) 277 - 278 - /* Regs for PID Filter */ 279 - 280 - #define PIDF_OFFSET 0x2800 281 - #define PIDF_BASE(n) ((n*4) + PIDF_OFFSET) 282 - #define PIDF_LEAK_ENABLE (PIDF_OFFSET + 0x100) 283 - #define PIDF_LEAK_STATUS (PIDF_OFFSET + 0x108) 284 - #define PIDF_LEAK_COUNT_RESET (PIDF_OFFSET + 0x110) 285 - #define PIDF_LEAK_COUNTER (PIDF_OFFSET + 0x114) 286 - 287 - #endif /* _C8SECTPFE_CORE_H_ */
-244
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-debugfs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * c8sectpfe-debugfs.c - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author: Peter Griffin <peter.griffin@linaro.org> 8 - * 9 - */ 10 - #include <linux/debugfs.h> 11 - #include <linux/device.h> 12 - #include <linux/interrupt.h> 13 - #include <linux/io.h> 14 - #include <linux/kernel.h> 15 - #include <linux/seq_file.h> 16 - #include <linux/slab.h> 17 - #include <linux/types.h> 18 - 19 - #include "c8sectpfe-debugfs.h" 20 - 21 - #define dump_register(nm ...) \ 22 - { \ 23 - .name = #nm, \ 24 - .offset = nm, \ 25 - } 26 - 27 - static const struct debugfs_reg32 fei_sys_regs[] = { 28 - dump_register(SYS_INPUT_ERR_STATUS), 29 - dump_register(SYS_OTHER_ERR_STATUS), 30 - dump_register(SYS_INPUT_ERR_MASK), 31 - dump_register(SYS_DMA_ROUTE), 32 - dump_register(SYS_INPUT_CLKEN), 33 - dump_register(IBENABLE_MASK), 34 - dump_register(SYS_OTHER_CLKEN), 35 - dump_register(SYS_CFG_NUM_IB), 36 - dump_register(SYS_CFG_NUM_MIB), 37 - dump_register(SYS_CFG_NUM_SWTS), 38 - dump_register(SYS_CFG_NUM_TSOUT), 39 - dump_register(SYS_CFG_NUM_CCSC), 40 - dump_register(SYS_CFG_NUM_RAM), 41 - dump_register(SYS_CFG_NUM_TP), 42 - 43 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(0)), 44 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(0)), 45 - dump_register(C8SECTPFE_IB_PID_SET(0)), 46 - dump_register(C8SECTPFE_IB_PKT_LEN(0)), 47 - dump_register(C8SECTPFE_IB_BUFF_STRT(0)), 48 - dump_register(C8SECTPFE_IB_BUFF_END(0)), 49 - dump_register(C8SECTPFE_IB_READ_PNT(0)), 50 - dump_register(C8SECTPFE_IB_WRT_PNT(0)), 51 - dump_register(C8SECTPFE_IB_PRI_THRLD(0)), 52 - dump_register(C8SECTPFE_IB_STAT(0)), 53 - dump_register(C8SECTPFE_IB_MASK(0)), 54 - dump_register(C8SECTPFE_IB_SYS(0)), 55 - 56 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(1)), 57 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(1)), 58 - dump_register(C8SECTPFE_IB_PID_SET(1)), 59 - dump_register(C8SECTPFE_IB_PKT_LEN(1)), 60 - dump_register(C8SECTPFE_IB_BUFF_STRT(1)), 61 - dump_register(C8SECTPFE_IB_BUFF_END(1)), 62 - dump_register(C8SECTPFE_IB_READ_PNT(1)), 63 - dump_register(C8SECTPFE_IB_WRT_PNT(1)), 64 - dump_register(C8SECTPFE_IB_PRI_THRLD(1)), 65 - dump_register(C8SECTPFE_IB_STAT(1)), 66 - dump_register(C8SECTPFE_IB_MASK(1)), 67 - dump_register(C8SECTPFE_IB_SYS(1)), 68 - 69 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(2)), 70 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(2)), 71 - dump_register(C8SECTPFE_IB_PID_SET(2)), 72 - dump_register(C8SECTPFE_IB_PKT_LEN(2)), 73 - dump_register(C8SECTPFE_IB_BUFF_STRT(2)), 74 - dump_register(C8SECTPFE_IB_BUFF_END(2)), 75 - dump_register(C8SECTPFE_IB_READ_PNT(2)), 76 - dump_register(C8SECTPFE_IB_WRT_PNT(2)), 77 - dump_register(C8SECTPFE_IB_PRI_THRLD(2)), 78 - dump_register(C8SECTPFE_IB_STAT(2)), 79 - dump_register(C8SECTPFE_IB_MASK(2)), 80 - dump_register(C8SECTPFE_IB_SYS(2)), 81 - 82 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(3)), 83 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(3)), 84 - dump_register(C8SECTPFE_IB_PID_SET(3)), 85 - dump_register(C8SECTPFE_IB_PKT_LEN(3)), 86 - dump_register(C8SECTPFE_IB_BUFF_STRT(3)), 87 - dump_register(C8SECTPFE_IB_BUFF_END(3)), 88 - dump_register(C8SECTPFE_IB_READ_PNT(3)), 89 - dump_register(C8SECTPFE_IB_WRT_PNT(3)), 90 - dump_register(C8SECTPFE_IB_PRI_THRLD(3)), 91 - dump_register(C8SECTPFE_IB_STAT(3)), 92 - dump_register(C8SECTPFE_IB_MASK(3)), 93 - dump_register(C8SECTPFE_IB_SYS(3)), 94 - 95 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(4)), 96 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(4)), 97 - dump_register(C8SECTPFE_IB_PID_SET(4)), 98 - dump_register(C8SECTPFE_IB_PKT_LEN(4)), 99 - dump_register(C8SECTPFE_IB_BUFF_STRT(4)), 100 - dump_register(C8SECTPFE_IB_BUFF_END(4)), 101 - dump_register(C8SECTPFE_IB_READ_PNT(4)), 102 - dump_register(C8SECTPFE_IB_WRT_PNT(4)), 103 - dump_register(C8SECTPFE_IB_PRI_THRLD(4)), 104 - dump_register(C8SECTPFE_IB_STAT(4)), 105 - dump_register(C8SECTPFE_IB_MASK(4)), 106 - dump_register(C8SECTPFE_IB_SYS(4)), 107 - 108 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(5)), 109 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(5)), 110 - dump_register(C8SECTPFE_IB_PID_SET(5)), 111 - dump_register(C8SECTPFE_IB_PKT_LEN(5)), 112 - dump_register(C8SECTPFE_IB_BUFF_STRT(5)), 113 - dump_register(C8SECTPFE_IB_BUFF_END(5)), 114 - dump_register(C8SECTPFE_IB_READ_PNT(5)), 115 - dump_register(C8SECTPFE_IB_WRT_PNT(5)), 116 - dump_register(C8SECTPFE_IB_PRI_THRLD(5)), 117 - dump_register(C8SECTPFE_IB_STAT(5)), 118 - dump_register(C8SECTPFE_IB_MASK(5)), 119 - dump_register(C8SECTPFE_IB_SYS(5)), 120 - 121 - dump_register(C8SECTPFE_IB_IP_FMT_CFG(6)), 122 - dump_register(C8SECTPFE_IB_TAGBYTES_CFG(6)), 123 - dump_register(C8SECTPFE_IB_PID_SET(6)), 124 - dump_register(C8SECTPFE_IB_PKT_LEN(6)), 125 - dump_register(C8SECTPFE_IB_BUFF_STRT(6)), 126 - dump_register(C8SECTPFE_IB_BUFF_END(6)), 127 - dump_register(C8SECTPFE_IB_READ_PNT(6)), 128 - dump_register(C8SECTPFE_IB_WRT_PNT(6)), 129 - dump_register(C8SECTPFE_IB_PRI_THRLD(6)), 130 - dump_register(C8SECTPFE_IB_STAT(6)), 131 - dump_register(C8SECTPFE_IB_MASK(6)), 132 - dump_register(C8SECTPFE_IB_SYS(6)), 133 - 134 - dump_register(DMA_CPU_ID), 135 - dump_register(DMA_CPU_VCR), 136 - dump_register(DMA_CPU_RUN), 137 - dump_register(DMA_CPU_PC), 138 - 139 - dump_register(DMA_PER_TPn_DREQ_MASK), 140 - dump_register(DMA_PER_TPn_DACK_SET), 141 - dump_register(DMA_PER_TPn_DREQ), 142 - dump_register(DMA_PER_TPn_DACK), 143 - dump_register(DMA_PER_DREQ_MODE), 144 - dump_register(DMA_PER_STBUS_SYNC), 145 - dump_register(DMA_PER_STBUS_ACCESS), 146 - dump_register(DMA_PER_STBUS_ADDRESS), 147 - dump_register(DMA_PER_IDLE_INT), 148 - dump_register(DMA_PER_PRIORITY), 149 - dump_register(DMA_PER_MAX_OPCODE), 150 - dump_register(DMA_PER_MAX_CHUNK), 151 - dump_register(DMA_PER_PAGE_SIZE), 152 - dump_register(DMA_PER_MBOX_STATUS), 153 - dump_register(DMA_PER_MBOX_SET), 154 - dump_register(DMA_PER_MBOX_CLEAR), 155 - dump_register(DMA_PER_MBOX_MASK), 156 - dump_register(DMA_PER_INJECT_PKT_SRC), 157 - dump_register(DMA_PER_INJECT_PKT_DEST), 158 - dump_register(DMA_PER_INJECT_PKT_ADDR), 159 - dump_register(DMA_PER_INJECT_PKT), 160 - dump_register(DMA_PER_PAT_PTR_INIT), 161 - dump_register(DMA_PER_PAT_PTR), 162 - dump_register(DMA_PER_SLEEP_MASK), 163 - dump_register(DMA_PER_SLEEP_COUNTER), 164 - 165 - dump_register(DMA_FIRMWARE_VERSION), 166 - dump_register(DMA_PTRREC_BASE), 167 - dump_register(DMA_PTRREC_INPUT_OFFSET), 168 - dump_register(DMA_ERRREC_BASE), 169 - 170 - dump_register(DMA_ERROR_RECORD(0)), 171 - dump_register(DMA_ERROR_RECORD(1)), 172 - dump_register(DMA_ERROR_RECORD(2)), 173 - dump_register(DMA_ERROR_RECORD(3)), 174 - dump_register(DMA_ERROR_RECORD(4)), 175 - dump_register(DMA_ERROR_RECORD(5)), 176 - dump_register(DMA_ERROR_RECORD(6)), 177 - dump_register(DMA_ERROR_RECORD(7)), 178 - dump_register(DMA_ERROR_RECORD(8)), 179 - dump_register(DMA_ERROR_RECORD(9)), 180 - dump_register(DMA_ERROR_RECORD(10)), 181 - dump_register(DMA_ERROR_RECORD(11)), 182 - dump_register(DMA_ERROR_RECORD(12)), 183 - dump_register(DMA_ERROR_RECORD(13)), 184 - dump_register(DMA_ERROR_RECORD(14)), 185 - dump_register(DMA_ERROR_RECORD(15)), 186 - dump_register(DMA_ERROR_RECORD(16)), 187 - dump_register(DMA_ERROR_RECORD(17)), 188 - dump_register(DMA_ERROR_RECORD(18)), 189 - dump_register(DMA_ERROR_RECORD(19)), 190 - dump_register(DMA_ERROR_RECORD(20)), 191 - dump_register(DMA_ERROR_RECORD(21)), 192 - dump_register(DMA_ERROR_RECORD(22)), 193 - 194 - dump_register(DMA_IDLE_REQ), 195 - dump_register(DMA_FIRMWARE_CONFIG), 196 - 197 - dump_register(PIDF_BASE(0)), 198 - dump_register(PIDF_BASE(1)), 199 - dump_register(PIDF_BASE(2)), 200 - dump_register(PIDF_BASE(3)), 201 - dump_register(PIDF_BASE(4)), 202 - dump_register(PIDF_BASE(5)), 203 - dump_register(PIDF_BASE(6)), 204 - dump_register(PIDF_BASE(7)), 205 - dump_register(PIDF_BASE(8)), 206 - dump_register(PIDF_BASE(9)), 207 - dump_register(PIDF_BASE(10)), 208 - dump_register(PIDF_BASE(11)), 209 - dump_register(PIDF_BASE(12)), 210 - dump_register(PIDF_BASE(13)), 211 - dump_register(PIDF_BASE(14)), 212 - dump_register(PIDF_BASE(15)), 213 - dump_register(PIDF_BASE(16)), 214 - dump_register(PIDF_BASE(17)), 215 - dump_register(PIDF_BASE(18)), 216 - dump_register(PIDF_BASE(19)), 217 - dump_register(PIDF_BASE(20)), 218 - dump_register(PIDF_BASE(21)), 219 - dump_register(PIDF_BASE(22)), 220 - dump_register(PIDF_LEAK_ENABLE), 221 - dump_register(PIDF_LEAK_STATUS), 222 - dump_register(PIDF_LEAK_COUNT_RESET), 223 - dump_register(PIDF_LEAK_COUNTER), 224 - }; 225 - 226 - void c8sectpfe_debugfs_init(struct c8sectpfei *fei) 227 - { 228 - fei->regset = devm_kzalloc(fei->dev, sizeof(*fei->regset), GFP_KERNEL); 229 - if (!fei->regset) 230 - return; 231 - 232 - fei->regset->regs = fei_sys_regs; 233 - fei->regset->nregs = ARRAY_SIZE(fei_sys_regs); 234 - fei->regset->base = fei->io; 235 - 236 - fei->root = debugfs_create_dir("c8sectpfe", NULL); 237 - debugfs_create_regset32("registers", S_IRUGO, fei->root, fei->regset); 238 - } 239 - 240 - void c8sectpfe_debugfs_exit(struct c8sectpfei *fei) 241 - { 242 - debugfs_remove_recursive(fei->root); 243 - fei->root = NULL; 244 - }
-23
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-debugfs.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * c8sectpfe-debugfs.h - C8SECTPFE STi DVB driver debugfs header 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Authors: Peter Griffin <peter.griffin@linaro.org> 8 - */ 9 - 10 - #ifndef __C8SECTPFE_DEBUG_H 11 - #define __C8SECTPFE_DEBUG_H 12 - 13 - #include "c8sectpfe-core.h" 14 - 15 - #if defined(CONFIG_DEBUG_FS) 16 - void c8sectpfe_debugfs_init(struct c8sectpfei *); 17 - void c8sectpfe_debugfs_exit(struct c8sectpfei *); 18 - #else 19 - static inline void c8sectpfe_debugfs_init(struct c8sectpfei *fei) {}; 20 - static inline void c8sectpfe_debugfs_exit(struct c8sectpfei *fei) {}; 21 - #endif 22 - 23 - #endif /* __C8SECTPFE_DEBUG_H */
-235
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-dvb.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * c8sectpfe-dvb.c - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author Peter Griffin <peter.griffin@linaro.org> 8 - * 9 - */ 10 - #include <linux/completion.h> 11 - #include <linux/delay.h> 12 - #include <linux/i2c.h> 13 - #include <linux/interrupt.h> 14 - 15 - #include <dt-bindings/media/c8sectpfe.h> 16 - 17 - #include "c8sectpfe-common.h" 18 - #include "c8sectpfe-core.h" 19 - #include "c8sectpfe-dvb.h" 20 - 21 - #include "dvb-pll.h" 22 - #include "lnbh24.h" 23 - #include "stv0367.h" 24 - #include "stv0367_priv.h" 25 - #include "stv6110x.h" 26 - #include "stv090x.h" 27 - #include "tda18212.h" 28 - 29 - static inline const char *dvb_card_str(unsigned int c) 30 - { 31 - switch (c) { 32 - case STV0367_TDA18212_NIMA_1: return "STV0367_TDA18212_NIMA_1"; 33 - case STV0367_TDA18212_NIMA_2: return "STV0367_TDA18212_NIMA_2"; 34 - case STV0367_TDA18212_NIMB_1: return "STV0367_TDA18212_NIMB_1"; 35 - case STV0367_TDA18212_NIMB_2: return "STV0367_TDA18212_NIMB_2"; 36 - case STV0903_6110_LNB24_NIMA: return "STV0903_6110_LNB24_NIMA"; 37 - case STV0903_6110_LNB24_NIMB: return "STV0903_6110_LNB24_NIMB"; 38 - default: return "unknown dvb frontend card"; 39 - } 40 - } 41 - 42 - static struct stv090x_config stv090x_config = { 43 - .device = STV0903, 44 - .demod_mode = STV090x_SINGLE, 45 - .clk_mode = STV090x_CLK_EXT, 46 - .xtal = 16000000, 47 - .address = 0x69, 48 - 49 - .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, 50 - .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, 51 - 52 - .repeater_level = STV090x_RPTLEVEL_64, 53 - 54 - .tuner_init = NULL, 55 - .tuner_set_mode = NULL, 56 - .tuner_set_frequency = NULL, 57 - .tuner_get_frequency = NULL, 58 - .tuner_set_bandwidth = NULL, 59 - .tuner_get_bandwidth = NULL, 60 - .tuner_set_bbgain = NULL, 61 - .tuner_get_bbgain = NULL, 62 - .tuner_set_refclk = NULL, 63 - .tuner_get_status = NULL, 64 - }; 65 - 66 - static struct stv6110x_config stv6110x_config = { 67 - .addr = 0x60, 68 - .refclk = 16000000, 69 - }; 70 - 71 - #define NIMA 0 72 - #define NIMB 1 73 - 74 - static struct stv0367_config stv0367_tda18212_config[] = { 75 - { 76 - .demod_address = 0x1c, 77 - .xtal = 16000000, 78 - .if_khz = 4500, 79 - .if_iq_mode = FE_TER_NORMAL_IF_TUNER, 80 - .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, 81 - .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT, 82 - }, { 83 - .demod_address = 0x1d, 84 - .xtal = 16000000, 85 - .if_khz = 4500, 86 - .if_iq_mode = FE_TER_NORMAL_IF_TUNER, 87 - .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, 88 - .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT, 89 - }, { 90 - .demod_address = 0x1e, 91 - .xtal = 16000000, 92 - .if_khz = 4500, 93 - .if_iq_mode = FE_TER_NORMAL_IF_TUNER, 94 - .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, 95 - .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT, 96 - }, 97 - }; 98 - 99 - static struct tda18212_config tda18212_conf = { 100 - .if_dvbt_6 = 4150, 101 - .if_dvbt_7 = 4150, 102 - .if_dvbt_8 = 4500, 103 - .if_dvbc = 5000, 104 - }; 105 - 106 - int c8sectpfe_frontend_attach(struct dvb_frontend **fe, 107 - struct c8sectpfe *c8sectpfe, 108 - struct channel_info *tsin, int chan_num) 109 - { 110 - struct tda18212_config *tda18212; 111 - const struct stv6110x_devctl *fe2; 112 - struct i2c_client *client; 113 - struct i2c_board_info tda18212_info = { 114 - .type = "tda18212", 115 - .addr = 0x60, 116 - }; 117 - 118 - if (!tsin) 119 - return -EINVAL; 120 - 121 - switch (tsin->dvb_card) { 122 - 123 - case STV0367_TDA18212_NIMA_1: 124 - case STV0367_TDA18212_NIMA_2: 125 - case STV0367_TDA18212_NIMB_1: 126 - case STV0367_TDA18212_NIMB_2: 127 - if (tsin->dvb_card == STV0367_TDA18212_NIMA_1) 128 - *fe = dvb_attach(stv0367ter_attach, 129 - &stv0367_tda18212_config[0], 130 - tsin->i2c_adapter); 131 - else if (tsin->dvb_card == STV0367_TDA18212_NIMB_1) 132 - *fe = dvb_attach(stv0367ter_attach, 133 - &stv0367_tda18212_config[1], 134 - tsin->i2c_adapter); 135 - else 136 - *fe = dvb_attach(stv0367ter_attach, 137 - &stv0367_tda18212_config[2], 138 - tsin->i2c_adapter); 139 - 140 - if (!*fe) { 141 - dev_err(c8sectpfe->device, 142 - "%s: stv0367ter_attach failed for NIM card %s\n" 143 - , __func__, dvb_card_str(tsin->dvb_card)); 144 - return -ENODEV; 145 - } 146 - 147 - /* 148 - * init the demod so that i2c gate_ctrl 149 - * to the tuner works correctly 150 - */ 151 - (*fe)->ops.init(*fe); 152 - 153 - /* Allocate the tda18212 structure */ 154 - tda18212 = devm_kzalloc(c8sectpfe->device, 155 - sizeof(struct tda18212_config), 156 - GFP_KERNEL); 157 - if (!tda18212) { 158 - dev_err(c8sectpfe->device, 159 - "%s: devm_kzalloc failed\n", __func__); 160 - return -ENOMEM; 161 - } 162 - 163 - memcpy(tda18212, &tda18212_conf, 164 - sizeof(struct tda18212_config)); 165 - 166 - tda18212->fe = (*fe); 167 - 168 - tda18212_info.platform_data = tda18212; 169 - 170 - /* attach tuner */ 171 - request_module("tda18212"); 172 - client = i2c_new_client_device(tsin->i2c_adapter, 173 - &tda18212_info); 174 - if (!i2c_client_has_driver(client)) { 175 - dvb_frontend_detach(*fe); 176 - return -ENODEV; 177 - } 178 - 179 - if (!try_module_get(client->dev.driver->owner)) { 180 - i2c_unregister_device(client); 181 - dvb_frontend_detach(*fe); 182 - return -ENODEV; 183 - } 184 - 185 - tsin->i2c_client = client; 186 - 187 - break; 188 - 189 - case STV0903_6110_LNB24_NIMA: 190 - *fe = dvb_attach(stv090x_attach, &stv090x_config, 191 - tsin->i2c_adapter, STV090x_DEMODULATOR_0); 192 - if (!*fe) { 193 - dev_err(c8sectpfe->device, "%s: stv090x_attach failed\n" 194 - "\tfor NIM card %s\n", 195 - __func__, dvb_card_str(tsin->dvb_card)); 196 - return -ENODEV; 197 - } 198 - 199 - fe2 = dvb_attach(stv6110x_attach, *fe, 200 - &stv6110x_config, tsin->i2c_adapter); 201 - if (!fe2) { 202 - dev_err(c8sectpfe->device, 203 - "%s: stv6110x_attach failed for NIM card %s\n" 204 - , __func__, dvb_card_str(tsin->dvb_card)); 205 - return -ENODEV; 206 - } 207 - 208 - stv090x_config.tuner_init = fe2->tuner_init; 209 - stv090x_config.tuner_set_mode = fe2->tuner_set_mode; 210 - stv090x_config.tuner_set_frequency = fe2->tuner_set_frequency; 211 - stv090x_config.tuner_get_frequency = fe2->tuner_get_frequency; 212 - stv090x_config.tuner_set_bandwidth = fe2->tuner_set_bandwidth; 213 - stv090x_config.tuner_get_bandwidth = fe2->tuner_get_bandwidth; 214 - stv090x_config.tuner_set_bbgain = fe2->tuner_set_bbgain; 215 - stv090x_config.tuner_get_bbgain = fe2->tuner_get_bbgain; 216 - stv090x_config.tuner_set_refclk = fe2->tuner_set_refclk; 217 - stv090x_config.tuner_get_status = fe2->tuner_get_status; 218 - 219 - dvb_attach(lnbh24_attach, *fe, tsin->i2c_adapter, 0, 0, 0x9); 220 - break; 221 - 222 - default: 223 - dev_err(c8sectpfe->device, 224 - "%s: DVB frontend card %s not yet supported\n", 225 - __func__, dvb_card_str(tsin->dvb_card)); 226 - return -ENODEV; 227 - } 228 - 229 - (*fe)->id = chan_num; 230 - 231 - dev_info(c8sectpfe->device, 232 - "DVB frontend card %s successfully attached", 233 - dvb_card_str(tsin->dvb_card)); 234 - return 0; 235 - }
-17
drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-dvb.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * c8sectpfe-common.h - C8SECTPFE STi DVB driver 4 - * 5 - * Copyright (c) STMicroelectronics 2015 6 - * 7 - * Author: Peter Griffin <peter.griffin@linaro.org> 8 - * 9 - */ 10 - #ifndef _C8SECTPFE_DVB_H_ 11 - #define _C8SECTPFE_DVB_H_ 12 - 13 - int c8sectpfe_frontend_attach(struct dvb_frontend **fe, 14 - struct c8sectpfe *c8sectpfe, struct channel_info *tsin, 15 - int chan_num); 16 - 17 - #endif