Meizu: use hardware PWM instead of interrupts+GPIO to set the backlight brightness level

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21772 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Bertrik Sikken 2009-07-11 13:43:04 +00:00
parent e976c51df8
commit 306753b1ed

View file

@ -26,55 +26,20 @@
#include "system.h"
/*
Interrupt-driven backlight driver using the PWM mode of a hardware timer.
Backlight driver using the PWM mode of a hardware timer.
Backlight brightness is implemented by configuring one of the timers in
the SoC for PWM mode. In this mode, two interrupts are generated for each
cycle, one at the start of the cycle and another one sometime between the
first interrupt and the start of the next cycle. The backlight is switched
on at the first interrupt and switched off at the second interrupt. This
way, the position in time of the second interrupt determines the duty cycle
and thereby the brightness of the backlight.
The backlight is switched on and off by means of a GPIO pin.
The PWM duty cycle depends exponentially on the configured brightness
level. This makes the brightness curve more linear to the human eye.
*/
void INT_TIMERA(void)
{
unsigned int tacon = TACON;
/* clear interrupts */
TACON = tacon;
/* TA_INT1, start of PWM cycle: enable backlight */
if (tacon & (1 << 17)) {
PDAT0 |= (1 << 2);
}
/* TA_INT0, disable backlight until next cycle */
if (tacon & (1 << 16)) {
PDAT0 &= ~(1 << 2);
}
}
void _backlight_set_brightness(int brightness)
{
static const unsigned char logtable[] = {0, 1, 2, 3, 5, 7, 10, 15, 22, 31, 44, 63, 90, 127, 180, 255};
/* pwm = (sqrt(2)**x)-1, where brightness level x = 0..16 */
static const unsigned char logtable[] =
{0, 1, 2, 3, 5, 7, 10, 15, 22, 31, 44, 63, 90, 127, 180, 255};
if (brightness == MIN_BRIGHTNESS_SETTING) {
/* turn backlight fully off and disable interrupt */
PDAT0 &= ~(1 << 2);
INTMSK &= ~(1 << 5);
}
else if (brightness == MAX_BRIGHTNESS_SETTING) {
/* turn backlight fully on and disable interrupt */
PDAT0 |= (1 << 2);
INTMSK &= ~(1 << 5);
}
else {
/* set PWM width and enable interrupt */
TADATA0 = logtable[brightness];
INTMSK |= (1 << 5);
}
/* set PWM width */
TCDATA0 = 255 - logtable[brightness];
}
void _backlight_on(void)
@ -89,22 +54,22 @@ void _backlight_off(void)
bool _backlight_init(void)
{
/* enable backlight pin as GPIO */
PCON0 = ((PCON0 & ~(3 << 4)) | (1 << 4));
/* enable backlight pin as timer output */
PCON0 = ((PCON0 & ~(3 << 4)) | (2 << 4));
/* enable timer clock */
PWRCON &= ~(1 << 4);
/* configure timer */
TACMD = (1 << 1); /* TA_CLR */
TACMD = (1 << 0); /* TA_EN */
TACON = (1 << 13) | /* TA_INT1_EN */
(1 << 12) | /* TA_INT0_EN */
(1 << 11) | /* TA_START */
(3 << 8) | /* TA_CS = PCLK / 64 */
(1 << 4); /* TA_MODE_SEL = PWM mode */
TADATA1 = 255; /* set PWM period */
TAPRE = 30; /* prescaler */
TCCMD = (1 << 1); /* TC_CLR */
TCCON = (0 << 13) | /* TC_INT1_EN */
(0 << 12) | /* TC_INT0_EN */
(0 << 11) | /* TC_START */
(3 << 8) | /* TC_CS = PCLK / 64 */
(1 << 4); /* TC_MODE_SEL = PWM mode */
TCDATA1 = 255; /* set PWM period */
TCPRE = 30; /* prescaler */
TCCMD = (1 << 0); /* TC_EN */
_backlight_on();