[PATCH] [RFC] Use ADC API

Nelson Castillo arhuaco at freaks-unidos.net
Wed Apr 1 08:31:55 CEST 2009


On Wed, Mar 11, 2009 at 5:12 PM, Nelson Castillo
<arhuaco at freaks-unidos.net> wrote:
> From: Nelson Castillo <arhuaco at freaks-unidos.net>
>
> This is a small fun patch that makes the TS driver use the s3c-adc
> driver. This is something we will have to do in order to get the
> driver upstream.
>
> This patch is a proof of concept only and should not be applied.
>
> It works but it is slow because we schedule conversions one by one. It
> could be improved in different ways. The following two come to my mind
> now:
>
> 1) As for conversion in quantums (say of 10) and discard a few if we
> don't get to need them.
>
> 2) Add a method to the TS filters called "minimum_needed" that helps
> the driver estimate how many points to ask for.
>
> If we use the ADC API we should play nice with other devices
> that might want to use the ADC thus the quantum approach should be
> good.

Well, our main trouble is that we don't know in advance how many
conversions we'll need and that's why in this RFC I asked for them one
by one. Another approach I'm trying is in this (untested) patch that
allows you to cancel pending ADC requests. This way we can  ask for
say 100 conversions and only use 50. I think this will solve the
problem (but I still don't know whether Ben will like this patch).

I should have more information on Friday.

Anything obviously wrong with this patch?

s3c-adc-cancel-conversions.patch

From: Nelson Castillo <arhuaco at freaks-unidos.net>

Signed-off-by: Nelson Castillo <arhuaco at freaks-unidos.net>
---

 arch/arm/plat-s3c/include/plat/adc.h |   11 ++++++++++-
 arch/arm/plat-s3c24xx/adc.c          |    9 +++++----
 2 files changed, 15 insertions(+), 5 deletions(-)


diff --git a/arch/arm/plat-s3c/include/plat/adc.h
b/arch/arm/plat-s3c/include/plat/adc.h
index 43df2a4..26fc4d5 100644
--- a/arch/arm/plat-s3c/include/plat/adc.h
+++ b/arch/arm/plat-s3c/include/plat/adc.h
@@ -19,9 +19,18 @@ struct s3c_adc_client;
 extern int s3c_adc_start(struct s3c_adc_client *client,
 			 unsigned int channel, unsigned int nr_samples);

+
+/*
+ * Register the ADC client.
+ *
+ * The conv callback has a return value. If it is non-zero, pending
+ * conversions scheduled with s3c_adc_start will be canceled.
+ */
+
 extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
 					       void (*select)(unsigned selected),
-					       void (*conv)(unsigned d0, unsigned d1),
+					       int (*conv)(unsigned d0,
+							   unsigned d1),
 					       unsigned int is_ts);

 extern void s3c_adc_release(struct s3c_adc_client *client);
diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c
index 9a5c767..4b4111d 100644
--- a/arch/arm/plat-s3c24xx/adc.c
+++ b/arch/arm/plat-s3c24xx/adc.c
@@ -45,7 +45,7 @@ struct s3c_adc_client {
 	unsigned char		 channel;

 	void	(*select_cb)(unsigned selected);
-	void	(*convert_cb)(unsigned val1, unsigned val2);
+	int	(*convert_cb)(unsigned val1, unsigned val2);
 };

 struct adc_device {
@@ -158,7 +158,7 @@ static void s3c_adc_default_select(unsigned select)

 struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
 					void (*select)(unsigned int selected),
-					void (*conv)(unsigned d0, unsigned d1),
+					int (*conv)(unsigned d0, unsigned d1),
 					unsigned int is_ts)
 {
 	struct s3c_adc_client *client;
@@ -200,6 +200,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
 	struct s3c_adc_client *client = adc->cur;
 	unsigned long flags;
 	unsigned data0, data1;
+	int ret;

 	if (!client) {
 		dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
@@ -210,9 +211,9 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
 	data1 = readl(adc->regs + S3C2410_ADCDAT1);
 	adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);

-	(client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff);
+	ret = (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff);

-	if (--client->nr_samples > 0) {
+	if (!ret && --client->nr_samples > 0) {
 		/* fire another conversion for this */

 		client->select_cb(1);



More information about the openmoko-kernel mailing list