[linux-dvb] Re: Hybrid tuner proposal (V4L/DVB)

Markus Rechberger mrechberger at gmail.com
Thu Apr 5 01:05:57 CEST 2007


To address people who are affected by this decission I'd like everyone
on the em28xx mailinglist (~150 people are signed up on the ML at the
moment) to watch this thread.

This is a topic which is very important for the driver to get into the
kernel tree, so please watch it carefully, this is also a very good
chance to learn how discussions on the video4linux/dvb side work.

If you have any doubts about that step forward you're welcome to
participate at that discussion.

Markus

On 4/5/07, Markus Rechberger <mrechberger at gmail.com> wrote:
> I sent this proposal to several individual developers already around
> 1-2 weeks ago, and received several comments, maybe I should give it a
> try to push a very last discussion about it.
>
> Video4Linux/DVB Hybrid Tuner Support
> ====================================
>
> During the last few years some hybrid tuners came up which support
> digital and analogue signals.
> Currently there are 2 approaches how to use such tuners.
>
> The first way is to simply send a few bytes through i2c to a tuner for
> setting up a frequency,
> this way splits up the specs into 2 halfs, the analogue tuner
> interface supports analogue tuning
> and the dtv part only supports setting up dtv channels.
>
> Pro:
> the code is tight, since these tuners are easy to program.
>
> Contra:
> all devices would need to reimplement that algorithm for setting up
> the channel, there's no
> global point for such an approach.
>
>
> Another way would be to inherit the v4l tuner interface like it's done
> in the saa7134-dvb tuner
> the driver just reimplements set_params and calls VIDIOC_S_FREQUENCY.
> This way if a device only supports DVB it would also have a dependency
> to the video4linux
> tuner framework.
>
> Pro:
> code can be reused, only one tuner implementation has to be written.
>
> Cons:
> a dvb only driver would require video4linux tuner bindings.
>
>
>
> How is it currently implemented into the DVB framework?
> -------------------------------------------------------
>
> there's already a pluggable tuner mechanism implemented into the DVB
> framework which makes use
> of dvb_attach().
>
> Every external module should have a struct that defines what method
> are provided by the tuner,
> currently the arguments of these methods are bound to struct
> dvb_frontend * which carries a priv
> pointer which is used to stored private data of the module.
>
> Here an example of such a struct (taken from mt2060.c)
> static const struct dvb_tuner_ops mt2060_tuner_ops = {
>         .info = {
>                 .name           = "Microtune MT2060",
>                 .frequency_min  =  48000000,
>                 .frequency_max  = 860000000,
>                 .frequency_step =     50000,
>         },
>
>         .release       = mt2060_release,
>
>         .init          = mt2060_init,
>         .sleep         = mt2060_sleep,
>
>         .set_params    = mt2060_set_params,
>         .get_frequency = mt2060_get_frequency,
>         .get_bandwidth = mt2060_get_bandwidth
> };
>
> The current interface structure is defined as:
> struct dvb_tuner_ops {
>
>         struct dvb_tuner_info info;
>
>         int (*release)(struct dvb_frontend *fe);
>         int (*init)(struct dvb_frontend *fe);
>         int (*sleep)(struct dvb_frontend *fe);
>
>         /** This is for simple PLLs - set all parameters in one go. */
>         int (*set_params)(struct dvb_frontend *fe, struct
> dvb_frontend_parameters *p);
>
>         /** This is support for demods like the mt352 - fills out the
> supplied buffer with what to write. */
>         int (*calc_regs)(struct dvb_frontend *fe, struct
> dvb_frontend_parameters *p, u8 *buf, int buf_len);
>
>         int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
>         int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
>
> #define TUNER_STATUS_LOCKED 1
>         int (*get_status)(struct dvb_frontend *fe, u32 *status);
>
>         /** These are provided seperately from set_params in order to
> facilitate silicon
>          * tuners which require sophisticated tuning loops,
> controlling each parameter seperately. */
>         int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
>         int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
> };
>
> these functionpointers are set up during the call of the specific
> {dvbtuner}_attach function
>
> memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
>
> This approach is heavily bound to an initialized dvb_frontend structure.
>
>
> The current video4linux approach
> --------------------------------
>
> the tuner-core doesn't support any external modules for real, instead
> all modules are directly linked into tuner.ko.
> The tuner-core calls a detection/setuproutine during either
> tuner_attach or TUNER_SET_TYPE_ADDR;
> during the i2c scan you can also override several settings by calling
> TUNER_SET_TYPE_ADDR within an attach_inform callback
> to adjust some settings (for example setting a different tuner type on
> a specific i2c address)
> This control option also supports changing the tuner type at a later
> time (for example for radio initialization etc)
>
>
> The new way
> ===========
>
> The newer way I'd like to propose here is to unify a pluggable tuner
> mechanism which then can be
> reused by other drivers as well for upcoming tuners.
>
> proposed changes to the dvb-framework:
>
> changes to the dvb-framework are intrusive, they'd require the change
> of dvb_tuner_ops.
> I'd suggest to defer dvb_frontend and add several new pointers to the
> dvb_tuner_ops structure.
> The dvb_tuner_ops structure should become a neutral structure that can
> easily be reused by anything that
> requires a tuner.
>
> the structure could be:
> struct v4l_dvb_tuner {
>         /* wrapper */
>         void *priv; /* some privat data for internal use */
>         void *dev; /* v4l private data for tuner-core */
>         struct dvb_frontend *fe; /* dvb_frontend, for dvb only
> drivers, internal use */
>
>         int (*ioctl)(struct v4l_dvb_tuner *dev, int cmd, int arg);
>         struct tuner_info info;
>         int (*release)(struct v4l_dvb_tuner *dev);
>         int (*init)(struct v4l_dvb_tuner *dev);
>         int (*sleep)(struct v4l_dvb_tuner *dev);
>
>         /** This is for simple PLLs - set all parameters in one go. */
>         int (*set_params)(struct v4l_dvb_tuner *dev, struct
> tuner_parameters *p);
>
>         /** This is support for demods like the mt352 - fills out the
> supplied buffer with what to write. */
>         int (*calc_regs)(struct v4l_dvb_tuner *dev, struct
> tuner_parameters *p, u8 *buf, int buf_len);
>
>         int (*get_frequency)(struct v4l_dvb_tuner *dev, u32 *frequency);
>         int (*get_bandwidth)(struct v4l_dvb_tuner *dev, u32 *bandwidth);
>
> #define TUNER_STATUS_LOCKED 1
>         int (*get_status)(struct v4l_dvb_tuner *dev, u32 *status);
>
>         /** These are provided seperately from set_params in order to
> facilitate silicon
>          * tuners which require sophisticated tuning loops,
> controlling each parameter seperately. */
>         int (*set_frequency)(struct v4l_dvb_tuner *dev, u32 frequency);
>         int (*set_bandwidth)(struct v4l_dvb_tuner *dev, u32 bandwidth);
>
>         int  (*set_mode)(struct v4l_dvb_tuner *dev, struct
> tuner_parameters *params);
> };
>
> in that case dvb_frontend *fe just gets deferred as an element of that
> structure,
> if any dvb only would still require dvb_frontend *fe it could easily
> still make use of it
> by just refering to its own structure dev->fe;
>
> As for hybrid tuners they'd have to avoid the usage of dvb_frontend
> *fe and they should
> only rely on its own structure which can be extended even in future.
>
> Features like i2c_gate_ctrl might also be added in a unified way to
> that structure.
>
> if (fe->ops.i2c_gate_ctrl)
>         fe->ops.i2c_gate_ctrl(fe, 1);
>
> tuner-core changes:
> the tuner-core itself relies on i2c, to use the unified external
> modules we have to add an approach
> which supports loading these external modules.
> I added support for loading the xc3028-tuner module within set_type()
> using the symbol_request approach
> When tuner.ko gets loaded it scans for i2c addresses and attaches
> itself to some predefined addresses.
> if a tuner was found on a certain address the i2c framework calls an
> attach_inform function which in case
> of the em28xx and several other drivers is privatly defined in the
> driver itself.
> this happens before:
>
> register_client:
>         tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
>         i2c_attach_client (&t->i2c);
>         set_type (&t->i2c,t->type, t->mode_mask, t->config,
> t->tuner_callback, TUNER_ATTACH);
> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
>         MOD_INC_USE_COUNT;
> #endif
>         return 0;
> }
>
> set_type gets called, at that point you can override the tuner to any
> tuner type you want by calling
> TUNER_SET_TYPE_ADDR within the attach_inform callback.
> In case of the em28xx it sets the tuner to TUNER_XC3028, so that the
> tuner framework knows that it has
> to request the xc3028 tuner and initialize the necessary function
> pointers with the unified xc3028
> tuner structure.
>
> I already had a previous tuner modularization approach which relied on
> the same way it was done
> in saa7134 by exporting a symbol which gets called by the external
> module to copy some function pointers.
> There were some drawbacks with that approach which are felt with
> saa7134 cx88 and em28xx already
> it's not possible to request external modules which rely on a symbol
> that's not yet exported
>
> This becomes an important point if you do some tuner detection, it's
> not possible to load
> external drivers before the tuner-core got loaded completly. So I
> didn't make much noise
> that this approach is broken especially during the initialization of a tuner.
>
> > Mauro wrote that requesting the tuner module first and afterwards call an init function within the driver
> > which requested that module, this might be a solution for using initialization functions similar to
> > usb_register/usb_deregister.
> > on the other side this would break the dvb_attach approach and it might require much bigger changes in the
> > dvb framework (?)
> > This approach is currently partly implemented in v4l-dvb-kernel on mcentral (http://mcentral.de/hg/~mrec/v4l-dvb-kernel)
>
> a current implementation which uses the unified module approach and a
> similar approach like dvb_attach can be found
> at:
> http://mcentral.de/hg/~mrec/v4l-dvb-experimental
> (see tuner-core.c, v4l_dvb_tuner.h)
>
> Markus
>


-- 
Markus Rechberger



More information about the linux-dvb mailing list