Re: Suspend/resume for Mantis 2033 driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux