diff options
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.patch | 128 |
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 + |