Re: [PATCH 10/11] add DVB-T support for tlg2300
Huang Shijie wrote: > This module contains the code for DVB-T. > > Signed-off-by: Huang Shijie > --- > drivers/media/video/tlg2300/pd-dvb.c | 649 > ++ > 1 files changed, 649 insertions(+), 0 deletions(-) > create mode 100644 drivers/media/video/tlg2300/pd-dvb.c > > diff --git a/drivers/media/video/tlg2300/pd-dvb.c > b/drivers/media/video/tlg2300/pd-dvb.c > new file mode 100644 > index 000..933fff0 > --- /dev/null > +++ b/drivers/media/video/tlg2300/pd-dvb.c > @@ -0,0 +1,649 @@ > +#include "pd-common.h" > +#include > +#include > +#include > +#include > + > +#include "vendorcmds.h" > +#include > +#include > + > +static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); > + > +static int dvb_bandwidth[][2] = { > + { TLG_BW_8, BANDWIDTH_8_MHZ }, > + { TLG_BW_7, BANDWIDTH_7_MHZ }, > + { TLG_BW_6, BANDWIDTH_6_MHZ } > +}; > +static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); > + > +static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb); > +static int poseidon_check_mode_dvbt(struct poseidon *pd) > +{ > + s32 ret = 0, cmd_status = 0; > + > + set_current_state(TASK_INTERRUPTIBLE); > + schedule_timeout(HZ/4); > + > + ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE); > + if (ret != 0) > + return ret; > + > + ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T); > + if (ret) > + return ret; > + > + /* signal source */ > + ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status); > + if (ret|cmd_status) > + return ret; > + > + return 0; > +} > + > +/* acquire : > + * 1 == open > + * 0 == release > + */ > +static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) > +{ > + struct poseidon *pd = fe->demodulator_priv; > + struct pd_dvb_adapter *pd_dvb; > + int ret = 0; > + > + if (!pd) > + return -ENODEV; > + > + pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe); > + if (acquire) { > + mutex_lock(&pd->lock); > + if (pd->state & POSEIDON_STATE_DISCONNECT) { > + ret = -ENODEV; > + goto open_out; > + } > + > + if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) { > + ret = -EBUSY; > + goto open_out; > + } > + > + usb_autopm_get_interface(pd->interface); > + if (0 == pd->state) { > + ret = poseidon_check_mode_dvbt(pd); > + if (ret < 0) > + goto open_out; > + pd->state |= POSEIDON_STATE_DVBT; > + pd_dvb->bandwidth = 0; > + pd_dvb->prev_freq = 0; > + } > + atomic_inc(&pd_dvb->users); > + kref_get(&pd->kref); > +open_out: > + mutex_unlock(&pd->lock); > + } else { > + dvb_stop_streaming(pd_dvb); > + > + if (atomic_dec_and_test(&pd_dvb->users)) { > + mutex_lock(&pd->lock); > + pd->state &= ~POSEIDON_STATE_DVBT; > + mutex_unlock(&pd->lock); > + } > + kref_put(&pd->kref, poseidon_delete); > + usb_autopm_put_interface(pd->interface); > + } > + return ret; > +} > + > +static void poseidon_fe_release(struct dvb_frontend *fe) > +{ > + struct poseidon *pd = fe->demodulator_priv; > + > +#ifdef CONFIG_PM > + pd->pm_suspend = NULL; > + pd->pm_resume = NULL; > +#endif > +} > + > +static s32 poseidon_fe_sleep(struct dvb_frontend *fe) > +{ > + return 0; > +} > + > +/* > + * return true if we can satisfy the conditions, else return false. > + */ > +static bool check_scan_ok(__u32 freq, int bandwidth, > + struct pd_dvb_adapter *adapter) > +{ > + if (bandwidth < 0) > + return false; > + > + if (adapter->prev_freq == freq > + && adapter->bandwidth == bandwidth) { > + long nl = jiffies - adapter->last_jiffies; > + unsigned int msec ; > + > + msec = jiffies_to_msecs(abs(nl)); > + return msec > 15000 ? true : false; > + } > + return true; > +} > + > +/* > + * Check if the firmware delays too long for an invalid frequency. > + */ > +static int fw_delay_overflow(struct pd_dvb_adapter *adapter) > +{ > + long nl = jiffies - adapter->last_jiffies; > + unsigned int msec ; > + > + msec = jiffies_to_msecs(abs(nl)); > + return msec > 800 ? true : false; > +} > + > +static int pm_dvb_suspend(struct poseidon *pd) > +{ > + struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; > + dvb_stop_streaming(pd_dvb); > + dvb_urb_cleanup(pd_dvb); > + mdelay(2000); Use msleep() > + return 0; > +} > + > + > +static int poseidon_set_fe(struct dvb_frontend *fe, > + struct dvb_frontend_parameters *fep) > +{ >
[PATCH 10/11] add DVB-T support for tlg2300
This module contains the code for DVB-T. Signed-off-by: Huang Shijie --- drivers/media/video/tlg2300/pd-dvb.c | 649 ++ 1 files changed, 649 insertions(+), 0 deletions(-) create mode 100644 drivers/media/video/tlg2300/pd-dvb.c diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c new file mode 100644 index 000..933fff0 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-dvb.c @@ -0,0 +1,649 @@ +#include "pd-common.h" +#include +#include +#include +#include + +#include "vendorcmds.h" +#include +#include + +static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); + +static int dvb_bandwidth[][2] = { + { TLG_BW_8, BANDWIDTH_8_MHZ }, + { TLG_BW_7, BANDWIDTH_7_MHZ }, + { TLG_BW_6, BANDWIDTH_6_MHZ } +}; +static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); + +static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb); +static int poseidon_check_mode_dvbt(struct poseidon *pd) +{ + s32 ret = 0, cmd_status = 0; + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/4); + + ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE); + if (ret != 0) + return ret; + + ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T); + if (ret) + return ret; + + /* signal source */ + ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status); + if (ret|cmd_status) + return ret; + + return 0; +} + +/* acquire : + * 1 == open + * 0 == release + */ +static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) +{ + struct poseidon *pd = fe->demodulator_priv; + struct pd_dvb_adapter *pd_dvb; + int ret = 0; + + if (!pd) + return -ENODEV; + + pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe); + if (acquire) { + mutex_lock(&pd->lock); + if (pd->state & POSEIDON_STATE_DISCONNECT) { + ret = -ENODEV; + goto open_out; + } + + if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) { + ret = -EBUSY; + goto open_out; + } + + usb_autopm_get_interface(pd->interface); + if (0 == pd->state) { + ret = poseidon_check_mode_dvbt(pd); + if (ret < 0) + goto open_out; + pd->state |= POSEIDON_STATE_DVBT; + pd_dvb->bandwidth = 0; + pd_dvb->prev_freq = 0; + } + atomic_inc(&pd_dvb->users); + kref_get(&pd->kref); +open_out: + mutex_unlock(&pd->lock); + } else { + dvb_stop_streaming(pd_dvb); + + if (atomic_dec_and_test(&pd_dvb->users)) { + mutex_lock(&pd->lock); + pd->state &= ~POSEIDON_STATE_DVBT; + mutex_unlock(&pd->lock); + } + kref_put(&pd->kref, poseidon_delete); + usb_autopm_put_interface(pd->interface); + } + return ret; +} + +static void poseidon_fe_release(struct dvb_frontend *fe) +{ + struct poseidon *pd = fe->demodulator_priv; + +#ifdef CONFIG_PM + pd->pm_suspend = NULL; + pd->pm_resume = NULL; +#endif +} + +static s32 poseidon_fe_sleep(struct dvb_frontend *fe) +{ + return 0; +} + +/* + * return true if we can satisfy the conditions, else return false. + */ +static bool check_scan_ok(__u32 freq, int bandwidth, + struct pd_dvb_adapter *adapter) +{ + if (bandwidth < 0) + return false; + + if (adapter->prev_freq == freq + && adapter->bandwidth == bandwidth) { + long nl = jiffies - adapter->last_jiffies; + unsigned int msec ; + + msec = jiffies_to_msecs(abs(nl)); + return msec > 15000 ? true : false; + } + return true; +} + +/* + * Check if the firmware delays too long for an invalid frequency. + */ +static int fw_delay_overflow(struct pd_dvb_adapter *adapter) +{ + long nl = jiffies - adapter->last_jiffies; + unsigned int msec ; + + msec = jiffies_to_msecs(abs(nl)); + return msec > 800 ? true : false; +} + +static int pm_dvb_suspend(struct poseidon *pd) +{ + struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; + dvb_stop_streaming(pd_dvb); + dvb_urb_cleanup(pd_dvb); + mdelay(2000); + return 0; +} + + +static int poseidon_set_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + s32 ret = 0, cmd_status = 0; + s32 i, bandwidth = -1; + struct poseidon *pd = fe->demodulator_priv; + struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; + + if (in_hibernation(pd)) +