Index: drivers/dahdi/wctdm.c
===================================================================
--- drivers/dahdi/wctdm.c	(revision 7109)
+++ drivers/dahdi/wctdm.c	(working copy)
@@ -55,7 +55,7 @@
   0x07 : 41mA
 */
 static int loopcurrent = 20;
-#define POLARITY_XOR(card) ((reversepolarity!=0) ^ (wc->mod[(card)].fxs.reversepolarity!=0) ^ (wc->mod[(card)].fxs.vmwi_lrev!=0))
+#define POLARITY_XOR ((reversepolarity!=0) ^ (fxs->reversepolarity!=0) ^ (fxs->vmwi_lrev!=0) ^ ((fxs->vmwisetting.vmwi_type & DAHDI_VMWI_HVAC)!=0))
 
 static int reversepolarity = 0;
 
@@ -244,6 +244,7 @@
 			int vmwi_lrev:1;		/* MWI Line Reversal*/
 			int vmwi_hvdc:1;		/* MWI High Voltage DC Idle line */
 			int vmwi_hvac:1;		/* MWI Neon High Voltage AC Idle line */
+			int neonringing:1;              /* Ring Generator is set for NEON */
 			struct calregs calregs;
 		} fxs;
 	} mod[NUM_CARDS];
@@ -301,6 +302,8 @@
 static int fxsrxgain = 0;
 
 static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
+static int wctdm_init_ring_generator_mode(struct wctdm *wc, int card);
+static int wctdm_set_ring_generator_mode(struct wctdm *wc, int card, int mode);
 
 static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char ints)
 {
@@ -1024,7 +1027,7 @@
 					/* just detected OffHook, during
 					 * Ringing or OnHookTransfer */
 					fxs->idletxhookstate =
-						POLARITY_XOR(card) ?
+						POLARITY_XOR ?
 							SLIC_LF_ACTIVE_REV :
 							SLIC_LF_ACTIVE_FWD;
 					break;
@@ -1079,7 +1082,7 @@
 		if (wc->cardflag & (1 << x) &&
 		    (wc->modtype[x] == MOD_TYPE_FXS)) {
 			struct fxs *const fxs = &wc->mod[x].fxs;
-			if (fxs->lasttxhook == SLIC_LF_RINGING) {
+			if (fxs->lasttxhook == SLIC_LF_RINGING && !fxs->neonringing) {
 				/* RINGing, prepare for OHT */
 				fxs->ohttimer = OHT_TIMER << 3;
 
@@ -1090,28 +1093,33 @@
 				 */
 
 				/* OHT mode when idle */
-				fxs->idletxhookstate = POLARITY_XOR(x) ?
+				fxs->idletxhookstate = POLARITY_XOR ?
 							SLIC_LF_OHTRAN_REV :
 							SLIC_LF_OHTRAN_FWD;
 			} else if (fxs->ohttimer) {
-				fxs->ohttimer -= DAHDI_CHUNKSIZE;
-				if (fxs->ohttimer)
-					continue;
-
-				/* Switch to Active : Reverse Forward */
-				fxs->idletxhookstate = POLARITY_XOR(x) ?
-							SLIC_LF_ACTIVE_REV :
-							SLIC_LF_ACTIVE_FWD;
-
-				if ((fxs->lasttxhook == SLIC_LF_OHTRAN_FWD) ||
-				    (fxs->lasttxhook == SLIC_LF_OHTRAN_REV)) {
-					/* Apply the change if appropriate */
-					fxs->lasttxhook = POLARITY_XOR(x) ?
-							   SLIC_LF_ACTIVE_REV :
-							   SLIC_LF_ACTIVE_FWD;
-
-					wctdm_setreg(wc, x, 64,
-						     fxs->lasttxhook);
+				/* check if still OnHook */
+				if (!fxs->oldrxhook){
+					fxs->ohttimer-= DAHDI_CHUNKSIZE;
+					if (!fxs->ohttimer) {
+						fxs->idletxhookstate = POLARITY_XOR ? SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD; /* Switch to Active, Rev or Fwd */
+						/* if currently OHT */
+						if ((fxs->lasttxhook == SLIC_LF_OHTRAN_FWD) || (fxs->lasttxhook == SLIC_LF_OHTRAN_REV)) {
+							if (fxs->vmwi_hvac){
+								/* force idle polarity Forward if ringing */
+								fxs->idletxhookstate = SLIC_LF_ACTIVE_FWD;
+								/* Set ring generator for neon */
+								wctdm_set_ring_generator_mode(wc, x, 1);
+								fxs->lasttxhook = SLIC_LF_RINGING;
+							} else {
+								fxs->lasttxhook = fxs->idletxhookstate;
+							}
+							/* Apply the change as appropriate */
+							wctdm_setreg(wc, x, LINE_STATE, fxs->lasttxhook);
+						}
+					}
+				} else {
+					fxs->ohttimer = 0;
+					fxs->idletxhookstate = POLARITY_XOR ? SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD; /* Switch to Active, Rev or Fwd */
 				}
 			}
 		}
@@ -1136,7 +1144,7 @@
 			case 8:
 				/* Read second shadow reg */
 				if (wc->modtype[x] == MOD_TYPE_FXS)
-					wc->reg1shadow[x] = wctdm_getreg(wc, x, 64);
+					wc->reg1shadow[x] = wctdm_getreg(wc, x, LINE_STATE);
 				else if (wc->modtype[x] == MOD_TYPE_FXO)
 					wc->reg1shadow[x] = wctdm_getreg(wc, x, 29);
 				break;
@@ -1500,41 +1508,64 @@
 static int set_vmwi(struct wctdm * wc, int chan_idx)
 {
 	struct fxs *const fxs = &wc->mod[chan_idx].fxs;
-	if (wc->mod[chan_idx].fxs.vmwi_active_messages){
-		wc->mod[chan_idx].fxs.vmwi_lrev = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV)?1:0;
-		wc->mod[chan_idx].fxs.vmwi_hvdc = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVDC)?1:0;
-		wc->mod[chan_idx].fxs.vmwi_hvac = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVAC)?1:0;
+	if (fxs->vmwi_active_messages){
+		fxs->vmwi_lrev = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV)?1:0;
+		fxs->vmwi_hvdc = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVDC)?1:0;
+		fxs->vmwi_hvac = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVAC)?1:0;
 	} else {
-		wc->mod[chan_idx].fxs.vmwi_lrev = 0;
-		wc->mod[chan_idx].fxs.vmwi_hvdc = 0;
-		wc->mod[chan_idx].fxs.vmwi_hvac = 0;
+		fxs->vmwi_lrev = 0;
+		fxs->vmwi_hvdc = 0;
+		fxs->vmwi_hvac = 0;
 	}
 
 	if (debug) {
 		printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d, hvdc=%d, hvac=%d\n",
-			   chan_idx,
-	  wc->mod[chan_idx].fxs.vmwi_active_messages,
-   wc->mod[chan_idx].fxs.vmwi_lrev,
-   wc->mod[chan_idx].fxs.vmwi_hvdc,
-   wc->mod[chan_idx].fxs.vmwi_hvac
+				chan_idx,
+				wc->mod[chan_idx].fxs.vmwi_active_messages,
+				wc->mod[chan_idx].fxs.vmwi_lrev,
+				wc->mod[chan_idx].fxs.vmwi_hvdc,
+				wc->mod[chan_idx].fxs.vmwi_hvac
 			  );
 	}
-	if (POLARITY_XOR(chan_idx)) {
-		wc->mod[chan_idx].fxs.idletxhookstate |= SLIC_LF_REVMASK;
-		/* Do not set while currently ringing or open */
-		if ((fxs->lasttxhook != SLIC_LF_RINGING) &&
-		    (fxs->lasttxhook != SLIC_LF_OPEN)) {
+	if (wc->mod[chan_idx].fxs.vmwi_hvac){
+		/* Can't change ring generator while On Hook Transfer might be happening */
+		if (!wc->mod[chan_idx].fxs.ohttimer) {
+			if (POLARITY_XOR) {
+				fxs->idletxhookstate |= SLIC_LF_REVMASK;
+			} else {
+				fxs->idletxhookstate &= ~SLIC_LF_REVMASK;
+			}
+			wctdm_set_ring_generator_mode(wc, chan_idx, 1);	/* Set ring generator for neon */
+			fxs->lasttxhook = SLIC_LF_RINGING;  	/* Activate ring to send neon pulses */
+			wctdm_setreg(wc, chan_idx, LINE_STATE, fxs->lasttxhook);
+		}
+	}else{
+		if (fxs->neonringing){
+			wctdm_set_ring_generator_mode(wc, chan_idx, 0);	/* Set ring generator for normal ringer */
+			fxs->lasttxhook = SLIC_LF_ACTIVE_FWD;		/* ACTIVE, polarity determined later */
+		} else {
+			/* Can't change polarity while ringing or when open, set idlehookstate instead */
+			if ((wc->mod[chan_idx].fxs.lasttxhook == SLIC_LF_RINGING) || (wc->mod[chan_idx].fxs.lasttxhook == SLIC_LF_OPEN)){
+				if (POLARITY_XOR) {
+					wc->mod[chan_idx].fxs.idletxhookstate |= SLIC_LF_REVMASK;
+				} else {
+					wc->mod[chan_idx].fxs.idletxhookstate &= ~SLIC_LF_REVMASK;
+				}
+				printk(KERN_DEBUG "Unable to change polarity on channel %d, lasttxhook=0x%X\n",
+					chan_idx,
+					fxs->lasttxhook
+				);
+				return 0;
+			}
+		}
+		if (POLARITY_XOR) {
+			fxs->idletxhookstate |= SLIC_LF_REVMASK;
 			fxs->lasttxhook |= SLIC_LF_REVMASK;
-			wctdm_setreg(wc, chan_idx, 64, fxs->lasttxhook);
+		} else {
+			fxs->idletxhookstate &= ~SLIC_LF_REVMASK;
+			fxs->lasttxhook &= ~SLIC_LF_REVMASK;
 		}
-	} else {
-		wc->mod[chan_idx].fxs.idletxhookstate &= ~SLIC_LF_REVMASK;
-		/* Do not set while currently ringing or open */
-		if ((fxs->lasttxhook != SLIC_LF_RINGING) &&
-		    (fxs->lasttxhook != SLIC_LF_OPEN)) {
-			wc->mod[chan_idx].fxs.lasttxhook &= ~SLIC_LF_REVMASK;
-			wctdm_setreg(wc, chan_idx, 64, wc->mod[chan_idx].fxs.lasttxhook);
-		}
+		wctdm_setreg(wc, chan_idx, LINE_STATE, wc->mod[chan_idx].fxs.lasttxhook);
 	}
 	return 0;
 }
@@ -1651,23 +1682,24 @@
 	unsigned char r19,r9;
 	int x;
 	int fxsmode=0;
+	struct fxs *const fxs = &wc->mod[card].fxs;
 
 	/* Sanity check the ProSLIC */
 	if (!sane && wctdm_proslic_insane(wc, card))
 		return -2;
 	
 	/* default messages to none and method to FSK */
-	memset(&wc->mod[card].fxs.vmwisetting, 0, sizeof(wc->mod[card].fxs.vmwisetting));
-	wc->mod[card].fxs.vmwi_lrev = 0;
-	wc->mod[card].fxs.vmwi_hvdc = 0;
-	wc->mod[card].fxs.vmwi_hvac = 0;
+	memset(&fxs->vmwisetting, 0, sizeof(fxs->vmwisetting));
+	fxs->vmwi_lrev = 0;
+	fxs->vmwi_hvdc = 0;
+	fxs->vmwi_hvac = 0;
 	
 				
 	/* By default, don't send on hook */
-	if (!reversepolarity != !wc->mod[card].fxs.reversepolarity)
-		wc->mod[card].fxs.idletxhookstate = SLIC_LF_ACTIVE_REV;
+	if (!reversepolarity != !fxs->reversepolarity)
+		fxs->idletxhookstate = SLIC_LF_ACTIVE_REV;
 	else
-		wc->mod[card].fxs.idletxhookstate = SLIC_LF_ACTIVE_FWD;
+		fxs->idletxhookstate = SLIC_LF_ACTIVE_FWD;
 
 	if (sane) {
 		/* Make sure we turn off the DC->DC converter to prevent anything from blowing up */
@@ -1752,13 +1784,13 @@
 
 		/* Save calibration vectors */
 		for (x=0;x<NUM_CAL_REGS;x++)
-			wc->mod[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x);
+			fxs->calregs.vals[x] = wctdm_getreg(wc, card, 96 + x);
 #endif
 
 	} else {
 		/* Restore calibration registers */
 		for (x=0;x<NUM_CAL_REGS;x++)
-			wctdm_setreg(wc, card, 96 + x, wc->mod[card].fxs.calregs.vals[x]);
+			wctdm_setreg(wc, card, 96 + x, fxs->calregs.vals[x]);
 	}
 	/* Calibration complete, restore original values */
 	for (x=0;x<5;x++) {
@@ -1800,10 +1832,6 @@
 	if (fxshonormode) {
 		fxsmode = acim2tiss[fxo_modes[_opermode].acim];
 		wctdm_setreg(wc, card, 10, 0x08 | fxsmode);
-		if (fxo_modes[_opermode].ring_osc)
-			wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc);
-		if (fxo_modes[_opermode].ring_x)
-			wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x);
 	}
     if (lowpower)
     	wctdm_setreg(wc, card, 72, 0x10);
@@ -1821,35 +1849,8 @@
     wctdm_setreg(wc, card, 64, 0x0);
     wctdm_setreg(wc, card, 1, 0x08);
 #endif
-
-	if (fastringer) {
-		/* Speed up Ringer */
-		wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d);
-		wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9);
-		/* Beef up Ringing voltage to 89V */
-		if (boostringer) {
-			wctdm_setreg(wc, card, 74, 0x3f);
-			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) 
-				return -1;
-			printk(KERN_INFO "Boosting fast ringer on slot %d (89V peak)\n", card + 1);
-		} else if (lowpower) {
-			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) 
-				return -1;
-			printk(KERN_INFO "Reducing fast ring power on slot %d (50V peak)\n", card + 1);
-		} else
-			printk(KERN_INFO "Speeding up ringer on slot %d (25Hz)\n", card + 1);
-	} else {
-		/* Beef up Ringing voltage to 89V */
-		if (boostringer) {
-			wctdm_setreg(wc, card, 74, 0x3f);
-			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) 
-				return -1;
-			printk(KERN_INFO "Boosting ringer on slot %d (89V peak)\n", card + 1);
-		} else if (lowpower) {
-			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) 
-				return -1;
-			printk(KERN_INFO "Reducing ring power on slot %d (50V peak)\n", card + 1);
-		}
+	if (wctdm_init_ring_generator_mode(wc, card)){
+		return -1;
 	}
 
 	if(fxstxgain || fxsrxgain) {
@@ -1883,8 +1884,8 @@
 	if(debug)
 			printk(KERN_DEBUG "DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
 
-	wc->mod[card].fxs.lasttxhook = wc->mod[card].fxs.idletxhookstate;
-	wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook);
+	fxs->lasttxhook = fxs->idletxhookstate;
+	wctdm_setreg(wc, card, LINE_STATE, fxs->lasttxhook);
 	return 0;
 }
 
@@ -1904,43 +1905,41 @@
 			return -EINVAL;
 		if (get_user(x, (__user int *) data))
 			return -EFAULT;
-		wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3;
+		fxs->ohttimer = x << 3;
 
-		/* Active mode when idle */
-		fxs->idletxhookstate = POLARITY_XOR(chan->chanpos - 1) ?
-					SLIC_LF_ACTIVE_REV :
-					SLIC_LF_ACTIVE_FWD;
-
-		if ((fxs->lasttxhook == SLIC_LF_ACTIVE_FWD) ||
-		    (fxs->lasttxhook == SLIC_LF_ACTIVE_REV)) {
-			/* Apply the change if appropriate */
-			fxs->lasttxhook = POLARITY_XOR(chan->chanpos - 1) ?
-						SLIC_LF_OHTRAN_REV :
-						SLIC_LF_OHTRAN_FWD;
-			wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
+		/* OHT mode when idle */
+		fxs->idletxhookstate = POLARITY_XOR ? SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD;
+		if (fxs->neonringing) {
+			/* keep same Forward polarity */
+			fxs->lasttxhook = SLIC_LF_OHTRAN_FWD;
+			wctdm_setreg(wc, chan->chanpos - 1, LINE_STATE, fxs->lasttxhook);
+		} else {
+			if (fxs->lasttxhook == SLIC_LF_ACTIVE_FWD || fxs->lasttxhook == SLIC_LF_ACTIVE_REV) {
+				/* Apply the change if appropriate */
+				fxs->lasttxhook = POLARITY_XOR ? SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD;
+				wctdm_setreg(wc, chan->chanpos - 1, LINE_STATE, fxs->lasttxhook);
+			}
 		}
-		break;
 	case DAHDI_SETPOLARITY:
+		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
+			return -EINVAL;
 		if (get_user(x, (__user int *) data))
 			return -EFAULT;
-		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
-			return -EINVAL;
 		/* Can't change polarity while ringing or when open */
-		if ((fxs->lasttxhook == SLIC_LF_RINGING) ||
-		    (fxs->lasttxhook == SLIC_LF_OPEN))
+		if ((wc->mod[chan->chanpos - 1 ].fxs.lasttxhook == SLIC_LF_RINGING) ||
+		    (wc->mod[chan->chanpos - 1 ].fxs.lasttxhook == SLIC_LF_OPEN))
 			return -EINVAL;
-		
-		wc->mod[chan->chanpos - 1].fxs.reversepolarity = x;
-		if ( POLARITY_XOR(chan->chanpos - 1) )
+		fxs->reversepolarity = x;
+		if ( POLARITY_XOR )
 			fxs->lasttxhook |= SLIC_LF_REVMASK;
 		else
 			fxs->lasttxhook &= ~SLIC_LF_REVMASK;
-		wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
+		wctdm_setreg(wc, chan->chanpos - 1, LINE_STATE, fxs->lasttxhook);
 		break;
 	case DAHDI_VMWI_CONFIG:
 		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
 			return -EINVAL;
-		if (copy_from_user(&(wc->mod[chan->chanpos - 1].fxs.vmwisetting), (__user void *) data, sizeof(wc->mod[chan->chanpos - 1].fxs.vmwisetting)))
+		if (copy_from_user(&(fxs->vmwisetting), (__user void *) data, sizeof(fxs->vmwisetting)))
 			return -EFAULT;
 		set_vmwi(wc, chan->chanpos - 1);
 		break;
@@ -1951,7 +1950,7 @@
 			return -EFAULT;
 		if (0 > x)
 			return -EFAULT;
-		wc->mod[chan->chanpos - 1].fxs.vmwi_active_messages = x;
+		fxs->vmwi_active_messages = x;
 		set_vmwi(wc, chan->chanpos - 1);
 		break;
 	case WCTDM_GET_STATS:
@@ -2061,13 +2060,14 @@
 static int wctdm_close(struct dahdi_chan *chan)
 {
 	struct wctdm *wc = chan->pvt;
+	struct fxs *const fxs = &wc->mod[chan->chanpos - 1].fxs;
 	wc->usecount--;
 	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
 		int idlehookstate;
-		idlehookstate = POLARITY_XOR(chan->chanpos - 1) ?
+		idlehookstate = POLARITY_XOR ?
 						SLIC_LF_ACTIVE_REV :
 						SLIC_LF_ACTIVE_FWD;
-		wc->mod[chan->chanpos - 1].fxs.idletxhookstate = idlehookstate;
+		fxs->idletxhookstate = idlehookstate;
 	}
 	/* If we're dead, release us now */
 	if (!wc->usecount && wc->dead) 
@@ -2075,10 +2075,118 @@
 	return 0;
 }
 
+static int wctdm_init_ring_generator_mode(struct wctdm *wc, int card)
+{
+	wctdm_setreg(wc, card, 34, 0x00);			/* Ringing Osc. Control */
+	
+								/* neon trapezoid timers */
+	wctdm_setreg(wc, card, 48, 0xe0);			/* Active Timer low byte */
+	wctdm_setreg(wc, card, 49, 0x01);			/* Active Timer high byte */
+	wctdm_setreg(wc, card, 50, 0xF0);			/* Inactive Timer low byte */
+	wctdm_setreg(wc, card, 51, 0x05);			/* Inactive Timer high byte */
+
+	wctdm_set_ring_generator_mode(wc, card, 0);
+
+	return 0;
+}
+
+static int wctdm_set_ring_generator_mode(struct wctdm *wc, int card, int mode)
+{
+	int reg20,reg21,reg74; /* RCO, RNGX, VBATH */
+	struct fxs *const fxs = &wc->mod[card].fxs;
+
+	fxs->neonringing = mode;	/* track ring generator mode */
+
+	if (mode) { /* Neon */
+		if (debug)
+			printk(KERN_DEBUG "NEON ring on channel %d, lasttxhook was 0x%x\n", card, fxs->lasttxhook);
+		fxs->lasttxhook = 0x1;			/* Must be in FORWARD ACTIVE before setting ringer */
+		wctdm_setreg(wc, card, LINE_STATE, fxs->lasttxhook);
+
+		wctdm_proslic_setreg_indirect(wc, card, 22, 0x03e8);	/* RNGY (4 HZ) */
+		wctdm_proslic_setreg_indirect(wc, card, 21, 0x7bef);	/* RNGX (91.5Vpk) */
+		wctdm_proslic_setreg_indirect(wc, card, 20, 0x009f);	/* RCO (RNGX, t rise) */
+
+		wctdm_setreg(wc, card, 34, 0x19);			/* Ringing Osc. Control */
+		wctdm_setreg(wc, card, 74, 0x3f);			/* VBATH 94.5V */
+		wctdm_proslic_setreg_indirect(wc, card, 29, 0x4600);	/* RPTP */
+		/* A write of 0x04 to register 64 will turn on the VM led */
+	} else {
+		wctdm_setreg(wc, card, 34, 0x00);			/* Ringing Osc. Control */
+
+		wctdm_proslic_setreg_indirect(wc, card, 22, 0x0000);	/* RNGY Initial Phase */
+		wctdm_proslic_setreg_indirect(wc, card, 29, 0x3600);    /* RPTP */
+		/* A write of 0x04 to register 64 will turn on the ringer */
+
+		if (fastringer) {
+			/* Speed up Ringer */
+			reg20 =  0x7e6d;
+						
+			reg74 = 0x32;	/* Default */
+			/* Beef up Ringing voltage to 89V */
+			if (boostringer) {
+				reg74 = 0x3f;
+				reg21 = 0x0247;	/* RNGX */
+				if (debug)
+					printk(KERN_DEBUG "Boosting fast ringer on channel %d (89V peak)\n", card);
+			} else if (lowpower) {
+				reg21 = 0x014b;	/* RNGX */
+				if (debug)
+					printk(KERN_DEBUG "Reducing fast ring power on channel %d (50V peak)\n", card);
+			} else if (fxshonormode && fxo_modes[_opermode].ring_x) {
+				reg21 = fxo_modes[_opermode].ring_x;
+				if (debug)
+					printk(KERN_DEBUG "fxshonormode: fast ring_x power on channel %d\n", card);
+			} else {
+				reg21 = 0x01b9;
+				if (debug)
+					printk(KERN_DEBUG "Speeding up ringer on channel %d (25Hz)\n", card);
+			}
+			wctdm_setreg(wc, card, 74, reg74); /* VBATH */
+			wctdm_proslic_setreg_indirect(wc, card, 20, reg20);  /* RCO */
+			wctdm_proslic_setreg_indirect(wc, card, 21, reg21);  /* RNGX */
+
+		} else {
+			/* Ringer Speed */
+			if (fxshonormode && fxo_modes[_opermode].ring_osc){
+				reg20 = fxo_modes[_opermode].ring_osc;
+				if (debug)
+					printk(KERN_DEBUG "fxshonormode: ring_osc speed on channel %d\n", card);
+			} else {
+				reg20 = 0x7ef0;	/* Default */
+			}
+
+			reg74 = 0x32;	/* Default */
+			/* Beef up Ringing voltage to 89V */
+			if (boostringer) {
+				reg74 = 0x3f;
+				reg21 = 0x1d1;
+				if (debug)
+					printk(KERN_DEBUG "Boosting ringer on channel %d (89V peak)\n", card);
+			} else if (lowpower) {
+				reg21 = 0x108; 
+				if (debug)
+					printk(KERN_DEBUG "Reducing ring power on channel %d (50V peak)\n", card);
+			} else if (fxshonormode && fxo_modes[_opermode].ring_x) {
+				reg21 = fxo_modes[_opermode].ring_x;
+				if (debug)
+					printk(KERN_DEBUG "fxshonormode: ring_x power on channel %d\n", card);
+			} else {
+				reg21 = 0x160;
+				if (debug)
+					printk(KERN_DEBUG "Normal ring power on channel %d\n", card);
+			}
+			wctdm_setreg(wc, card, 74, reg74); /* VBATH */
+			wctdm_proslic_setreg_indirect(wc, card, 20, reg20);  /* RCO */
+			wctdm_proslic_setreg_indirect(wc, card, 21, reg21);  /* RNGX */
+		}
+	}
+	return 0;
+}
+
 static int wctdm_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
 {
 	struct wctdm *wc = chan->pvt;
-
 	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
 		/* XXX Enable hooksig for FXO XXX */
 		switch(txsig) {
@@ -2101,9 +2209,14 @@
 			switch(chan->sig) {
 			case DAHDI_SIG_FXOKS:
 			case DAHDI_SIG_FXOLS:
-				fxs->lasttxhook = fxs->vmwi_hvac ?
-							SLIC_LF_RINGING :
-							fxs->idletxhookstate;
+				/* Can't change Ring Generator during OHT */
+				if (!fxs->ohttimer){
+					wctdm_set_ring_generator_mode(wc, chan->chanpos - 1, fxs->vmwi_hvac);
+					fxs->lasttxhook = fxs->vmwi_hvac ?
+									SLIC_LF_RINGING : fxs->idletxhookstate;
+				}else{
+					fxs->lasttxhook = fxs->idletxhookstate;
+				}
 				break;
 			case DAHDI_SIG_EM:
 				fxs->lasttxhook = fxs->idletxhookstate;
@@ -2124,6 +2237,7 @@
 			}
 			break;
 		case DAHDI_TXSIG_START:
+			wctdm_set_ring_generator_mode(wc, chan->chanpos - 1, 0); /* Set ringer mode */
 			fxs->lasttxhook = SLIC_LF_RINGING;
 			break;
 		case DAHDI_TXSIG_KEWL:
@@ -2138,9 +2252,7 @@
 			       txsig, fxs->lasttxhook);
 		}
 
-#if 1
 		wctdm_setreg(wc, chan->chanpos - 1, 64, fxs->lasttxhook);
-#endif
 	}
 	return 0;
 }
