Hello!
I am working with colibri imx6ull 512 1T som.
BSP Version 5.4.0
I have my custom image that I changed backlight pwm to pwm_B (pwm 5).
I have a buzzer connected to PWM_A (pwm 4).
I have a big app runnning on my system.
My goal is that the buzzer sounds with a beep when I press touchscreen, so I modified ad7879.c driver file where I enable pwm for a brief period of time and then disable It.
Here copy the diff with my code and attach ad7879.c original driver.
I wil explain a little that I done:
I use deferred schedule work adding linux/workqueue.h library.
Define pwm parameters (pwm period, duty_cycle) and pwm device.
Define schedule work functions.
In function ad7879_probe() function I do the request for pwm4 and configure Its parameters.
In ad7879_ts_event_release() function I scheduled work and delay so when I release the touchscreen first beep_on_workqueue function is executed (where pwm is enabled) and after that beep_off_workqueue is executed (where pwm is disabled).
This is working but I have a bug that is sometimes the pwm buzzer is enabled but It not disabled untill press touchscreen again.
I debug the code and the function beep_off_workqueue is executed but It seems that pwm_disable(pwm4) dosn’t take effect.
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 556a2af46e18..1705bf70a048 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -29,7 +29,10 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/gpio/driver.h>
-
+//Section added by Me
+#include <linux/pwm.h>
+#include <linux/workqueue.h>
+//end of section
#include <linux/input/touchscreen.h>
#include <linux/module.h>
#include "ad7879.h"
@@ -131,7 +134,46 @@ struct ad7879 {
int y;
int Rt;
};
+//Section added by Me
+// Define PWM parameters
+#define PWM_RATE 500000 //Period value in nano seconds - Freq = 2 kHz. Freq and duty_cycle buzzer technicals specifications, for more details see buzzer datasheet.
+#define PWM_DUTTY_CYCLE 250000 // Duty_cycle 50 %
+static bool success_initialization = true;
+// Declaration of deferreded work structs and functions
+static struct pwm_device *pwm4 = NULL;
+static void beep_on_workqueue(struct work_struct *work); /*Schedule work to power ON the Buzzer. */
+static void beep_off_workqueue(struct work_struct *work);/*Schedule delayed work to OFF the Buzzer after a time. */
+
+static unsigned long time_delay; /*Time to be delayed to power OFF the Buzzer*/
+static DECLARE_WORK(beep_on_touch_workqueue, beep_on_workqueue);/*Add this work to the WorkQueue. Just add, not run it*/
+static DECLARE_DELAYED_WORK(beep_off_touch_workqueue, beep_off_workqueue);/*Add this work to the WorkQueue. Just add, not run it*/
+
+static void beep_on_workqueue(struct work_struct *work)
+{
+ if(success_initialization)
+ {
+ if (pwm_enable(pwm4) < 0)
+ {
+ printk(KERN_ERR "Couldn't set beep on to buzzer. PWM4 is disabled \n");
+ }
+ }
+ else
+ {
+ printk(KERN_ERR "Couldn't set beep on to buzzer. The buzzer wasn't initialized. \n");
+ }
+}
+
+static void beep_off_workqueue(struct work_struct *work)
+{
+ if(success_initialization)
+ {
+ pwm_disable(pwm4);
+ }
+ else
+ {
+ printk(KERN_ERR "Couldn't set beep off to buzzer. The buzzer wasn't initialized. \n");
+ }
+}
+// End of section added by Cuffia
static int ad7879_read(struct ad7879 *ts, u8 reg)
{
unsigned int val;
@@ -229,7 +271,10 @@ static int ad7879_report(struct ad7879 *ts)
static void ad7879_ts_event_release(struct ad7879 *ts)
{
struct input_dev *input_dev = ts->input;
-
+ // Section added byMe
+ schedule_work(&beep_on_touch_workqueue); /*Schedule this work into the queue*/
+ schedule_delayed_work(&beep_off_touch_workqueue,time_delay);/*Schedule this work into the queue with time_delay*/
+ // End section added by Me
input_report_abs(input_dev, ABS_PRESSURE, 0);
input_report_key(input_dev, BTN_TOUCH, 0);
input_sync(input_dev);
@@ -521,6 +566,17 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
struct input_dev *input_dev;
int err;
u16 revid;
+ //Section added by Me
+ time_delay = jiffies + 200 * HZ / 1000; /*Time used to delay the work. 200 is time in millisecond. 1000 is a constant*/
+ pwm4 = pwm_request(0, "pwmchip0");
+ if (pwm4 == NULL || (pwm_config(pwm4, PWM_DUTTY_CYCLE, PWM_RATE) < 0))
+ {
+ printk(KERN_ERR "Pwm4 config error \n");
+ success_initialization = false;
+ }
+ pwm_disable(pwm4);
+ pwm_free(pwm4);
+ //End of section added by Me
if (irq <= 0) {
dev_err(dev, "No IRQ specified\n");
Where is my problem? It can be the use of threads o cpu?