Commit d525e5c2 authored by Maciej S. Szmigiero's avatar Maciej S. Szmigiero Committed by Mauro Carvalho Chehab

media: cxusb: implement Medion MD95700 digital / analog coexistence

This patch prepares cxusb driver for supporting the analog part of
Medion 95700 (previously only the digital - DVB - mode was supported).

Specifically, it adds support for:
* switching the device between analog and digital modes of operation,
* enforcing that only one mode is active at the same time due to hardware
limitations.

Actual implementation of the analog mode will be provided by the next
commit.
Signed-off-by: default avatarMaciej S. Szmigiero <mail@maciej.szmigiero.name>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 65efeca0
This diff is collapsed.
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
#ifndef _DVB_USB_CXUSB_H_ #ifndef _DVB_USB_CXUSB_H_
#define _DVB_USB_CXUSB_H_ #define _DVB_USB_CXUSB_H_
#include <linux/i2c.h>
#include <linux/mutex.h>
#define DVB_USB_LOG_PREFIX "cxusb" #define DVB_USB_LOG_PREFIX "cxusb"
#include "dvb-usb.h" #include "dvb-usb.h"
...@@ -34,6 +37,7 @@ ...@@ -34,6 +37,7 @@
struct cxusb_state { struct cxusb_state {
u8 gpio_write_state[3]; u8 gpio_write_state[3];
bool gpio_write_refresh[3];
struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner; struct i2c_client *i2c_client_tuner;
...@@ -45,4 +49,48 @@ struct cxusb_state { ...@@ -45,4 +49,48 @@ struct cxusb_state {
enum fe_status *status); enum fe_status *status);
}; };
enum cxusb_open_type {
CXUSB_OPEN_INIT, CXUSB_OPEN_NONE,
CXUSB_OPEN_ANALOG, CXUSB_OPEN_DIGITAL
};
struct cxusb_medion_dev {
/* has to be the first one */
struct cxusb_state state;
struct dvb_usb_device *dvbdev;
enum cxusb_open_type open_type;
unsigned int open_ctr;
struct mutex open_lock;
};
/* defines for "debug" module parameter */
#define CXUSB_DBG_RC BIT(0)
#define CXUSB_DBG_I2C BIT(1)
#define CXUSB_DBG_MISC BIT(2)
extern int dvb_usb_cxusb_debug;
int cxusb_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, const u8 *wbuf, int wlen, u8 *rbuf, int rlen);
static inline int cxusb_medion_analog_init(struct dvb_usb_device *dvbdev)
{
return -EINVAL;
}
static inline int cxusb_medion_register_analog(struct dvb_usb_device *dvbdev)
{
return 0;
}
static inline void cxusb_medion_unregister_analog(struct dvb_usb_device *dvbdev)
{
}
int cxusb_medion_get(struct dvb_usb_device *dvbdev,
enum cxusb_open_type open_type);
void cxusb_medion_put(struct dvb_usb_device *dvbdev);
#endif #endif
...@@ -56,9 +56,6 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) ...@@ -56,9 +56,6 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
* for reception. * for reception.
*/ */
if (adap->feedcount == onoff && adap->feedcount > 0) { if (adap->feedcount == onoff && adap->feedcount > 0) {
deb_ts("submitting all URBs\n");
usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
deb_ts("controlling pid parser\n"); deb_ts("controlling pid parser\n");
if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER && if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
adap->props.fe[adap->active_fe].caps & adap->props.fe[adap->active_fe].caps &
...@@ -80,6 +77,8 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) ...@@ -80,6 +77,8 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
} }
} }
deb_ts("submitting all URBs\n");
usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
} }
return 0; return 0;
} }
......
...@@ -133,6 +133,10 @@ static int dvb_usb_exit(struct dvb_usb_device *d) ...@@ -133,6 +133,10 @@ static int dvb_usb_exit(struct dvb_usb_device *d)
dvb_usb_i2c_exit(d); dvb_usb_i2c_exit(d);
deb_info("state should be zero now: %x\n", d->state); deb_info("state should be zero now: %x\n", d->state);
d->state = DVB_USB_STATE_INIT; d->state = DVB_USB_STATE_INIT;
if (d->priv != NULL && d->props.priv_destroy != NULL)
d->props.priv_destroy(d);
kfree(d->priv); kfree(d->priv);
kfree(d); kfree(d);
return 0; return 0;
...@@ -154,6 +158,15 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums) ...@@ -154,6 +158,15 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
err("no memory for priv in 'struct dvb_usb_device'"); err("no memory for priv in 'struct dvb_usb_device'");
return -ENOMEM; return -ENOMEM;
} }
if (d->props.priv_init != NULL) {
ret = d->props.priv_init(d);
if (ret != 0) {
kfree(d->priv);
d->priv = NULL;
return ret;
}
}
} }
/* check the capabilities and set appropriate variables */ /* check the capabilities and set appropriate variables */
......
...@@ -129,6 +129,9 @@ struct usb_data_stream_properties { ...@@ -129,6 +129,9 @@ struct usb_data_stream_properties {
* @frontend_ctrl: called to power on/off active frontend. * @frontend_ctrl: called to power on/off active frontend.
* @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
* device (not URB submitting/killing). * device (not URB submitting/killing).
* This callback will be called without data URBs being active - data URBs
* will be submitted only after streaming_ctrl(1) returns successfully and
* they will be killed before streaming_ctrl(0) gets called.
* @pid_filter_ctrl: called to en/disable the PID filter, if any. * @pid_filter_ctrl: called to en/disable the PID filter, if any.
* @pid_filter: called to set/unset a PID for filtering. * @pid_filter: called to set/unset a PID for filtering.
* @frontend_attach: called to attach the possible frontends (fill fe-field * @frontend_attach: called to attach the possible frontends (fill fe-field
...@@ -234,6 +237,11 @@ enum dvb_usb_mode { ...@@ -234,6 +237,11 @@ enum dvb_usb_mode {
* *
* @size_of_priv: how many bytes shall be allocated for the private field * @size_of_priv: how many bytes shall be allocated for the private field
* of struct dvb_usb_device. * of struct dvb_usb_device.
* @priv_init: optional callback to initialize the variable that private field
* of struct dvb_usb_device has pointer to just after it had been allocated and
* zeroed.
* @priv_destroy: just like priv_init, only called before deallocating
* the memory pointed by private field of struct dvb_usb_device.
* *
* @power_ctrl: called to enable/disable power of the device. * @power_ctrl: called to enable/disable power of the device.
* @read_mac_address: called to read the MAC address of the device. * @read_mac_address: called to read the MAC address of the device.
...@@ -275,6 +283,8 @@ struct dvb_usb_device_properties { ...@@ -275,6 +283,8 @@ struct dvb_usb_device_properties {
int no_reconnect; int no_reconnect;
int size_of_priv; int size_of_priv;
int (*priv_init)(struct dvb_usb_device *);
void (*priv_destroy)(struct dvb_usb_device *);
int num_adapters; int num_adapters;
struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment