[Gta04-owner] 3.0.8 kernel for Android/Replicant

NeilBrown neilb at suse.de
Tue Dec 4 06:31:12 CET 2012


On Tue, 4 Dec 2012 09:54:58 +1100 NeilBrown <neilb at suse.de> wrote:

> 
> The display problem seems to be caused by the backlight not working.
> I didn't manage to find out why in a quick look, but you can work around it
> for now with:

Actually, go with this instead - it makes the backlight work properly.

Something is going wrong with runtime power management code and old register
values are being 'restored' on top of the new ones.

I'm not sure this is really the perfect fix, but it works and will do.

I also added a couple of other fixes to the pwm code so that e.g. if you set
the brightness to the value that it already is, you will now not get a
flicker.

I haven't looked into the power-down issue at all.
You might have noticed there is a problem with the serial port in that it
will swallow the first keystroke after a pause.  I know what causes this -
it is runtime power management again.  I think if you set the baudrate to
9600 or lower it will work properly.  It can be fixed for real, but I don't
remember exactly how just at the moment.

NeilBrown

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index e807a61..07fbb70 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -328,6 +328,7 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
+	timer->context.tiocp_cfg = l;
 
 	if (!timer->is_early_init)
 		__timer_disable(timer);
@@ -365,6 +366,7 @@ end:
 	/* Match hardware reset default of posted mode */
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
 			OMAP_TIMER_CTRL_POSTED);
+	timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
 
 	if (!timer->is_early_init)
 		__timer_disable(timer);
@@ -587,6 +589,7 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
 	if (!(l & OMAP_TIMER_CTRL_ST)) {
 		l |= OMAP_TIMER_CTRL_ST;
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+		timer->context.tclr = l;
 	}
 	spin_unlock_irqrestore(&timer->lock, flags);
 	return 0;
@@ -613,6 +616,7 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
 	if (l & OMAP_TIMER_CTRL_ST) {
 		l &= ~0x1;
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+		timer->context.tclr = l;
 
 		if (!pdata->needs_manual_reset) {
 			/* Readback to make sure write has completed */
@@ -688,6 +692,8 @@ int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	timer->context.tclr = l;
+	timer->context.tldr = load;
 	__timer_disable(timer);
 	spin_unlock_irqrestore(&timer->lock, flags);
 	return 0;
@@ -717,6 +723,7 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 	if (autoreload) {
 		l |= OMAP_TIMER_CTRL_AR;
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
+		timer->context.tldr = load;
 	} else {
 		l &= ~OMAP_TIMER_CTRL_AR;
 	}
@@ -724,6 +731,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	timer->context.tcrr = load;
+	timer->context.tclr = l;
 	spin_unlock_irqrestore(&timer->lock, flags);
 	return 0;
 }
@@ -747,6 +756,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 		l &= ~OMAP_TIMER_CTRL_CE;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+	timer->context.tclr = l;
+	timer->context.tmar = match;
 	__timer_disable(timer);
 	spin_unlock_irqrestore(&timer->lock, flags);
 	return 0;
@@ -773,6 +784,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 		l |= OMAP_TIMER_CTRL_PT;
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+	timer->context.tclr = l;
 	__timer_disable(timer);
 	spin_unlock_irqrestore(&timer->lock, flags);
 	return 0;
@@ -815,6 +827,8 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
+	timer->context.tier = value;
+	timer->context.twer = value;
 
 	if (!timer->is_early_init)
 		__timer_disable(timer);
@@ -853,6 +867,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 	spin_lock_irqsave(&timer->lock, flags);
 	if (timer->is_early_init || timer->enabled) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
+		timer->context.tisr = value;
 		spin_unlock_irqrestore(&timer->lock, flags);
 		return 0;
 	}
@@ -892,6 +907,7 @@ int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 	spin_lock_irqsave(&timer->lock, flags);
 	if (timer->is_early_init || timer->enabled) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+		timer->context.tcrr = value;
 		spin_unlock_irqrestore(&timer->lock, flags);
 		return 0;
 	}
diff --git a/arch/arm/plat-omap/pwm.c b/arch/arm/plat-omap/pwm.c
index c6d103d..0ca65de 100644
--- a/arch/arm/plat-omap/pwm.c
+++ b/arch/arm/plat-omap/pwm.c
@@ -71,6 +71,7 @@ struct pwm_device {
 	const char						  *label;
 	unsigned int					   use_count;
 	unsigned int					   pwm_id;
+	int				duty_ns, period_ns;
 };
 
 /* Function Prototypes */
@@ -203,6 +204,11 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 			"duty cycle: %d, period %d\n",
 			duty_ns, period_ns);
 
+	if (pwm->duty_ns == duty_ns &&
+	    pwm->period_ns == period_ns)
+		/* No change - don't cause any transients */
+		return 0;
+
 	clk_rate = clk_get_rate(omap_dm_timer_get_fclk(pwm->dm_timer));
 
 	/* Calculate the appropriate load and match values based on the
@@ -218,6 +224,10 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 	 */
 
 	omap_dm_timer_enable(pwm->dm_timer);
+	/* omap_dm_timer_stop does a 'disable', so we do 2 enabled to keep
+	 * it enabled while we do some more settings.
+	 */
+	omap_dm_timer_enable(pwm->dm_timer);
 	omap_dm_timer_stop(pwm->dm_timer);
 
 	omap_dm_timer_set_load(pwm->dm_timer, autoreload, load_value);
@@ -243,7 +253,8 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 	 */
 
 	omap_dm_timer_disable(pwm->dm_timer);
-
+	pwm->duty_ns = duty_ns;
+	pwm->period_ns = period_ns;
 	return status;
 }
 EXPORT_SYMBOL(pwm_config);
@@ -280,7 +291,7 @@ void pwm_disable(struct pwm_device *pwm)
 {
 	omap_dm_timer_enable(pwm->dm_timer);
 	omap_dm_timer_stop(pwm->dm_timer);
-	omap_dm_timer_disable(pwm->dm_timer);
+	/* omap_dm_timer_stop did a disable, so we don't need to */
 }
 EXPORT_SYMBOL(pwm_disable);
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: not available
URL: <http://lists.goldelico.com/pipermail/gta04-owner/attachments/20121204/fbc0cb06/attachment-0001.bin>


More information about the Gta04-owner mailing list