Hi Manu,
Here is the first version of the patch
that will implement Suspend/resume S2DISK
(no remote control support).
S2DISK works for me on cu1216.c on 2.6.22.1-41.fc7 kernel.
For another Mantis device, you have to
- introduce tuner_ops.sleep and tuner_ops.init in mantis_dvb.c (two
lines after dvb_attach(cu1216)).
- implement fe->ops.init to do something if necessary (I did it on
cu1216.c).
- implement fe->ops.set_frontend() to accept NULL for "set those params
that were active during suspend".
- If tuner_ops.init is defined, resume in mantis_dvb.c assumes that
set_frontend() accepts NULL argument.
I tried to make the patch so, that you could check it into your version
control as such.
Unfortunately I couldn't compile your v4l-dvb branch, and thus
I converted your v4l-dvb branch into the very latest LinuxTV v4l-dvb
version for testing.
This patch doesn't include remote control support,
because mantis_rc.c is not yet in the version control.
cu1216.c: many small adjustments.
- Fixes rmmod/insmod "lost frontend" problem.
- Fixes inversion=1 support requirement for Finland DVB-C.
- dvb_core is able to reset cu1216 module if it fails.
dvb/mantis: many suspend related adjustments.
- Suspend/resume support for S2DISK: it works for cu1216. See
mantis_dvb.c if you
like to add support for other frontend.
- mantis_dvb.c: will not load all Mantis frontend modules, but just the
ones that are needed.
- mantis_dvb.c: will turn off tuner (tuner_ops.sleep) , and turn it on
again for cu1216.c (tuner_ops.init).
- mantis_dvb.c: suspend/resume support takes advantage of the tuner
power functions and fe->ops.set_frontend(fe,NULL) if tuner_ops.init is
defined.
- mantis_pci.c: share code with probe and resume and with exit and suspend.
- mantis_i2c.c: suspend/resume support.
- mantis_i2c.c: mantis_i2c_init and mantis_i2c_exit altered a lot, but
those changes aren't necessary anymore.
Maybe remove those unnecessary changes?
- mantis_dma.c: suspend/resume support. mantis_start_dma and
mantis_stop_dma calls are enough though.
Maybe just remove all suspend/resume code from mantis_start/stop_dma?
- mantis_common.h: suspend/resume support. Some suspend status support
added and introduced some functions.
- mantis_core.h: suspend/resume support: Introduced some functions.
- mantis/Makefile: Use += for flags: this is the way in current v4l-dvb
main branch.
Now you have my code to be seen and even applied into your Mantis
branch, if you want.
mantis_rc.c: This code is not yet to be seen, but at least I had to
enable Mantis IRQ for
remote control during resume.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
Signed-off-by: Marko M Ristola <marko.ristola@xxxxxxxxxxx>
Regards,
Marko Ristola
--- v4l-dvb-base/linux/drivers/media/dvb/frontends/cu1216.c 2007-08-05 14:12:08.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/frontends/cu1216.c 2007-08-06 23:51:14.000000000 +0300
@@ -44,14 +44,14 @@ MODULE_PARM_DESC(verbose, "print AFC off
struct cu1216_state {
struct i2c_adapter *i2c;
- struct dvb_frontend_ops ops;
/* config settings */
const struct cu1216_config *config;
- struct dvb_frontend frontend;
u8 pwm;
u8 reg0;
+
+ u32 AC_uSysClk;
struct dvb_frontend_parameters params;
};
@@ -65,11 +65,6 @@ typedef struct AC_TypeQAM_TAG {
} AC_TypeQAM_T;
-
-
-static u32 AC_uSysClk;
-static u8 li_Iq, li_oldIq = 0, uc_Gain, uc_oldGain = 0;
-
static void cu1216_set_symbolRate(struct dvb_frontend *fe, u16 uFreqSymb);
static void cu1216_set_QAM(struct dvb_frontend *fe, u8 bQAM);
static void cu1216_set_IQ(struct dvb_frontend *fe, u8 bSI);
@@ -93,14 +88,11 @@ static int cu1216_writereg (struct cu121
.len = 2
};
int ret;
-#if 0
- printk("cu1216 write %d: %02x\n", reg, data);
-#endif
ret = i2c_transfer (state->i2c, &msg, 1);
if (ret != 1)
- printk("DVB: TDA10021(%d): %s, writereg error "
+ printk("DVB: TDA10021(%p): %s, writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
+ state, __FUNCTION__, reg, data, ret);
msleep(10);
return (ret != 1) ? -EREMOTEIO : 0;
@@ -639,11 +631,6 @@ static void cu1216_reset(struct dvb_fron
}
*/
-static int cu1216_init_none(struct dvb_frontend *fe)
-{
- return 0;
-}
-
static int cu1216_init(struct dvb_frontend *fe)
{
struct cu1216_state *state = fe->demodulator_priv;
@@ -652,8 +639,8 @@ static int cu1216_init(struct dvb_fronte
s32 lDeltaF;
// calculate the system frequency
- AC_uSysClk = OM5734_XTALFREQ_DEF * (OM5734_PLLMFACTOR_DEF + 1);
- AC_uSysClk /= (OM5734_PLLNFACTOR_DEF + 1) * (OM5734_PLLPFACTOR_DEF + 1);
+ state->AC_uSysClk = OM5734_XTALFREQ_DEF * (OM5734_PLLMFACTOR_DEF + 1);
+ state->AC_uSysClk /= (OM5734_PLLNFACTOR_DEF + 1) * (OM5734_PLLPFACTOR_DEF + 1);
// PLL factors
// bPLL_M_Factor =0x07
@@ -741,11 +728,11 @@ static int cu1216_init(struct dvb_fronte
// set ALGOD and deltaF
//57840000 = OM5734_XTALFREQ_DEF*(OM5734_PLLMFACTOR_DEF+1) / (OM5734_PLLNFACTOR_DEF+1)*(OM5734_PLLPFACTOR_DEF+1)
- lDeltaF = (s32)(AC_uSysClk * 5 / 1000);
+ lDeltaF = (s32)((state->AC_uSysClk) * 5 / 1000);
lDeltaF /= -8;
lDeltaF += (AC_TUNFI_DEF / 1000);
lDeltaF *= 2048;
- lDeltaF /= (s32)(AC_uSysClk / 1000);
+ lDeltaF /= (s32)((state->AC_uSysClk) / 1000);
cu1216_writereg(state, AC_DELTAF1_IND, (u8)lDeltaF);
cu1216_writereg(state, AC_DELTAF2_IND, (u8)(((lDeltaF>>8) & 0x03) | AC_DELTAF2_ALGOD_BIT));
@@ -783,6 +770,16 @@ static int cu1216_init(struct dvb_fronte
return 0;
}
+// no memory allocations. resume after suspend might need reinitialization here!
+static int cu1216_init_none(struct dvb_frontend *fe)
+{
+
+ cu1216_clear_register(fe);
+ cu1216_init(fe);
+
+ return 0;
+}
+
static void delay_ms_interruptible(u32 ms)
{
set_current_state(TASK_INTERRUPTIBLE);
@@ -800,16 +797,19 @@ static int cu1216_set_parameters(struct
{
struct cu1216_state *state = fe->demodulator_priv;
- u8 i;
u8 QamSize = 0;
u32 ErrRate[3];
+ u8 li_Iq, uc_Gain, uc_oldGain = 0;
fe_status_t value;
int status = -EINVAL;
- printk("[%s]:frequency = %d , symbol = %d , qam = %d .\n",
+ if (params == NULL)
+ params = &state->params;
+
+ printk("[%s]:frequency = %d , symbol = %d , qam = %d, inversion = %d .\n",
__func__,
params->frequency , params->u.qam.symbol_rate,
- params->u.qam.modulation);
+ params->u.qam.modulation, params->inversion );
switch (params->u.qam.modulation) {
case QPSK :
@@ -835,9 +835,6 @@ static int cu1216_set_parameters(struct
break;
}
- if (li_oldIq >= 2)
- li_oldIq = 0;
-
// cu1216_reset(fe);
// FIXME ! need to do a Bridge RESET from here
// state->config->fe_reset(fe);
@@ -862,67 +859,65 @@ static int cu1216_set_parameters(struct
//Write QAM
cu1216_set_QAM(fe, QamSize);
- for (i = li_oldIq; i < li_oldIq + 2; i++) {
- li_Iq = i % 2;
+ li_Iq = (params->inversion == INVERSION_ON)? 1:0;
- for (uc_Gain = 1; uc_Gain < 4; uc_Gain++) {
- cu1216_set_IQ(fe, li_Iq);
-
- cu1216_set_gain(fe, uc_Gain);
-
- //udelay(50);
- delay_us_interruptible(5);
-
- if (cu1216_read_status(fe, &value) == 0) {
-
- li_oldIq = li_Iq;
- uc_oldGain = uc_Gain;
- ErrRate[0] = cu1216_read_errRate(fe);
-
- if (uc_Gain < 3) {
- cu1216_set_gain(fe, uc_Gain+1);
- //udelay(50);
- delay_us_interruptible(5);
- ErrRate[1] = cu1216_read_errRate(fe);
-
- if (ErrRate[0] > ErrRate[1]) {
- cu1216_set_gain(fe , uc_Gain);
- //udelay(50);
- delay_us_interruptible(5);
-
- } else {
- uc_oldGain = uc_Gain + 1;
- uc_Gain = uc_Gain + 1;
-
- if (uc_Gain < 3) {
- cu1216_set_gain(fe, uc_Gain + 1);
-
- //udelay(50);
- delay_us_interruptible(5);
- ErrRate[2] = cu1216_read_errRate(fe);
-
- if (ErrRate[1] > ErrRate[2]) {
- cu1216_set_gain(fe , uc_oldGain);
-
- //udelay(50);
- delay_us_interruptible(5);
- } else {
- uc_oldGain = uc_Gain + 1;
- }
- }
- }
- }
- goto ret;
- }
- }
+ for (uc_Gain = 1; uc_Gain < 4; uc_Gain++) {
+ cu1216_set_IQ(fe, li_Iq);
+
+ cu1216_set_gain(fe, uc_Gain);
+
+ //udelay(50);
+ delay_us_interruptible(5);
+
+ if (cu1216_read_status(fe, &value) == 0) {
+
+ uc_oldGain = uc_Gain;
+ ErrRate[0] = cu1216_read_errRate(fe);
+
+ if (uc_Gain < 3) {
+ cu1216_set_gain(fe, uc_Gain+1);
+ //udelay(50);
+ delay_us_interruptible(5);
+ ErrRate[1] = cu1216_read_errRate(fe);
+
+ if (ErrRate[0] > ErrRate[1]) {
+ cu1216_set_gain(fe , uc_Gain);
+
+ //udelay(50);
+ delay_us_interruptible(5);
+ } else {
+ uc_oldGain = uc_Gain + 1;
+ uc_Gain = uc_Gain + 1;
+
+ if (uc_Gain < 3) {
+ cu1216_set_gain(fe, uc_Gain + 1);
+
+ //udelay(50);
+ delay_us_interruptible(5);
+
+ ErrRate[2] = cu1216_read_errRate(fe);
+ if (ErrRate[1] > ErrRate[2]) {
+ cu1216_set_gain(fe , uc_oldGain);
+
+ //udelay(50);
+ delay_us_interruptible(5);
+ } else {
+ uc_oldGain = uc_Gain + 1;
+ }
+ }
+ }
+ }
+ goto ret;
+ }
}
status = -1;
ret:
- state->params = *params;
-
+ if (params != &(state->params))
+ state->params = *params;
+
return status ;
}
@@ -932,13 +927,13 @@ static int cu1216_get_frontend(struct dv
int sync;
s8 afc = 0;
- sync = cu1216_readreg(state, 0x11);
- afc = cu1216_readreg(state, 0x19);
+ sync = cu1216_readreg(state, AC_SYNC_IND);
+ afc = cu1216_readreg(state, AC_VAFC_IND);
if (verbose) {
/* AFC only valid when carrier has been recovered */
- printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
- "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
- state->frontend.dvb->num, afc,
+ printk(sync & 2 ? "DVB: TDA10021(%p): AFC (%d) %dHz\n" :
+ "DVB: TDA10021(%p): [AFC (%d) %dHz]\n",
+ state, afc,
- ((s32)p->u.qam.symbol_rate * afc) >> 10);
}
@@ -968,16 +963,21 @@ static int cu1216_sleep(struct dvb_front
{
struct cu1216_state *state = fe->demodulator_priv;
- cu1216_writereg (state, 0x1b, 0x02); /* pdown ADC */
- cu1216_writereg (state, 0x00, 0x80); /* standby */
+ cu1216_writereg (state, AC_ADC_IND, 0x02); /* pdown ADC */
+ cu1216_writereg (state, AC_CONF_IND, 0x80); /* standby */
return 0;
}
static void cu1216_release(struct dvb_frontend *fe)
{
- struct cu1216_state *state = fe->demodulator_priv;
- kfree(state);
+ struct cu1216_state *state = NULL;
+
+ state = fe->demodulator_priv;
+ fe->demodulator_priv = NULL;
+
+ kfree(state);
+ kfree(fe);
}
static struct dvb_frontend_ops cu1216_ops;
@@ -985,8 +985,14 @@ static struct dvb_frontend_ops cu1216_op
struct dvb_frontend *cu1216_attach(const struct cu1216_config *config,
struct i2c_adapter *i2c)
{
+ struct dvb_frontend *fe = NULL;
struct cu1216_state *state = NULL;
+ /* allocate memory for the frontend */
+ fe = kmalloc(sizeof (struct dvb_frontend), GFP_KERNEL);
+ if (fe == NULL)
+ goto error;
+
/* allocate memory for the internal state */
state = kmalloc(sizeof (struct cu1216_state), GFP_KERNEL);
if (state == NULL)
@@ -995,20 +1001,19 @@ struct dvb_frontend *cu1216_attach(const
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &cu1216_ops, sizeof (struct dvb_frontend_ops));
- //state->pwm = pwm;
- //state->reg0 = cu1216_inittab[0];
+
+ fe->demodulator_priv = state;
+ fe->ops = cu1216_ops;
/* check if the demod is there */
if ((cu1216_readreg(state, 0x1a) & 0xf0) != 0x70)
goto error;
- /* create dvb_frontend */
- state->frontend.ops = state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
+ /* created dvb_frontend */
+ return fe;
error:
+ kfree(fe);
kfree(state);
return NULL;
}
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/Makefile v4l-dvb/linux/drivers/media/dvb/mantis/Makefile
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/Makefile 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/Makefile 2007-08-07 18:18:47.000000000 +0300
@@ -4,4 +4,4 @@ mantis-objs = mantis_core.o mantis_dma.o
obj-$(CONFIG_DVB_MANTIS) += mantis.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_common.h v4l-dvb/linux/drivers/media/dvb/mantis/mantis_common.h
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_common.h 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_common.h 2007-08-07 20:44:17.000000000 +0300
@@ -64,6 +64,7 @@
#define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr)
#define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr)
#define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr)
+#define mmoff(dat, addr) mmwrite(~((u32)(dat)) & mmread(addr), addr)
#define MANTIS_TS_188 0
#define MANTIS_TS_204 1
@@ -94,6 +95,7 @@ struct mantis_pci {
unsigned int num;
/* RISC Core */
+ u8 pm_dma_active;
u32 finished_block;
u32 last_block;
u32 line_bytes;
@@ -119,6 +121,7 @@ struct mantis_pci {
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
struct dvb_net dvbnet;
+ int has_power;
u8 feeds;
@@ -145,4 +148,10 @@ extern int mantis_dvb_exit(struct mantis
extern void mantis_dma_xfer(unsigned long data);
extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
+extern int mantis_dvb_suspend(struct mantis_pci *mantis, pm_message_t prevState, pm_message_t mesg);
+extern void mantis_dvb_resume(struct mantis_pci *mantis, pm_message_t prevMesg);
+
+extern int mantis_dma_suspend(struct mantis_pci *mantis, pm_message_t mesg, int has_dma);
+extern void mantis_dma_resume(struct mantis_pci *mantis, pm_message_t prevMesg, int has_dma);
+
#endif //__MANTIS_COMMON_H
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_core.c v4l-dvb/linux/drivers/media/dvb/mantis/mantis_core.c
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_core.c 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_core.c 2007-08-07 18:42:17.000000000 +0300
@@ -154,12 +154,14 @@ int mantis_core_init(struct mantis_pci *
dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed");
return err;
}
+// TODO: RC init
return 0;
}
int mantis_core_exit(struct mantis_pci *mantis)
{
+// TODO: RC exit
mantis_dma_stop(mantis);
dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping");
if (mantis_dma_exit(mantis) < 0)
@@ -172,22 +174,22 @@ int mantis_core_exit(struct mantis_pci *
return 0;
}
+// Turn the given bit on or off.
void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
{
- u32 reg;
+ u32 currVal;
+ u32 newVal;
- if (value)
- reg = 0x0000;
+ currVal = mmread(MANTIS_GPIF_ADDR);
+
+ if ( value )
+ newVal = currVal | ( 1 << bitpos );
else
- reg = 0xffff;
-
- reg = (value << bitpos);
+ newVal = currVal & ( ~ ( 1 << bitpos ) );
- mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR);
+ mmwrite(newVal, MANTIS_GPIF_ADDR);
mmwrite(0x00, MANTIS_GPIF_DOUT);
udelay(100);
- mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR);
- mmwrite(0x00, MANTIS_GPIF_DOUT);
}
@@ -210,3 +212,24 @@ void mantis_set_direction(struct mantis_
mmwrite(reg, 0x28);
}
}
+
+int mantis_core_suspend(struct mantis_pci *mantis, pm_message_t prevState, pm_message_t mesg)
+{
+ mantis_dvb_suspend(mantis, prevState, mesg);
+ //mantis_rc_suspend(mantis, mesg);
+ mantis_i2c_suspend(mantis, mesg);
+
+ return 0;
+}
+
+int mantis_core_resume(struct mantis_pci *mantis, pm_message_t prevMesg)
+{
+ gpio_set_bits(mantis,13,1);
+ gpio_set_bits(mantis,14,1);
+
+ mantis_i2c_resume(mantis, prevMesg);
+ //mantis_rc_resume(mantis, prevMesg);
+ mantis_dvb_resume(mantis, prevMesg);
+
+ return 0;
+}
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_core.h v4l-dvb/linux/drivers/media/dvb/mantis/mantis_core.h
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_core.h 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_core.h 2007-08-07 18:23:36.000000000 +0300
@@ -58,4 +58,12 @@ extern int mantis_core_exit(struct manti
//extern void mantis_fe_reset(struct dvb_frontend *fe);
extern void mantis_set_direction(struct mantis_pci *mantis, int direction);
+//extern int mantis_rc_suspend(struct mantis_pci *mantis, pm_message_t mesg);
+//extern void mantis_rc_resume(struct mantis_pci *mantis, pm_message_t prevMesg);
+extern int mantis_i2c_suspend(struct mantis_pci *mantis, pm_message_t mesg);
+extern void mantis_i2c_resume(struct mantis_pci *mantis, pm_message_t prevMesg);
+
+extern int mantis_core_suspend(struct mantis_pci *mantis, pm_message_t prevState, pm_message_t mesg);
+extern int mantis_core_resume(struct mantis_pci *mantis, pm_message_t prevMesg);
+
#endif //__MANTIS_CORE_H
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_dma.c v4l-dvb/linux/drivers/media/dvb/mantis/mantis_dma.c
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_dma.c 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_dma.c 2007-08-07 18:03:01.000000000 +0300
@@ -237,3 +237,19 @@ void mantis_dma_xfer(unsigned long data)
mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;
}
}
+
+// suspend to standby, ram or disk.
+int mantis_dma_suspend(struct mantis_pci *mantis, pm_message_t mesg, int has_dma)
+{
+ if (has_dma)
+ mantis_dma_stop(mantis);
+
+ return 0;
+}
+
+// resumes into state D0 always.
+void mantis_dma_resume(struct mantis_pci *mantis, pm_message_t prevMesg, int has_dma)
+{
+ if (has_dma)
+ mantis_dma_start(mantis);
+}
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_dvb.c v4l-dvb/linux/drivers/media/dvb/mantis/mantis_dvb.c
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_dvb.c 2007-08-07 17:38:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_dvb.c 2007-08-07 19:53:32.000000000 +0300
@@ -38,18 +38,18 @@ void mantis_fe_powerup(struct mantis_pci
msleep_interruptible(100);
gpio_set_bits(mantis, 0x0c, 1);
msleep_interruptible(100);
+ mantis->has_power = 1;
}
void mantis_fe_powerdown(struct mantis_pci *mantis)
{
dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF");
gpio_set_bits(mantis, 0x0c, 0);
+ mantis->has_power = 0;
}
-static int mantis_fe_reset(struct dvb_frontend *fe)
+static int mantis_frontend_reset(struct mantis_pci *mantis)
{
- struct mantis_pci *mantis = fe->dvb->priv;
-
dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset");
gpio_set_bits(mantis, 13, 0);
msleep_interruptible(100);
@@ -62,17 +62,35 @@ static int mantis_fe_reset(struct dvb_fr
return 0;
}
-static int mantis_frontend_reset(struct mantis_pci *mantis)
+static int mantis_frontend_tuner_init(struct mantis_pci *mantis)
{
- dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset");
- gpio_set_bits(mantis, 13, 0);
- msleep_interruptible(100);
- gpio_set_bits(mantis, 13, 0);
- msleep_interruptible(100);
- gpio_set_bits(mantis, 13, 1);
- msleep_interruptible(100);
- gpio_set_bits(mantis, 13, 1);
+ mantis_fe_powerdown(mantis);
+ mantis_fe_powerup(mantis);
+ mantis_frontend_reset(mantis);
+
+ return 0;
+}
+
+static int mantis_fe_reset(struct dvb_frontend *fe)
+{
+ struct mantis_pci *mantis = fe->dvb->priv;
+
+ return mantis_frontend_reset(mantis);
+}
+
+static int mantis_dvb_tuner_init(struct dvb_frontend *fe)
+{
+ struct mantis_pci *mantis = fe->dvb->priv;
+ printk("mantis tuner init\n");
+ return mantis_frontend_tuner_init(mantis);
+}
+static int mantis_dvb_tuner_sleep(struct dvb_frontend *fe)
+{
+ struct mantis_pci *mantis = fe->dvb->priv;
+
+ printk("mantis tuner sleep\n");
+ mantis_fe_powerdown(mantis);
return 0;
}
@@ -124,6 +142,7 @@ int __devinit mantis_dvb_init(struct man
int result;
dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter");
+ mantis->has_power = 0;
if (dvb_register_adapter(&mantis->dvb_adapter,
"Mantis dvb adapter", THIS_MODULE,
&mantis->pdev->dev) < 0) {
@@ -214,11 +233,13 @@ int __devinit mantis_frontend_init(struc
switch (mantis->subsystem_device) {
case MANTIS_VP_1033_DVB_S: // VP-1033
dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
- mantis->fe = stv0299_attach(&lgtdqcs001f_config,
+ mantis->fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config,
&mantis->adapter);
if (mantis->fe) {
mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
+ mantis->fe->ops.tuner_ops.sleep = mantis_dvb_tuner_sleep;
+ mantis->fe->ops.tuner_ops.init = mantis_dvb_tuner_init;
dprintk(verbose, MANTIS_ERROR, 1,
"found STV0299 DVB-S frontend @ 0x%02x",
lgtdqcs001f_config.demod_address);
@@ -229,7 +250,7 @@ int __devinit mantis_frontend_init(struc
break;
case MANTIS_VP_1034_DVB_S: // VP-1034
dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
- mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter);
+ mantis->fe = dvb_attach(mb86a16_attach, &vp1034_config, &mantis->adapter);
if (mantis->fe) {
dprintk(verbose, MANTIS_ERROR, 1,
"found MB86A16 DVB-S/DSS frontend @0x%02x",
@@ -239,9 +260,12 @@ int __devinit mantis_frontend_init(struc
break;
case MANTIS_VP_2033_DVB_C: // VP-2033
dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
- mantis->fe = cu1216_attach(&philips_cu1216_config, &mantis->adapter);
+ mantis->fe = dvb_attach(cu1216_attach, &philips_cu1216_config, &mantis->adapter);
if (mantis->fe) {
mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set;
+ mantis->fe->ops.tuner_ops.sleep = mantis_dvb_tuner_sleep;
+ // fe->ops.set_frontend)(mantis->fe, NULL) must not crash on resume!
+ mantis->fe->ops.tuner_ops.init = mantis_dvb_tuner_init;
dprintk(verbose, MANTIS_ERROR, 1,
"found Philips CU1216 DVB-C frontend @ 0x%02x",
philips_cu1216_config.demod_address);
@@ -253,8 +277,18 @@ int __devinit mantis_frontend_init(struc
break;
case MANTIS_VP_3030_DVB_T: // VP-3030
dprintk(verbose, MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
- mantis->fe = zl10353_attach(&mantis_vp3030_config, &mantis->adapter);
+ mantis->fe = dvb_attach(zl10353_attach, &mantis_vp3030_config, &mantis->adapter);
if (mantis->fe) {
+
+#ifdef DVB_PLL_ENV57H1XD5
+ if (dvb_attach(dvb_pll_attach, mantis->fe,
+ 0x60,
+ &mantis->adapter,
+ DVB_PLL_ENV57H1XD5) == NULL) {
+
+ return -EIO;
+ }
+#else
if (dvb_pll_attach(mantis->fe,
0x60,
&mantis->adapter,
@@ -262,6 +296,7 @@ int __devinit mantis_frontend_init(struc
return -EIO;
}
+#endif
dprintk(verbose, MANTIS_ERROR, 1,
"Mantis DVB-T Zarlink 10353 frontend attach success");
}
@@ -307,3 +342,38 @@ int __devexit mantis_dvb_exit(struct man
return 0;
}
+
+// suspend to standby, ram or disk.
+int mantis_dvb_suspend(struct mantis_pci *mantis, pm_message_t prevState, pm_message_t mesg)
+{
+ mantis_dma_suspend(mantis, mesg, (mantis->feeds)? 1:0);
+
+ // tuner: power down. idea is to keep remote control still up.
+ if (mantis->has_power) {
+ printk("mantis tuner sleep\n");
+ mantis_fe_powerdown(mantis);
+ mantis->has_power = 1; // restore power setting for resume.
+ }
+
+ return 0;
+}
+
+void mantis_dvb_resume(struct mantis_pci *mantis, pm_message_t prevMesg)
+{
+ if (mantis->has_power && mantis->fe->ops.tuner_ops.init) {
+ printk("mantis tuner power on\n");
+ (mantis->fe->ops.tuner_ops.init)(mantis->fe);
+
+ if (mantis->fe->ops.init) {
+ printk("mantis ops.init\n");
+ (mantis->fe->ops.init)(mantis->fe);
+ }
+
+ // set_frontend: must support NULL case. mantis->fe->ops.tuner_ops.init is the flag
+ if (mantis->feeds > 0)
+ (mantis->fe->ops.set_frontend)(mantis->fe, NULL);
+
+ }
+
+ mantis_dma_resume(mantis, prevMesg, (mantis->feeds)? 1:0);
+}
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_i2c.c v4l-dvb/linux/drivers/media/dvb/mantis/mantis_i2c.c
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_i2c.c 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_i2c.c 2007-08-07 20:50:21.000000000 +0300
@@ -158,29 +158,53 @@ static struct i2c_adapter mantis_i2c_ada
.algo = &mantis_algo,
};
-int __devinit mantis_i2c_init(struct mantis_pci *mantis)
+static int mantis_add_adapter(struct mantis_pci *mantis)
{
- u32 intstat, intmask;
struct i2c_adapter *i2c_adapter = &mantis->adapter;
struct pci_dev *pdev = mantis->pdev;
+ int i2c_rc;
- mutex_init(&mantis->i2c_lock);
memcpy(i2c_adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter));
i2c_set_adapdata(i2c_adapter, mantis);
i2c_adapter->dev.parent = &pdev->dev;
- mantis->i2c_rc = i2c_add_adapter(i2c_adapter);
- if (mantis->i2c_rc < 0)
- return mantis->i2c_rc;
-
- dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C ..");
-
- intstat = mmread(MANTIS_INT_STAT);
- intmask = mmread(MANTIS_INT_MASK);
- mmwrite(intstat, MANTIS_INT_STAT);
- mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK);
+ mantis->i2c_rc = i2c_rc = i2c_add_adapter(i2c_adapter);
+
+ if (i2c_rc >= 0) {
+ dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C ..");
+
+ mmoff(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+ mmor(MANTIS_INT_I2CDONE, MANTIS_INT_MASK);
- dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", intstat, intmask);
+ }
+
+ if (i2c_rc < 0)
+ return i2c_rc;
+
+ return 0;
+}
+
+static int mantis_del_adapter(struct mantis_pci *mantis)
+{
+ int i2c_rc;
+
+ i2c_rc = i2c_del_adapter(&mantis->adapter);
+
+ mmoff(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+ mmoff(MANTIS_INT_I2CDONE, MANTIS_INT_MASK);
+
+ return i2c_rc;
+}
+
+int __devinit mantis_i2c_init(struct mantis_pci *mantis)
+{
+ int i2c_rc;
+
+ mutex_init(&mantis->i2c_lock);
+
+ i2c_rc = mantis_add_adapter(mantis);
+ if (i2c_rc < 0)
+ return i2c_rc;
return 0;
}
@@ -188,5 +212,21 @@ int __devinit mantis_i2c_init(struct man
int __devexit mantis_i2c_exit(struct mantis_pci *mantis)
{
dprintk(verbose, MANTIS_DEBUG, 1, "Removing I2C adapter");
- return i2c_del_adapter(&mantis->adapter);
+ return mantis_del_adapter(mantis);
+}
+
+// suspend to standby, ram or disk.
+int mantis_i2c_suspend(struct mantis_pci *mantis, pm_message_t mesg)
+{
+ mmoff(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+ mmoff(MANTIS_INT_I2CDONE, MANTIS_INT_MASK);
+
+ return 0;
+}
+
+// resumes into state D0 always.
+void mantis_i2c_resume(struct mantis_pci *mantis, pm_message_t prevMesg)
+{
+ mmoff(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+ mmor(MANTIS_INT_I2CDONE, MANTIS_INT_MASK);
}
diff --exclude=CVS -uprN v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_pci.c v4l-dvb/linux/drivers/media/dvb/mantis/mantis_pci.c
--- v4l-dvb-base/linux/drivers/media/dvb/mantis/mantis_pci.c 2007-08-05 14:12:17.000000000 +0300
+++ v4l-dvb/linux/drivers/media/dvb/mantis/mantis_pci.c 2007-08-07 20:57:21.000000000 +0300
@@ -128,52 +128,21 @@ static irqreturn_t mantis_pci_irq(int ir
return IRQ_HANDLED;
}
-
-static int __devinit mantis_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *mantis_pci_table)
+// This init code is common for both probe and resume
+static int mantis_init_pci(struct pci_dev *pdev, struct mantis_pci *mantis)
{
u8 revision, latency;
- struct mantis_pci *mantis;
- int ret = 0;
-
- mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL);
- if (mantis == NULL) {
- printk("%s: Out of memory\n", __func__);
- ret = -ENOMEM;
- goto err;
- }
- memset(mantis, 0, sizeof (struct mantis_pci));
- mantis->num = devs;
- devs++;
-
- if (pci_enable_device(pdev)) {
- dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed");
- ret = -ENODEV;
- goto err;
- }
- mantis->mantis_addr = pci_resource_start(pdev, 0);
- if (!request_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), DRIVER_NAME)) {
- ret = -ENODEV;
- goto err0;
- }
-
- if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) {
- dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed");
- ret = -ENODEV;
- goto err1;
- }
// Clear and disable all interrupts at startup
// to avoid lockup situations
mmwrite(0x00, MANTIS_INT_MASK);
if (request_irq(pdev->irq, mantis_pci_irq, IRQF_SHARED | IRQF_DISABLED,
- DRIVER_NAME, mantis) < 0) {
+ DRIVER_NAME, mantis) < 0) {
dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed");
- ret = -ENODEV;
- goto err2;
+ return -ENODEV;
}
+
pci_set_master(pdev);
pci_set_drvdata(pdev, mantis);
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
@@ -183,7 +152,6 @@ static int __devinit mantis_pci_probe(st
mantis->pdev = pdev;
mantis->subsystem_vendor = pdev->subsystem_vendor;
mantis->subsystem_device = pdev->subsystem_device;
- init_waitqueue_head(&mantis->i2c_wq);
// CAM bypass
//mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK);
@@ -206,34 +174,71 @@ static int __devinit mantis_pci_probe(st
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32);
dprintk(verbose, MANTIS_ERROR, 0,
- "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n",
- pdev->irq, mantis->latency,
- mantis->mantis_addr, mantis->mantis_mmio);
+ "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n",
+ pdev->irq, mantis->latency,
+ mantis->mantis_addr, mantis->mantis_mmio);
+
+ return 0;
+}
+
+static int __devinit mantis_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *mantis_pci_table)
+{
+ struct mantis_pci *mantis;
+ int ret = 0;
+
+ mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL);
+ if (mantis == NULL) {
+ printk("%s: Out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ memset(mantis, 0, sizeof (struct mantis_pci));
+ mantis->num = devs;
+ devs++;
+
+ if (pci_enable_device(pdev)) {
+ dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ mantis->mantis_addr = pci_resource_start(pdev, 0);
+
+ if (!request_mem_region(mantis->mantis_addr,
+ pci_resource_len(pdev, 0), DRIVER_NAME))
+ goto no_mem_region;
+
+ if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) {
+ dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed");
+ goto no_mmio;
+ }
+
+ if ((ret=mantis_init_pci(pdev, mantis))<0)
+ goto err;
+
+ init_waitqueue_head(&mantis->i2c_wq);
// No more PCI specific stuff !
- if (mantis_core_init(mantis) < 0) {
+ if ((ret = mantis_core_init(mantis)) < 0) {
dprintk(verbose, MANTIS_ERROR, 1, "Mantis core init failed");
- ret = -ENODEV;
- goto err2;
+ goto err;
}
return 0;
// Error conditions ..
-err2:
- dprintk(verbose, MANTIS_DEBUG, 1, "Err: IO Unmap");
- if (mantis->mantis_mmio)
- iounmap(mantis->mantis_mmio);
-err1:
- dprintk(verbose, MANTIS_DEBUG, 1, "Err: Release regions");
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+no_mmio:
+ dprintk(verbose, MANTIS_DEBUG, 1, "Err: no mmio region");
+ release_mem_region(mantis->mantis_addr,
+ pci_resource_len(pdev, 0));
+
+no_mem_region:
+ dprintk(verbose, MANTIS_DEBUG, 1, "Err: no mem region");
pci_disable_device(pdev);
-err0:
+
+err:
dprintk(verbose, MANTIS_DEBUG, 1, "Err: Free");
kfree(mantis);
-err:
- dprintk(verbose, MANTIS_DEBUG, 1, "Err:");
return ret;
}
@@ -247,8 +252,8 @@ static void __devexit mantis_pci_remove(
}
mantis_core_exit(mantis);
dprintk(verbose, MANTIS_ERROR, 1, "Removing -->Mantis irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p",
- pdev->irq, mantis->latency, mantis->mantis_addr,
- mantis->mantis_mmio);
+ pdev->irq, mantis->latency, mantis->mantis_addr,
+ mantis->mantis_mmio);
free_irq(pdev->irq, mantis);
pci_release_regions(pdev);
@@ -260,11 +265,53 @@ static void __devexit mantis_pci_remove(
kfree(mantis);
}
+static int mantis_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ struct mantis_pci *mantis = pci_get_drvdata(pdev);
+
+ mantis_core_suspend(mantis, pdev->dev.power.power_state, mesg);
+
+ /* Disable IRQ */
+ free_irq(pdev->irq, mantis);
+
+ pci_save_state(pdev);
+
+ /* Disable IO/bus master/irq router */
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
+
+ return 0;
+}
+
+static int mantis_pci_resume(struct pci_dev *pdev)
+{
+ struct mantis_pci *mantis = pci_get_drvdata(pdev);
+ int ret = 0;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if (pci_enable_device(pdev)) {
+ dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed");
+ return -ENODEV;
+ }
+
+ if ((ret = mantis_init_pci(pdev, mantis)) < 0)
+ return ret;
+
+ // No more PCI specific stuff !
+ mantis_core_resume(mantis, pdev->dev.power.power_state);
+
+ return 0;
+}
+
static struct pci_driver mantis_pci_driver = {
.name = DRIVER_NAME,
.id_table = mantis_pci_table,
.probe = mantis_pci_probe,
.remove = mantis_pci_remove,
+ .suspend = mantis_pci_suspend,
+ .resume = mantis_pci_resume,
};
static int __devinit mantis_pci_init(void)
_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb