1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * FireDTV driver (formerly known as FireSAT) 4 * 5 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> 6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> 7 */ 8 9 #include <linux/bitops.h> 10 #include <linux/device.h> 11 #include <linux/errno.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/mutex.h> 15 #include <linux/types.h> 16 17 #include <media/dmxdev.h> 18 #include <media/dvb_demux.h> 19 #include <media/dvbdev.h> 20 #include <media/dvb_frontend.h> 21 22 #include "firedtv.h" 23 24 static int alloc_channel(struct firedtv *fdtv) 25 { 26 int i; 27 28 for (i = 0; i < 16; i++) 29 if (!__test_and_set_bit(i, &fdtv->channel_active)) 30 break; 31 return i; 32 } 33 34 static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[]) 35 { 36 int i, n; 37 38 for (i = 0, n = 0; i < 16; i++) 39 if (test_bit(i, &fdtv->channel_active)) 40 pid[n++] = fdtv->channel_pid[i]; 41 *pidc = n; 42 } 43 44 static inline void dealloc_channel(struct firedtv *fdtv, int i) 45 { 46 __clear_bit(i, &fdtv->channel_active); 47 } 48 49 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed) 50 { 51 struct firedtv *fdtv = dvbdmxfeed->demux->priv; 52 int pidc, c, ret; 53 u16 pids[16]; 54 55 switch (dvbdmxfeed->type) { 56 case DMX_TYPE_TS: 57 case DMX_TYPE_SEC: 58 break; 59 default: 60 dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n", 61 dvbdmxfeed->type); 62 return -EINVAL; 63 } 64 65 if (mutex_lock_interruptible(&fdtv->demux_mutex)) 66 return -EINTR; 67 68 if (dvbdmxfeed->type == DMX_TYPE_TS) { 69 switch (dvbdmxfeed->pes_type) { 70 case DMX_PES_VIDEO: 71 case DMX_PES_AUDIO: 72 case DMX_PES_TELETEXT: 73 case DMX_PES_PCR: 74 case DMX_PES_OTHER: 75 c = alloc_channel(fdtv); 76 break; 77 default: 78 dev_err(fdtv->device, 79 "can't start dmx feed: invalid pes type %u\n", 80 dvbdmxfeed->pes_type); 81 ret = -EINVAL; 82 goto out; 83 } 84 } else { 85 c = alloc_channel(fdtv); 86 } 87 88 if (c > 15) { 89 dev_err(fdtv->device, "can't start dmx feed: busy\n"); 90 ret = -EBUSY; 91 goto out; 92 } 93 94 dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c; 95 fdtv->channel_pid[c] = dvbdmxfeed->pid; 96 collect_channels(fdtv, &pidc, pids); 97 98 if (dvbdmxfeed->pid == 8192) { 99 ret = avc_tuner_get_ts(fdtv); 100 if (ret) { 101 dealloc_channel(fdtv, c); 102 dev_err(fdtv->device, "can't get TS\n"); 103 goto out; 104 } 105 } else { 106 ret = avc_tuner_set_pids(fdtv, pidc, pids); 107 if (ret) { 108 dealloc_channel(fdtv, c); 109 dev_err(fdtv->device, "can't set PIDs\n"); 110 goto out; 111 } 112 } 113 out: 114 mutex_unlock(&fdtv->demux_mutex); 115 116 return ret; 117 } 118 119 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 120 { 121 struct dvb_demux *demux = dvbdmxfeed->demux; 122 struct firedtv *fdtv = demux->priv; 123 int pidc, c, ret; 124 u16 pids[16]; 125 126 if (dvbdmxfeed->type == DMX_TYPE_TS && 127 !((dvbdmxfeed->ts_type & TS_PACKET) && 128 (demux->dmx.frontend->source != DMX_MEMORY_FE))) { 129 130 if (dvbdmxfeed->ts_type & TS_DECODER) { 131 if (dvbdmxfeed->pes_type >= DMX_PES_OTHER || 132 !demux->pesfilter[dvbdmxfeed->pes_type]) 133 return -EINVAL; 134 135 demux->pids[dvbdmxfeed->pes_type] |= 0x8000; 136 demux->pesfilter[dvbdmxfeed->pes_type] = NULL; 137 } 138 139 if (!(dvbdmxfeed->ts_type & TS_DECODER && 140 dvbdmxfeed->pes_type < DMX_PES_OTHER)) 141 return 0; 142 } 143 144 if (mutex_lock_interruptible(&fdtv->demux_mutex)) 145 return -EINTR; 146 147 c = (unsigned long)dvbdmxfeed->priv; 148 dealloc_channel(fdtv, c); 149 collect_channels(fdtv, &pidc, pids); 150 151 ret = avc_tuner_set_pids(fdtv, pidc, pids); 152 153 mutex_unlock(&fdtv->demux_mutex); 154 155 return ret; 156 } 157 158 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 159 160 int fdtv_dvb_register(struct firedtv *fdtv, const char *name) 161 { 162 int err; 163 164 err = dvb_register_adapter(&fdtv->adapter, name, 165 THIS_MODULE, fdtv->device, adapter_nr); 166 if (err < 0) 167 goto fail_log; 168 169 /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/ 170 fdtv->demux.dmx.capabilities = 0; 171 172 fdtv->demux.priv = fdtv; 173 fdtv->demux.filternum = 16; 174 fdtv->demux.feednum = 16; 175 fdtv->demux.start_feed = fdtv_start_feed; 176 fdtv->demux.stop_feed = fdtv_stop_feed; 177 fdtv->demux.write_to_decoder = NULL; 178 179 err = dvb_dmx_init(&fdtv->demux); 180 if (err) 181 goto fail_unreg_adapter; 182 183 fdtv->dmxdev.filternum = 16; 184 fdtv->dmxdev.demux = &fdtv->demux.dmx; 185 fdtv->dmxdev.capabilities = 0; 186 187 err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter); 188 if (err) 189 goto fail_dmx_release; 190 191 fdtv->frontend.source = DMX_FRONTEND_0; 192 193 err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend); 194 if (err) 195 goto fail_dmxdev_release; 196 197 err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx, 198 &fdtv->frontend); 199 if (err) 200 goto fail_rem_frontend; 201 202 err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx); 203 if (err) 204 goto fail_disconnect_frontend; 205 206 fdtv_frontend_init(fdtv, name); 207 err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe); 208 if (err) 209 goto fail_net_release; 210 211 err = fdtv_ca_register(fdtv); 212 if (err) 213 dev_info(fdtv->device, 214 "Conditional Access Module not enabled\n"); 215 return 0; 216 217 fail_net_release: 218 dvb_net_release(&fdtv->dvbnet); 219 fail_disconnect_frontend: 220 fdtv->demux.dmx.close(&fdtv->demux.dmx); 221 fail_rem_frontend: 222 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend); 223 fail_dmxdev_release: 224 dvb_dmxdev_release(&fdtv->dmxdev); 225 fail_dmx_release: 226 dvb_dmx_release(&fdtv->demux); 227 fail_unreg_adapter: 228 dvb_unregister_adapter(&fdtv->adapter); 229 fail_log: 230 dev_err(fdtv->device, "DVB initialization failed\n"); 231 return err; 232 } 233 234 void fdtv_dvb_unregister(struct firedtv *fdtv) 235 { 236 fdtv_ca_release(fdtv); 237 dvb_unregister_frontend(&fdtv->fe); 238 dvb_net_release(&fdtv->dvbnet); 239 fdtv->demux.dmx.close(&fdtv->demux.dmx); 240 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend); 241 dvb_dmxdev_release(&fdtv->dmxdev); 242 dvb_dmx_release(&fdtv->demux); 243 dvb_unregister_adapter(&fdtv->adapter); 244 } 245