root/drivers/media/common/videobuf2/videobuf2-dvb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dvb_fnc
  2. vb2_dvb_start_feed
  3. vb2_dvb_stop_feed
  4. vb2_dvb_register_adapter
  5. vb2_dvb_register_frontend
  6. vb2_dvb_register_bus
  7. vb2_dvb_unregister_bus
  8. vb2_dvb_get_frontend
  9. vb2_dvb_find_frontend
  10. vb2_dvb_alloc_frontend
  11. vb2_dvb_dealloc_frontends

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *
   4  * some helper function for simple DVB cards which simply DMA the
   5  * complete transport stream and let the computer sort everything else
   6  * (i.e. we are using the software demux, ...).  Also uses the
   7  * video-buf to manage DMA buffers.
   8  *
   9  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/init.h>
  14 #include <linux/device.h>
  15 #include <linux/slab.h>
  16 
  17 #include <media/videobuf2-dvb.h>
  18 
  19 /* ------------------------------------------------------------------ */
  20 
  21 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  22 MODULE_LICENSE("GPL");
  23 
  24 /* ------------------------------------------------------------------ */
  25 
  26 static int dvb_fnc(struct vb2_buffer *vb, void *priv)
  27 {
  28         struct vb2_dvb *dvb = priv;
  29 
  30         dvb_dmx_swfilter(&dvb->demux, vb2_plane_vaddr(vb, 0),
  31                                       vb2_get_plane_payload(vb, 0));
  32         return 0;
  33 }
  34 
  35 static int vb2_dvb_start_feed(struct dvb_demux_feed *feed)
  36 {
  37         struct dvb_demux *demux = feed->demux;
  38         struct vb2_dvb *dvb = demux->priv;
  39         int rc = 0;
  40 
  41         if (!demux->dmx.frontend)
  42                 return -EINVAL;
  43 
  44         mutex_lock(&dvb->lock);
  45         dvb->nfeeds++;
  46 
  47         if (!dvb->dvbq.threadio) {
  48                 rc = vb2_thread_start(&dvb->dvbq, dvb_fnc, dvb, dvb->name);
  49                 if (rc)
  50                         dvb->nfeeds--;
  51         }
  52         if (!rc)
  53                 rc = dvb->nfeeds;
  54         mutex_unlock(&dvb->lock);
  55         return rc;
  56 }
  57 
  58 static int vb2_dvb_stop_feed(struct dvb_demux_feed *feed)
  59 {
  60         struct dvb_demux *demux = feed->demux;
  61         struct vb2_dvb *dvb = demux->priv;
  62         int err = 0;
  63 
  64         mutex_lock(&dvb->lock);
  65         dvb->nfeeds--;
  66         if (0 == dvb->nfeeds)
  67                 err = vb2_thread_stop(&dvb->dvbq);
  68         mutex_unlock(&dvb->lock);
  69         return err;
  70 }
  71 
  72 static int vb2_dvb_register_adapter(struct vb2_dvb_frontends *fe,
  73                           struct module *module,
  74                           void *adapter_priv,
  75                           struct device *device,
  76                           struct media_device *mdev,
  77                           char *adapter_name,
  78                           short *adapter_nr,
  79                           int mfe_shared)
  80 {
  81         int result;
  82 
  83         mutex_init(&fe->lock);
  84 
  85         /* register adapter */
  86         result = dvb_register_adapter(&fe->adapter, adapter_name, module,
  87                 device, adapter_nr);
  88         if (result < 0) {
  89                 pr_warn("%s: dvb_register_adapter failed (errno = %d)\n",
  90                        adapter_name, result);
  91         }
  92         fe->adapter.priv = adapter_priv;
  93         fe->adapter.mfe_shared = mfe_shared;
  94 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
  95         if (mdev)
  96                 fe->adapter.mdev = mdev;
  97 #endif
  98         return result;
  99 }
 100 
 101 static int vb2_dvb_register_frontend(struct dvb_adapter *adapter,
 102         struct vb2_dvb *dvb)
 103 {
 104         int result;
 105 
 106         /* register frontend */
 107         result = dvb_register_frontend(adapter, dvb->frontend);
 108         if (result < 0) {
 109                 pr_warn("%s: dvb_register_frontend failed (errno = %d)\n",
 110                        dvb->name, result);
 111                 goto fail_frontend;
 112         }
 113 
 114         /* register demux stuff */
 115         dvb->demux.dmx.capabilities =
 116                 DMX_TS_FILTERING | DMX_SECTION_FILTERING |
 117                 DMX_MEMORY_BASED_FILTERING;
 118         dvb->demux.priv       = dvb;
 119         dvb->demux.filternum  = 256;
 120         dvb->demux.feednum    = 256;
 121         dvb->demux.start_feed = vb2_dvb_start_feed;
 122         dvb->demux.stop_feed  = vb2_dvb_stop_feed;
 123         result = dvb_dmx_init(&dvb->demux);
 124         if (result < 0) {
 125                 pr_warn("%s: dvb_dmx_init failed (errno = %d)\n",
 126                        dvb->name, result);
 127                 goto fail_dmx;
 128         }
 129 
 130         dvb->dmxdev.filternum    = 256;
 131         dvb->dmxdev.demux        = &dvb->demux.dmx;
 132         dvb->dmxdev.capabilities = 0;
 133         result = dvb_dmxdev_init(&dvb->dmxdev, adapter);
 134 
 135         if (result < 0) {
 136                 pr_warn("%s: dvb_dmxdev_init failed (errno = %d)\n",
 137                        dvb->name, result);
 138                 goto fail_dmxdev;
 139         }
 140 
 141         dvb->fe_hw.source = DMX_FRONTEND_0;
 142         result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 143         if (result < 0) {
 144                 pr_warn("%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
 145                        dvb->name, result);
 146                 goto fail_fe_hw;
 147         }
 148 
 149         dvb->fe_mem.source = DMX_MEMORY_FE;
 150         result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 151         if (result < 0) {
 152                 pr_warn("%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
 153                        dvb->name, result);
 154                 goto fail_fe_mem;
 155         }
 156 
 157         result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 158         if (result < 0) {
 159                 pr_warn("%s: connect_frontend failed (errno = %d)\n",
 160                        dvb->name, result);
 161                 goto fail_fe_conn;
 162         }
 163 
 164         /* register network adapter */
 165         result = dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
 166         if (result < 0) {
 167                 pr_warn("%s: dvb_net_init failed (errno = %d)\n",
 168                        dvb->name, result);
 169                 goto fail_fe_conn;
 170         }
 171         return 0;
 172 
 173 fail_fe_conn:
 174         dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 175 fail_fe_mem:
 176         dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 177 fail_fe_hw:
 178         dvb_dmxdev_release(&dvb->dmxdev);
 179 fail_dmxdev:
 180         dvb_dmx_release(&dvb->demux);
 181 fail_dmx:
 182         dvb_unregister_frontend(dvb->frontend);
 183 fail_frontend:
 184         dvb_frontend_detach(dvb->frontend);
 185         dvb->frontend = NULL;
 186 
 187         return result;
 188 }
 189 
 190 /* ------------------------------------------------------------------ */
 191 /* Register a single adapter and one or more frontends */
 192 int vb2_dvb_register_bus(struct vb2_dvb_frontends *f,
 193                          struct module *module,
 194                          void *adapter_priv,
 195                          struct device *device,
 196                          struct media_device *mdev,
 197                          short *adapter_nr,
 198                          int mfe_shared)
 199 {
 200         struct list_head *list, *q;
 201         struct vb2_dvb_frontend *fe;
 202         int res;
 203 
 204         fe = vb2_dvb_get_frontend(f, 1);
 205         if (!fe) {
 206                 pr_warn("Unable to register the adapter which has no frontends\n");
 207                 return -EINVAL;
 208         }
 209 
 210         /* Bring up the adapter */
 211         res = vb2_dvb_register_adapter(f, module, adapter_priv, device, mdev,
 212                 fe->dvb.name, adapter_nr, mfe_shared);
 213         if (res < 0) {
 214                 pr_warn("vb2_dvb_register_adapter failed (errno = %d)\n", res);
 215                 return res;
 216         }
 217 
 218         /* Attach all of the frontends to the adapter */
 219         mutex_lock(&f->lock);
 220         list_for_each_safe(list, q, &f->felist) {
 221                 fe = list_entry(list, struct vb2_dvb_frontend, felist);
 222                 res = vb2_dvb_register_frontend(&f->adapter, &fe->dvb);
 223                 if (res < 0) {
 224                         pr_warn("%s: vb2_dvb_register_frontend failed (errno = %d)\n",
 225                                 fe->dvb.name, res);
 226                         goto err;
 227                 }
 228                 res = dvb_create_media_graph(&f->adapter, false);
 229                 if (res < 0)
 230                         goto err;
 231         }
 232 
 233         mutex_unlock(&f->lock);
 234         return 0;
 235 
 236 err:
 237         mutex_unlock(&f->lock);
 238         vb2_dvb_unregister_bus(f);
 239         return res;
 240 }
 241 EXPORT_SYMBOL(vb2_dvb_register_bus);
 242 
 243 void vb2_dvb_unregister_bus(struct vb2_dvb_frontends *f)
 244 {
 245         vb2_dvb_dealloc_frontends(f);
 246 
 247         dvb_unregister_adapter(&f->adapter);
 248 }
 249 EXPORT_SYMBOL(vb2_dvb_unregister_bus);
 250 
 251 struct vb2_dvb_frontend *vb2_dvb_get_frontend(
 252         struct vb2_dvb_frontends *f, int id)
 253 {
 254         struct list_head *list, *q;
 255         struct vb2_dvb_frontend *fe, *ret = NULL;
 256 
 257         mutex_lock(&f->lock);
 258 
 259         list_for_each_safe(list, q, &f->felist) {
 260                 fe = list_entry(list, struct vb2_dvb_frontend, felist);
 261                 if (fe->id == id) {
 262                         ret = fe;
 263                         break;
 264                 }
 265         }
 266 
 267         mutex_unlock(&f->lock);
 268 
 269         return ret;
 270 }
 271 EXPORT_SYMBOL(vb2_dvb_get_frontend);
 272 
 273 int vb2_dvb_find_frontend(struct vb2_dvb_frontends *f,
 274         struct dvb_frontend *p)
 275 {
 276         struct list_head *list, *q;
 277         struct vb2_dvb_frontend *fe = NULL;
 278         int ret = 0;
 279 
 280         mutex_lock(&f->lock);
 281 
 282         list_for_each_safe(list, q, &f->felist) {
 283                 fe = list_entry(list, struct vb2_dvb_frontend, felist);
 284                 if (fe->dvb.frontend == p) {
 285                         ret = fe->id;
 286                         break;
 287                 }
 288         }
 289 
 290         mutex_unlock(&f->lock);
 291 
 292         return ret;
 293 }
 294 EXPORT_SYMBOL(vb2_dvb_find_frontend);
 295 
 296 struct vb2_dvb_frontend *vb2_dvb_alloc_frontend(
 297         struct vb2_dvb_frontends *f, int id)
 298 {
 299         struct vb2_dvb_frontend *fe;
 300 
 301         fe = kzalloc(sizeof(struct vb2_dvb_frontend), GFP_KERNEL);
 302         if (fe == NULL)
 303                 return NULL;
 304 
 305         fe->id = id;
 306         mutex_init(&fe->dvb.lock);
 307 
 308         mutex_lock(&f->lock);
 309         list_add_tail(&fe->felist, &f->felist);
 310         mutex_unlock(&f->lock);
 311         return fe;
 312 }
 313 EXPORT_SYMBOL(vb2_dvb_alloc_frontend);
 314 
 315 void vb2_dvb_dealloc_frontends(struct vb2_dvb_frontends *f)
 316 {
 317         struct list_head *list, *q;
 318         struct vb2_dvb_frontend *fe;
 319 
 320         mutex_lock(&f->lock);
 321         list_for_each_safe(list, q, &f->felist) {
 322                 fe = list_entry(list, struct vb2_dvb_frontend, felist);
 323                 if (fe->dvb.net.dvbdev) {
 324                         dvb_net_release(&fe->dvb.net);
 325                         fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
 326                                 &fe->dvb.fe_mem);
 327                         fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx,
 328                                 &fe->dvb.fe_hw);
 329                         dvb_dmxdev_release(&fe->dvb.dmxdev);
 330                         dvb_dmx_release(&fe->dvb.demux);
 331                         dvb_unregister_frontend(fe->dvb.frontend);
 332                 }
 333                 if (fe->dvb.frontend)
 334                         /* always allocated, may have been reset */
 335                         dvb_frontend_detach(fe->dvb.frontend);
 336                 list_del(list); /* remove list entry */
 337                 kfree(fe);      /* free frontend allocation */
 338         }
 339         mutex_unlock(&f->lock);
 340 }
 341 EXPORT_SYMBOL(vb2_dvb_dealloc_frontends);

/* [<][>][^][v][top][bottom][index][help] */