diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1173-add-use-pcf50633-resume-callback-jbt6k74.patch.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.24/1173-add-use-pcf50633-resume-callback-jbt6k74.patch.patch | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1173-add-use-pcf50633-resume-callback-jbt6k74.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1173-add-use-pcf50633-resume-callback-jbt6k74.patch.patch new file mode 100644 index 0000000000..9171612b15 --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.24/1173-add-use-pcf50633-resume-callback-jbt6k74.patch.patch @@ -0,0 +1,438 @@ +From de64d8449b10dc39eebdee6bc01409cd0197e38a Mon Sep 17 00:00:00 2001 +From: Andy Green <andy@openmoko.com> +Date: Wed, 2 Jul 2008 22:38:15 +0100 +Subject: [PATCH] add-use-pcf50633-resume-callback-jbt6k74.patch + +Adds the resume callback stuff to glamo, then changes +jbt6k74 to no longer use a sleeping workqueue, but to +make its resume actions dependent on pcf50633 and +glamo resume (for backlight and communication to LCM +respectively) + +Signed-off-by: Andy Green <andy@openmoko.com> +--- + arch/arm/mach-s3c2440/mach-gta02.c | 39 ++++++++++++++++++++- + drivers/i2c/chips/pcf50633.c | 17 +++------ + drivers/mfd/glamo/glamo-core.c | 16 ++++++++ + drivers/mfd/glamo/glamo-core.h | 3 +- + drivers/video/display/jbt6k74.c | 67 +++++++++++++++++++----------------- + include/linux/glamofb.h | 3 ++ + include/linux/jbt6k74.h | 4 ++ + include/linux/pcf50633.h | 2 +- + include/linux/resume-dependency.h | 10 +++--- + 9 files changed, 108 insertions(+), 53 deletions(-) + +diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c +index d7882ea..9ba1036 100644 +--- a/arch/arm/mach-s3c2440/mach-gta02.c ++++ b/arch/arm/mach-s3c2440/mach-gta02.c +@@ -88,6 +88,12 @@ + /* arbitrates which sensor IRQ owns the shared SPI bus */ + static spinlock_t motion_irq_lock; + ++/* the dependency of jbt / LCM on pcf50633 resume */ ++struct resume_dependency resume_dep_jbt_pcf; ++/* the dependency of jbt / LCM on glamo resume */ ++struct resume_dependency resume_dep_jbt_glamo; ++ ++ + /* define FIQ IPC struct */ + /* + * contains stuff FIQ ISR modifies and normal kernel code can see and use +@@ -857,21 +863,50 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = { + + /* SPI: LCM control interface attached to Glamo3362 */ + +-void gta02_jbt6k74_reset(int devidx, int level) ++static void gta02_jbt6k74_reset(int devidx, int level) + { + glamo_lcm_reset(level); + } + + /* finally bring up deferred backlight resume now LCM is resumed itself */ + +-void gta02_jbt6k74_resuming(int devidx) ++static void gta02_jbt6k74_resuming(int devidx) + { + pcf50633_backlight_resume(pcf50633_global); + } + ++static int gta02_jbt6k74_all_dependencies_resumed(int devidx) ++{ ++ if (!resume_dep_jbt_pcf.called_flag) ++ return 0; ++ ++ if (!resume_dep_jbt_glamo.called_flag) ++ return 0; ++ ++ return 1; ++} ++ ++/* register jbt resume action to be dependent on pcf50633 and glamo resume */ ++ ++static void gta02_jbt6k74_suspending(int devindex, struct spi_device *spi) ++{ ++ void jbt6k74_resume(void *spi); /* little white lies about types */ ++ ++ resume_dep_jbt_pcf.callback = jbt6k74_resume; ++ resume_dep_jbt_pcf.context = (void *)spi; ++ pcf50633_register_resume_dependency(pcf50633_global, ++ &resume_dep_jbt_pcf); ++ resume_dep_jbt_glamo.callback = jbt6k74_resume; ++ resume_dep_jbt_glamo.context = (void *)spi; ++ glamo_register_resume_dependency(&resume_dep_jbt_glamo); ++} ++ ++ + const struct jbt6k74_platform_data jbt6k74_pdata = { + .reset = gta02_jbt6k74_reset, + .resuming = gta02_jbt6k74_resuming, ++ .suspending = gta02_jbt6k74_suspending, ++ .all_dependencies_resumed = gta02_jbt6k74_all_dependencies_resumed, + }; + + static struct spi_board_info gta02_spi_board_info[] = { +diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c +index ec6b9f1..2f9b9e1 100644 +--- a/drivers/i2c/chips/pcf50633.c ++++ b/drivers/i2c/chips/pcf50633.c +@@ -1937,7 +1937,7 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind) + + pcf50633_global = data; + +- init_resume_dependency_list(data->resume_dependency); ++ init_resume_dependency_list(&data->resume_dependency); + + populate_sysfs_group(data); + +@@ -2153,11 +2153,11 @@ int pcf50633_report_resumers(struct pcf50633_data *pcf, char *buf) + */ + + void pcf50633_register_resume_dependency(struct pcf50633_data *pcf, +- struct pcf50633_resume_dependency *dep) ++ struct resume_dependency *dep) + { +- register_resume_dependency(pcf->resume_dependency, dep); ++ register_resume_dependency(&pcf->resume_dependency, dep); + } +-EXPORT_SYMBOL_GPL(pcf50633_register_resume_dep); ++EXPORT_SYMBOL_GPL(pcf50633_register_resume_dependency); + + + static int pcf50633_suspend(struct device *dev, pm_message_t state) +@@ -2251,9 +2251,6 @@ static int pcf50633_resume(struct device *dev) + struct i2c_client *client = to_i2c_client(dev); + struct pcf50633_data *pcf = i2c_get_clientdata(client); + int i; +- struct list_head *pos, *q; +- struct pcf50633_resume_dependency *dep; +- + + mutex_lock(&pcf->lock); + +@@ -2281,10 +2278,6 @@ static int pcf50633_resume(struct device *dev) + __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout); + __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena); + __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim); +- } else { /* force backlight down, platform will restore later */ +- __reg_write(pcf, PCF50633_REG_LEDOUT, 2); +- __reg_write(pcf, PCF50633_REG_LEDENA, 0x20); +- __reg_write(pcf, PCF50633_REG_LEDDIM, 1); + } + + /* FIXME: one big read? */ +@@ -2298,7 +2291,7 @@ static int pcf50633_resume(struct device *dev) + + pcf50633_irq(pcf->irq, pcf); + +- callback_all_resume_dependencies(pcf->resume_dependency); ++ callback_all_resume_dependencies(&pcf->resume_dependency); + + return 0; + } +diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c +index 34b2a01..4925e62 100644 +--- a/drivers/mfd/glamo/glamo-core.c ++++ b/drivers/mfd/glamo/glamo-core.c +@@ -1087,6 +1087,8 @@ static int __init glamo_probe(struct platform_device *pdev) + goto out_free; + } + ++ init_resume_dependency_list(&glamo->resume_dependency); ++ + /* register a number of sibling devices whoise IOMEM resources + * are siblings of pdev's IOMEM resource */ + #if 0 +@@ -1225,6 +1227,18 @@ static int glamo_remove(struct platform_device *pdev) + } + + #ifdef CONFIG_PM ++ ++/* have to export this because struct glamo_core is opaque */ ++ ++void glamo_register_resume_dependency(struct resume_dependency * ++ resume_dependency) ++{ ++ register_resume_dependency(&glamo_handle->resume_dependency, ++ resume_dependency); ++} ++EXPORT_SYMBOL_GPL(glamo_register_resume_dependency); ++ ++ + static int glamo_suspend(struct platform_device *pdev, pm_message_t state) + { + glamo_power(glamo_handle, GLAMO_POWER_SUSPEND); +@@ -1234,6 +1248,8 @@ static int glamo_suspend(struct platform_device *pdev, pm_message_t state) + static int glamo_resume(struct platform_device *pdev) + { + glamo_power(glamo_handle, GLAMO_POWER_ON); ++ callback_all_resume_dependencies(&glamo_handle->resume_dependency); ++ + return 0; + } + #else +diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h +index cf89f03..1fee059 100644 +--- a/drivers/mfd/glamo/glamo-core.h ++++ b/drivers/mfd/glamo/glamo-core.h +@@ -2,7 +2,7 @@ + #define __GLAMO_CORE_H + + #include <asm/system.h> +- ++#include <linux/resume-dependency.h> + + /* for the time being, we put the on-screen framebuffer into the lowest + * VRAM space. This should make the code easily compatible with the various +@@ -29,6 +29,7 @@ struct glamo_core { + u_int16_t type; + u_int16_t revision; + spinlock_t lock; ++ struct resume_dependency resume_dependency; + }; + + struct glamo_script { +diff --git a/drivers/video/display/jbt6k74.c b/drivers/video/display/jbt6k74.c +index 178e2da..8e7bf36 100644 +--- a/drivers/video/display/jbt6k74.c ++++ b/drivers/video/display/jbt6k74.c +@@ -27,11 +27,8 @@ + #include <linux/device.h> + #include <linux/platform_device.h> + #include <linux/delay.h> +-#include <linux/workqueue.h> + #include <linux/jbt6k74.h> + +-#include <linux/spi/spi.h> +- + enum jbt_register { + JBT_REG_SLEEP_IN = 0x10, + JBT_REG_SLEEP_OUT = 0x11, +@@ -116,14 +113,12 @@ struct jbt_info { + struct mutex lock; /* protects tx_buf and reg_cache */ + u16 tx_buf[8]; + u16 reg_cache[0xEE]; +- struct work_struct work; ++ int have_resumed; + }; + + #define JBT_COMMAND 0x000 + #define JBT_DATA 0x100 + +-static void jbt_resume_work(struct work_struct *work); +- + + static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg) + { +@@ -576,8 +571,6 @@ static int __devinit jbt_probe(struct spi_device *spi) + if (!jbt) + return -ENOMEM; + +- INIT_WORK(&jbt->work, jbt_resume_work); +- + jbt->spi_dev = spi; + jbt->state = JBT_STATE_DEEP_STANDBY; + mutex_init(&jbt->lock); +@@ -635,27 +628,48 @@ static int jbt_suspend(struct spi_device *spi, pm_message_t state) + struct jbt_info *jbt = dev_get_drvdata(&spi->dev); + struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; + ++ /* platform needs to register resume dependencies here */ ++ if (jbt6k74_pdata->suspending) ++ (jbt6k74_pdata->suspending)(0, spi); ++ + /* Save mode for resume */ + jbt->last_state = jbt->state; + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + +- (jbt6k74_pdata->reset)(0, 0); ++ jbt->have_resumed = 0; ++ ++// (jbt6k74_pdata->reset)(0, 0); + + return 0; + } + +-static void jbt_resume_work(struct work_struct *work) ++int jbt6k74_resume(struct spi_device *spi) + { +- struct jbt_info *jbt = container_of(work, struct jbt_info, work); +- struct jbt6k74_platform_data *jbt6k74_pdata = +- jbt->spi_dev->dev.platform_data; ++ struct jbt_info *jbt = dev_get_drvdata(&spi->dev); ++ struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; ++ ++ /* if we still wait on dependencies, exit because we will get called ++ * again. This guy will get called once by core resume action, and ++ * should be set as resume_dependency callback for any dependencies ++ * set by platform code. ++ */ + +- printk(KERN_INFO"jbt_resume_work waiting...\n"); +- /* 100ms is not enough here 2008-05-08 andy@openmoko.com +- * if CONFIG_PM_DEBUG is enabled 2000ms is required ++ if (jbt6k74_pdata->all_dependencies_resumed) ++ if (!(jbt6k74_pdata->all_dependencies_resumed)(0)) ++ return 0; ++ ++ /* we can get called twice with all dependencies resumed if our core ++ * resume callback is last of all. Protect against going twice + */ +- msleep(400); +- printk(KERN_INFO"jbt_resume_work GO...\n"); ++ if (jbt->have_resumed) ++ return 0; ++ ++ jbt->have_resumed = 1; ++ ++ /* OK we are sure all devices we depend on for operation are up now */ ++ ++ /* even this needs glamo up on GTA02 :-/ */ ++ (jbt6k74_pdata->reset)(0, 1); + + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY); + msleep(100); +@@ -675,21 +689,10 @@ static void jbt_resume_work(struct work_struct *work) + if (jbt6k74_pdata->resuming) + (jbt6k74_pdata->resuming)(0); + +- printk(KERN_INFO"jbt_resume_work done...\n"); +-} +- +-static int jbt_resume(struct spi_device *spi) +-{ +- struct jbt_info *jbt = dev_get_drvdata(&spi->dev); +- struct jbt6k74_platform_data *jbt6k74_pdata = spi->dev.platform_data; +- +- (jbt6k74_pdata->reset)(0, 1); +- +- if (!schedule_work(&jbt->work)) +- dev_err(&spi->dev, "Unable to schedule LCM wakeup work\n"); +- + return 0; + } ++EXPORT_SYMBOL_GPL(jbt6k74_resume); ++ + #else + #define jbt_suspend NULL + #define jbt_resume NULL +@@ -704,7 +707,7 @@ static struct spi_driver jbt6k74_driver = { + .probe = jbt_probe, + .remove = __devexit_p(jbt_remove), + .suspend = jbt_suspend, +- .resume = jbt_resume, ++ .resume = jbt6k74_resume, + }; + + static int __init jbt_init(void) +diff --git a/include/linux/glamofb.h b/include/linux/glamofb.h +index 51bf593..bb4ed0a 100644 +--- a/include/linux/glamofb.h ++++ b/include/linux/glamofb.h +@@ -2,6 +2,7 @@ + #define _LINUX_GLAMOFB_H + + #include <linux/spi/glamo.h> ++#include <linux/resume-dependency.h> + + struct glamofb_val { + unsigned int defval; +@@ -36,5 +37,7 @@ struct glamofb_platform_data { + int glamofb_cmd_mode(struct glamofb_handle *gfb, int on); + int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val); + void glamo_lcm_reset(int level); ++extern void ++glamo_register_resume_dependency(struct resume_dependency * resume_dependency); + + #endif +diff --git a/include/linux/jbt6k74.h b/include/linux/jbt6k74.h +index 0ac9124..f0eaf39 100644 +--- a/include/linux/jbt6k74.h ++++ b/include/linux/jbt6k74.h +@@ -1,9 +1,13 @@ + #ifndef __JBT6K74_H__ + #define __JBT6K74_H__ + ++#include <linux/spi/spi.h> ++ + struct jbt6k74_platform_data { + void (*reset)(int devindex, int level); + void (*resuming)(int devindex); /* called when LCM is resumed */ ++ void (*suspending)(int devindex, struct spi_device *spi); ++ int (*all_dependencies_resumed)(int devindex); + }; + + #endif +diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h +index 2bef616..8a75b28 100644 +--- a/include/linux/pcf50633.h ++++ b/include/linux/pcf50633.h +@@ -127,7 +127,7 @@ pcf50633_report_resumers(struct pcf50633_data *pcf, char *buf); + + extern void + pcf50633_register_resume_dependency(struct pcf50633_data *pcf, +- struct pcf50633_resume_dependency *dep); ++ struct resume_dependency *dep); + + + #define PCF50633_FEAT_EXTON 0x00000001 /* not yet supported */ +diff --git a/include/linux/resume-dependency.h b/include/linux/resume-dependency.h +index b13aa3e..e0c0f33 100644 +--- a/include/linux/resume-dependency.h ++++ b/include/linux/resume-dependency.h +@@ -38,7 +38,7 @@ struct resume_dependency { + */ + + #define init_resume_dependency_list(_head) \ +- INIT_LIST_HEAD(&_head.list); ++ INIT_LIST_HEAD(&(_head)->list); + + + /* if your resume function depends on something else being resumed first, you +@@ -48,8 +48,8 @@ struct resume_dependency { + */ + + #define register_resume_dependency(_head, _dep) { \ +- _dep->called_flag = 0; \ +- list_add(&_dep->list, &_head->list); \ ++ (_dep)->called_flag = 0; \ ++ list_add(&(_dep)->list, &(_head)->list); \ + } + + /* In the resume function that things can be dependent on, at the end you +@@ -61,10 +61,10 @@ struct resume_dependency { + struct list_head *_pos, *_q; \ + struct resume_dependency *_dep; \ + \ +- list_for_each_safe(pos, _q, &_head.list) { \ ++ list_for_each_safe(_pos, _q, &((_head)->list)) { \ + _dep = list_entry(_pos, struct resume_dependency, list); \ + _dep->called_flag = 1; \ +- (_dep->callback)(dep->context); \ ++ (_dep->callback)(_dep->context); \ + list_del(_pos); \ + } \ + } +-- +1.5.6.5 + |