aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2010-04-24 21:04:46 +0200
committerThomas White <taw@bitwiz.org.uk>2010-04-24 21:04:46 +0200
commit9b8c785d585d285df13295c78d1b847d6b3a2f37 (patch)
treeb24b52456c4052bfcafd2eb22a4daaab4b2c04fb
parent41d7c60ae54e843323dbc942b6a8bac02cf2f938 (diff)
JBT6k74 tweaks: Make resolution switch work
Signed-off-by: Thomas White <taw@bitwiz.org.uk>
-rw-r--r--arch/arm/mach-s3c2442/mach-gta02.c4
-rw-r--r--drivers/mfd/glamo/glamo-display.c9
-rw-r--r--drivers/video/backlight/jbt6k74.c121
-rw-r--r--include/linux/jbt6k74.h4
4 files changed, 103 insertions, 35 deletions
diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c
index 581a183d509..3bd9dabf444 100644
--- a/arch/arm/mach-s3c2442/mach-gta02.c
+++ b/arch/arm/mach-s3c2442/mach-gta02.c
@@ -228,7 +228,7 @@ static struct fb_videomode gta02_glamo_modes[] = {
.name = "240x320",
.xres = 240,
.yres = 320,
- .pixclock = 100000,
+ .pixclock = 40816,
.left_margin = 8,
.right_margin = 16,
.upper_margin = 2,
@@ -556,7 +556,7 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
.min_uV = 2000000,
.max_uV = 3300000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(hcldo_consumers),
diff --git a/drivers/mfd/glamo/glamo-display.c b/drivers/mfd/glamo/glamo-display.c
index f57d273f30c..a5519689476 100644
--- a/drivers/mfd/glamo/glamo-display.c
+++ b/drivers/mfd/glamo/glamo-display.c
@@ -307,6 +307,7 @@ static int glamo_crtc_mode_set(struct drm_crtc *crtc,
printk(KERN_WARNING "[glamo-drm] Display is off - "
"enabling it before setting mode.\n");
glamo_lcd_power(gdrm, 1);
+ msleep(500);
}
glamo_lcd_cmd_mode(gdrm, 1);
@@ -355,14 +356,14 @@ static int glamo_crtc_mode_set(struct drm_crtc *crtc,
glamo_lcd_cmd_mode(gdrm, 0);
+ glamo_crtc_mode_set_base(crtc, 0, 0, old_fb);
+
if ( mode->hdisplay == 240 ) {
- jbt6k74_setresolution(JBT_RESOLUTION_QVGA);
+ jbt6k74_finish_resolutionchange(JBT_RESOLUTION_QVGA);
} else {
- jbt6k74_setresolution(JBT_RESOLUTION_VGA);
+ jbt6k74_finish_resolutionchange(JBT_RESOLUTION_VGA);
}
- glamo_crtc_mode_set_base(crtc, 0, 0, old_fb);
-
gcrtc->current_mode = *mode;
gcrtc->current_mode_set = 1;
gcrtc->current_fb = old_fb;
diff --git a/drivers/video/backlight/jbt6k74.c b/drivers/video/backlight/jbt6k74.c
index 40c31f6a0f5..43249ad92eb 100644
--- a/drivers/video/backlight/jbt6k74.c
+++ b/drivers/video/backlight/jbt6k74.c
@@ -104,6 +104,7 @@ enum jbt_register {
static const char *jbt_power_mode_names[] = {
[JBT_POWER_MODE_OFF] = "off",
+ [JBT_POWER_MODE_STANDBY] = "standby",
[JBT_POWER_MODE_NORMAL] = "normal",
};
@@ -148,6 +149,8 @@ static int jbt_reg_write_nodata(struct jbt_info *jbt, uint8_t reg)
else
dev_err(&jbt->spi->dev, "Write failed: %d\n", ret);
+ mdelay(1);
+
return ret;
}
@@ -165,6 +168,8 @@ static int jbt_reg_write(struct jbt_info *jbt, uint8_t reg, uint8_t data)
else
dev_err(&jbt->spi->dev, "Write failed: %d\n", ret);
+ mdelay(1);
+
return ret;
}
@@ -183,6 +188,8 @@ static int jbt_reg_write16(struct jbt_info *jbt, uint8_t reg, uint16_t data)
else
dev_err(&jbt->spi->dev, "Write failed: %d\n", ret);
+ mdelay(1);
+
return ret;
}
@@ -262,7 +269,7 @@ static int jbt_off_to_normal(struct jbt_info *jbt)
gpio_set_value_cansleep(pdata->gpio_reset, 1);
ret = regulator_bulk_enable(ARRAY_SIZE(jbt->supplies), jbt->supplies);
- mdelay(30);
+ mdelay(120);
/* three times command zero */
ret |= jbt_reg_write_nodata(jbt, 0x00);
@@ -334,6 +341,49 @@ static int jbt_normal_to_off(struct jbt_info *jbt)
}
+static int jbt_normal_to_standby(struct jbt_info *jbt)
+{
+ int ret;
+
+ if ( jbt->power_mode != JBT_POWER_MODE_NORMAL ) return 0;
+
+ /* Make sure we are 120 ms after SLEEP_{IN,OUT} */
+ while (time_before(jiffies, jbt->next_sleep)) cpu_relax();
+
+ /* Sleep mode on */
+ ret = jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
+ ret |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8000 | 1 << 3);
+
+ ret |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN);
+ jbt->next_sleep = jiffies + msecs_to_jiffies(150);
+
+ jbt->power_mode = JBT_POWER_MODE_STANDBY;
+
+ return ret ? -EIO : 0;
+}
+
+
+static int jbt_standby_to_normal(struct jbt_info *jbt)
+{
+ int ret;
+
+ if ( jbt->power_mode != JBT_POWER_MODE_STANDBY ) return 0;
+
+ /* Make sure we are 120 ms after SLEEP_{IN,OUT} */
+ while (time_before(jiffies, jbt->next_sleep)) cpu_relax();
+
+ ret = jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
+ jbt->next_sleep = jiffies + msecs_to_jiffies(150);
+
+ ret |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON);
+ ret |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xdff9);
+
+ jbt->power_mode = JBT_POWER_MODE_NORMAL;
+
+ return ret ? -EIO : 0;
+}
+
+
static int jbt6k74_enter_power_mode(struct jbt_info *jbt,
enum jbt_power_mode new_mode)
{
@@ -354,6 +404,9 @@ static int jbt6k74_enter_power_mode(struct jbt_info *jbt,
case JBT_POWER_MODE_NORMAL:
ret = jbt_off_to_normal(jbt);
break;
+ case JBT_POWER_MODE_STANDBY:
+ ret = -EINVAL;
+ break;
}
break;
case JBT_POWER_MODE_NORMAL:
@@ -364,7 +417,14 @@ static int jbt6k74_enter_power_mode(struct jbt_info *jbt,
case JBT_POWER_MODE_OFF:
ret = jbt_normal_to_off(jbt);
break;
+ case JBT_POWER_MODE_STANDBY:
+ ret = -EINVAL;
+ break;
}
+ break;
+ case JBT_POWER_MODE_STANDBY:
+ ret = -EINVAL;
+ break;
}
if (ret == 0) {
@@ -382,29 +442,46 @@ static int jbt6k74_enter_power_mode(struct jbt_info *jbt,
static int jbt6k74_set_resolution(struct jbt_info *jbt,
enum jbt_resolution new_resolution)
{
+ int old_resolution;
int ret = 0;
- enum jbt_resolution old_resolution;
+
+ if ( !jbt ) return -1;
mutex_lock(&jbt->lock);
- if (jbt->resolution == new_resolution)
- goto out_unlock;
+ if ( jbt->resolution == new_resolution ) goto out_unlock;
+ if ( jbt->power_mode == JBT_POWER_MODE_OFF ) goto out_unlock;
old_resolution = jbt->resolution;
jbt->resolution = new_resolution;
- if (jbt->power_mode == JBT_POWER_MODE_NORMAL) {
+ if ( jbt->power_mode == JBT_POWER_MODE_NORMAL ) {
+
+ ret = jbt_normal_to_standby(jbt);
+
+ mdelay(25);
+
+ if (jbt->resolution == JBT_RESOLUTION_VGA) {
+ /* Quad mode off */
+ ret |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00);
+ ret = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80);
+ } else {
+ /* Quad mode on */
+ ret |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22);
+ ret = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81);
+ }
- /* "Reboot" the LCM */
- ret = jbt_normal_to_off(jbt);
- mdelay(1000);
- ret |= jbt_off_to_normal(jbt);
+ mdelay(25);
+
+ ret |= jbt_standby_to_normal(jbt);
if (ret) {
jbt->resolution = old_resolution;
- dev_err(&jbt->spi->dev, "Failed to set resolution '%s')\n",
+ dev_err(&jbt->spi->dev,
+ "Failed to set resolution '%s')\n",
jbt_resolution_names[new_resolution]);
}
+
}
out_unlock:
@@ -737,26 +814,18 @@ static int __devexit jbt_remove(struct spi_device *spi)
return 0;
}
-/* Begin horrible layering violations (in the interest of making stuff work) */
+/* Begin horrible layering violations in the interest of making stuff work */
-int jbt6k74_setresolution(enum jbt_resolution new_resolution)
+int jbt6k74_finish_resolutionchange(enum jbt_resolution new_resolution)
{
- if ( !jbt_global ) {
- printk(KERN_CRIT "JBT not initialised!!!\n");
- return -1;
- }
- jbt6k74_set_resolution(jbt_global, new_resolution);
- return 0;
+ if ( !jbt_global ) return 0;
+ return jbt6k74_set_resolution(jbt_global, new_resolution);
}
-EXPORT_SYMBOL_GPL(jbt6k74_setresolution);
+EXPORT_SYMBOL_GPL(jbt6k74_finish_resolutionchange);
-/* This is utterly, totally horrible. I'm REALLY sorry... */
void jbt6k74_setpower(enum jbt_power_mode new_power)
{
- if ( !jbt_global ) {
- printk(KERN_CRIT "JBT not initialised!!!\n");
- return;
- }
+ if ( !jbt_global ) return;
jbt6k74_enter_power_mode(jbt_global, new_power);
}
EXPORT_SYMBOL_GPL(jbt6k74_setpower);
@@ -770,10 +839,8 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state)
jbt->suspend_mode = jbt->power_mode;
- printk(KERN_CRIT "[jbt] powering off for suspend\n");
jbt6k74_enter_power_mode(jbt, JBT_POWER_MODE_OFF);
- printk(KERN_CRIT "[jbt] done\n");
dev_info(&spi->dev, "suspended\n");
return 0;
@@ -784,13 +851,11 @@ int jbt6k74_resume(struct spi_device *spi)
struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
dev_info(&spi->dev, "starting resume: %d\n", jbt->suspend_mode);
- printk(KERN_CRIT "[jbt] powering on for resume\n");
mdelay(20);
jbt->suspended = 0;
jbt6k74_enter_power_mode(jbt, jbt->suspend_mode);
- printk(KERN_CRIT "[jbt] done\n");
dev_info(&spi->dev, "resumed: %d\n", jbt->suspend_mode);
return 0;
diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h
index f430e5a363a..2010bdcd4f7 100644
--- a/include/linux/jbt6k74.h
+++ b/include/linux/jbt6k74.h
@@ -10,11 +10,13 @@ enum jbt_resolution {
enum jbt_power_mode {
JBT_POWER_MODE_OFF,
+ JBT_POWER_MODE_STANDBY,
JBT_POWER_MODE_NORMAL,
};
extern void jbt6k74_setpower(enum jbt_power_mode new_power);
-extern int jbt6k74_setresolution(enum jbt_resolution new_resolution);
+extern int jbt6k74_prepare_resolutionchange(enum jbt_resolution new_resolution);
+extern int jbt6k74_finish_resolutionchange(enum jbt_resolution new_resolution);
/*