summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-openmoko-shr-drm-devel/0001-Fix-s3c-adc-suspend.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-openmoko-shr-drm-devel/0001-Fix-s3c-adc-suspend.patch')
-rw-r--r--recipes/linux/linux-openmoko-shr-drm-devel/0001-Fix-s3c-adc-suspend.patch128
1 files changed, 128 insertions, 0 deletions
diff --git a/recipes/linux/linux-openmoko-shr-drm-devel/0001-Fix-s3c-adc-suspend.patch b/recipes/linux/linux-openmoko-shr-drm-devel/0001-Fix-s3c-adc-suspend.patch
new file mode 100644
index 0000000000..6627e698f0
--- /dev/null
+++ b/recipes/linux/linux-openmoko-shr-drm-devel/0001-Fix-s3c-adc-suspend.patch
@@ -0,0 +1,128 @@
+From e22e97d2266d100f501f1e22275595eb68dd3e6f Mon Sep 17 00:00:00 2001
+From: Vasily Khoruzhick <anarsoul@gmail.com>
+Date: Thu, 1 Oct 2009 20:58:18 -0500
+Subject: [PATCH 1/7] Fix s3c-adc suspend
+
+Fix for a bug that shows when the s3c2410 TS driver requests
+a conversion from the s3c-adc driver and the machine goes into suspend.
+In this case the touchscreen stops working.
+
+Note: Nelson edited the original patch with a few small changes.
+
+Reported-by: Radek Polak <psonek2@seznam.cz>
+Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
+Signed-off-by: Nelson Castillo <arhuaco@freaks-unidos.net>
+---
+ arch/arm/plat-s3c24xx/adc.c | 42 +++++++++++++++++++++++++++++++++++++-----
+ 1 files changed, 37 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c
+index 9056bcc..4ce45c5 100644
+--- a/arch/arm/plat-s3c24xx/adc.c
++++ b/arch/arm/plat-s3c24xx/adc.c
+@@ -43,6 +43,7 @@ struct s3c_adc_client {
+ unsigned int nr_samples;
+ unsigned char is_ts;
+ unsigned char channel;
++ unsigned selected;
+
+ void (*select_cb)(unsigned selected);
+ void (*convert_cb)(unsigned val1, unsigned val2,
+@@ -68,6 +69,7 @@ static struct adc_device *adc_dev;
+ static LIST_HEAD(adc_pending);
+
+ #define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
++#define adc_info(_adc, msg...) dev_info(&(_adc)->pdev->dev, msg)
+
+ #define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | \
+ S3C2410_ADCTSC_XP_SEN | S3C2410_ADCTSC_AUTO_PST | \
+@@ -91,7 +93,10 @@ static inline void s3c_adc_select(struct adc_device *adc,
+ {
+ unsigned con = readl(adc->regs + S3C2410_ADCCON);
+
+- client->select_cb(1);
++ if (!client->selected) {
++ client->selected = 1;
++ client->select_cb(1);
++ }
+
+ con &= ~S3C2410_ADCCON_MUXMASK;
+ con &= ~S3C2410_ADCCON_STDBM;
+@@ -115,12 +120,9 @@ void s3c_adc_try(struct adc_device *adc)
+ {
+ struct s3c_adc_client *next = adc->ts_pend;
+
+- if (!next && !list_empty(&adc_pending)) {
++ if (!next && !list_empty(&adc_pending))
+ next = list_first_entry(&adc_pending,
+ struct s3c_adc_client, pend);
+- list_del(&next->pend);
+- } else
+- adc->ts_pend = NULL;
+
+ if (next) {
+ adc_dbg(adc, "new client is %p\n", next);
+@@ -229,9 +231,16 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
+ /* fire another conversion for this */
+
+ client->select_cb(1);
++ client->selected = 1;
+ s3c_adc_convert(adc);
+ } else {
+ local_irq_save(flags);
++ client->selected = 0;
++ if (!adc->cur->is_ts)
++ list_del(&adc->cur->pend);
++ else
++ adc->ts_pend = NULL;
++
+ (client->select_cb)(0);
+ adc->cur = NULL;
+
+@@ -341,20 +350,43 @@ static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
+ writel(con, adc->regs + S3C2410_ADCCON);
+
+ clk_disable(adc->clk);
++ disable_irq(IRQ_ADC);
++
++ if (!list_empty(&adc_pending) || adc->ts_pend)
++ adc_info(adc, "%s:We still have clients pending\n", __func__);
+
+ return 0;
+ }
+
++static struct work_struct resume_work;
++
++static void adc_resume_work(struct work_struct *work)
++{
++ struct adc_device *adc = platform_get_drvdata(adc_dev->pdev);
++
++ adc_info(adc, "%s:We still have clients pending\n", __func__);
++ s3c_adc_try(adc_dev);
++}
++
+ static int s3c_adc_resume(struct platform_device *pdev)
+ {
+ struct adc_device *adc = platform_get_drvdata(pdev);
+
++ enable_irq(IRQ_ADC);
+ clk_enable(adc->clk);
+
+ writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
+ adc->regs + S3C2410_ADCCON);
+ writel(adc->delay, adc->regs + S3C2410_ADCDLY);
+
++ /* Schedule task if there are clients pending. */
++ if (!list_empty(&adc_pending) || adc_dev->ts_pend) {
++ INIT_WORK(&resume_work, adc_resume_work);
++ if (!schedule_work(&resume_work))
++ dev_err(&pdev->dev,
++ "Failed to schedule adc_resume work!\n");
++ }
++
+ return 0;
+ }
+
+--
+1.6.5.2
+