I have made the following changes intended for :
  CE:Adaptation:N950-N9 / kernel-adaptation-n950

Please review and accept or decline.
BOSS has already run some checks on this request.
See the "Messages from BOSS" section below.

https://build.pub.meego.com//request/show/7196

Thank You,
kjokinie

[This message was auto-generated]

---

Request # 7196:

Messages from BOSS:

State: review at 2012-10-30T10:31:38 by bossbot

Reviews:
       accepted by bossbot : Prechecks succeeded.
       new for CE-maintainers : Please replace this text with a review and 
approve/reject the review (not the SR). BOSS will take care of the rest

Changes:
  submit: home:kjokinie:branches:Mer:MDS:Core:armv7hl / kernel-adaptation-n950 
-> CE:Adaptation:N950-N9 / kernel-adaptation-n950
  
changes files:
--------------
--- kernel-adaptation-n950.changes
+++ kernel-adaptation-n950.changes
@@ -0,0 +1,4 @@
+* Tue Oct 30 2012 Kalle Jokiniemi <[email protected]> - 
2.6.32.20121810.2
+- Converted N9 vibra driver to ff-memless, it now supports FF_RUMBLE and 
FF_PERIODIC effects
+- Updated README with up-to-date instructions
+

old:
----
  kernel-n9-2.6.32.20121810.1.tar.bz2

new:
----
  kernel-n9-2.6.32.20121810.2.tar.bz2

spec files:
-----------
--- kernel-adaptation-n950-debug.spec
+++ kernel-adaptation-n950-debug.spec
@@ -1,6 +1,6 @@
 Name:       kernel-adaptation-n950-debug
 Summary:    Kernel Adaptation for n950
-Version:    2.6.32.20121810.1
+Version:    2.6.32.20121810.2
 Release:    1
 Group:      Kernel/Linux Kernel
 License:    GPLv2
@@ -8,7 +8,6 @@
 Source0:    kernel-n9-%{version}.tar.bz2
 Source1:    kernel-adaptation-n950-debug.config
 Source2:    kernel-adaptation-n950.cmdline
-
 Source3:  kernel-adaptation-n950.spec.tpl
 Source4:  generate-spec.sh
 Source5:  kernel-adaptation-n950.config
@@ -51,7 +50,7 @@
 cp %{SOURCE1} ./.config
 
 # make sure EXTRAVERSION says what we want it to say
-perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = .20121810.1-n950-debug/" 
Makefile
+perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = .20121810.2-n950-debug/" 
Makefile
 
 # Verify this spec is using the latest template version
 /usr/bin/mer_verify_kernel_spec 1 --fatal-if-old
--- kernel-adaptation-n950.spec
+++ kernel-adaptation-n950.spec
@@ -1,6 +1,6 @@
 Name:       kernel-adaptation-n950
 Summary:    Kernel Adaptation for n950
-Version:    2.6.32.20121810.1
+Version:    2.6.32.20121810.2
 Release:    1
 Group:      Kernel/Linux Kernel
 License:    GPLv2
@@ -8,7 +8,6 @@
 Source0:    kernel-n9-%{version}.tar.bz2
 Source1:    kernel-adaptation-n950.config
 Source2:    kernel-adaptation-n950.cmdline
-
 Source3:  kernel-adaptation-n950.spec.tpl
 Source4:  generate-spec.sh
 Source5:  kernel-adaptation-n950-debug.config
@@ -51,7 +50,7 @@
 cp %{SOURCE1} ./.config
 
 # make sure EXTRAVERSION says what we want it to say
-perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = .20121810.1-n950/" Makefile
+perl -p -i -e "s/^EXTRAVERSION.*/EXTRAVERSION = .20121810.2-n950/" Makefile
 
 # Verify this spec is using the latest template version
 /usr/bin/mer_verify_kernel_spec 1 --fatal-if-old

other changes:
--------------

++++++ README
--- README
+++ README
@@ -1 +1,20 @@
-Generate spec files from kernel-adaptation-n950.spec.tpl using generate-spec.sh
+Kernel tagging:
+- The GIT tree is here: https://github.com/nemomobile/kernel-adaptation-n950-n9
+- The branch for 2.6.32 based development is "mer-n9-2.6.32-20121301"
+- The old nemo-n9-2.6.32.YYYYDDMM.X tag numbering is not sequential, so we
+  increase the version during 2012 by just incrementing the .X, YYYYDDMM
+  has to remain same to make sure versions increase and zypper does not get
+  confused.
+
+- Once we reach 2013, the tagging will be changed to
+  nemo-n9-2.6.32.YYYYMMDD.X, where YYYYMMDD is the date, and X is running
+  number starting from 1 for tags made during same day.
+
+The kernel tarball generation (using git-archive):
+
+git archive --format=tar --prefix=kernel-n9-2.6.32.YYYYMMDD.X 
nemo-n9-2.6.32.YYYYMMDD.X |bzip2 > kernel-n9-2.6.32.YYYYMMDD.X.tar.bz2
+
+Spec file generation:
+- Generate spec files from kernel-adaptation-n950.spec.tpl using 
generate-spec.sh. 
+- Remember to edit EXTRAVERSION in generate-spec.sh, if you tagged a new 
version.
+

++++++ generate-spec.sh
--- generate-spec.sh
+++ generate-spec.sh
@@ -3,7 +3,7 @@
 DEBUG_SUFFIX=n950-debug
 SUFFIX=n950
 HW=n950
-EXTRA=20121810.1
+EXTRA=20121810.2
 
 sed -e "s/SUFFIX/${SUFFIX}/" \
     -e "s/HARDWARE/${HW}/" \

++++++ kernel-n9-2.6.32.20121810.1.tar.bz2 -> 
kernel-n9-2.6.32.20121810.2.tar.bz2
--- drivers/input/misc/vibra_spi.c
+++ drivers/input/misc/vibra_spi.c
@@ -37,14 +37,24 @@
 #include <linux/uaccess.h>
 
 /* Number of effects handled with memoryless devices */
-#define VIBRA_EFFECTS          36
-#define MAX_EFFECT_SIZE                1024 /* In bytes */
+#define WAVE_SIZE              156 /* In u32 */
 #define WAIT_TIMEOUT           10 /* In ms */
 
 #define FF_EFFECT_QUEUED       BIT(0)
 #define FF_EFFECT_PLAYING      BIT(1)
 #define FF_EFFECT_ABORTING     BIT(2)
-#define FF_EFFECT_UPLOADING    BIT(3)
+
+/* A pre-generated normalized sine-table for signal generation */
+static u8 sine_lookup[] = {
+       32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 29, 29, 29, 28,
+       28, 27, 27, 27, 26, 26, 25, 24, 24, 23, 23, 22, 22, 21, 20, 20, 19, 18,
+       18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, 10, 9, 8, 8, 7, 7,
+       6, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+       8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 16, 17, 18, 18,
+       19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 27, 28, 28,
+       29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32
+};
 
 enum vibra_status {
        IDLE = 0,
@@ -57,8 +67,6 @@
        char            *buf;
        unsigned int    buflen;
        unsigned long   flags;  /* effect state (STARTED, PLAYING, etc) */
-       int             remaining_ms;
-       unsigned int    len_ms;
 };
 
 struct vibra_data {
@@ -75,9 +83,8 @@
 
        enum vibra_status               status;
 
-       struct vibra_effect_info        effects[VIBRA_EFFECTS];
-       int                             next_effect;
-       int                             current_effect;
+       struct vibra_effect_info        einfo;
+
        wait_queue_head_t               wq;
 
        void (*set_power)(bool enable);
@@ -88,8 +95,8 @@
        spi_message_init(&vibra->msg);
        memset(&vibra->t, 0, sizeof(vibra->t));
 
-       vibra->t.tx_buf = vibra->effects[vibra->current_effect].buf;
-       vibra->t.len    = vibra->effects[vibra->current_effect].buflen;
+       vibra->t.tx_buf = vibra->einfo.buf;
+       vibra->t.len    = vibra->einfo.buflen;
        spi_message_add_tail(&vibra->t, &vibra->msg);
 
        return spi_sync(vibra->spi_dev, &vibra->msg);
@@ -100,105 +107,103 @@
        DECLARE_WAITQUEUE(wait, current);
        struct vibra_data *vibra = container_of(work,
                                                struct vibra_data, play_work);
-       struct vibra_effect_info *curr;
+       struct vibra_effect_info *curr = &vibra->einfo;
        int ret;
 
        add_wait_queue(&vibra->wq, &wait);
        while (1) {
-               long val;
-
                if (vibra->status == CLOSING)
                        goto switch_off;
 
-               vibra->current_effect = vibra->next_effect;
-               curr = &vibra->effects[vibra->current_effect];
-
                if (curr->flags & FF_EFFECT_ABORTING)
                        goto switch_off;
 
-               if (curr->remaining_ms > 0) {
-                       spin_lock_bh(&vibra->input_dev->event_lock);
-                       curr->flags |= FF_EFFECT_PLAYING;
-                       curr->remaining_ms -= curr->len_ms;
-                       spin_unlock_bh(&vibra->input_dev->event_lock);
-
-                       dev_dbg(vibra->dev, "curr->remaining_ms: %d\n",
-                               curr->remaining_ms);
-
-                       if (vibra->status == STARTED) {
-                               if (vibra->set_power)
-                                       vibra->set_power(true);
-
-                               vibra->status = PLAYING;
-                       }
-
-                       ret = vibra_spi_raw_write_effect(vibra);
-                       if (ret < 0) {
-                               dev_err(vibra->dev,
-                                       "Error replaying an effect: %d", ret);
-                               goto switch_off;
-                       }
-
-                       spin_lock_bh(&vibra->input_dev->event_lock);
-                       curr->flags &= ~FF_EFFECT_PLAYING;
-                       spin_unlock_bh(&vibra->input_dev->event_lock);
-
-                       continue;
-               } else {
-                       dev_dbg(vibra->dev, "curr->remaining_ms: %d\n",
-                               curr->remaining_ms);
+               spin_lock_bh(&vibra->input_dev->event_lock);
+               curr->flags |= FF_EFFECT_PLAYING;
+
+               spin_unlock_bh(&vibra->input_dev->event_lock);
+
+               if (vibra->status == STARTED) {
+                       if (vibra->set_power)
+                               vibra->set_power(true);
+
+                       vibra->status = PLAYING;
+               }
+
+               ret = vibra_spi_raw_write_effect(vibra);
+               if (ret < 0) {
+                       dev_err(vibra->dev,
+                               "Error replaying an effect: %d", ret);
+                       goto switch_off;
                }
 
-               /*
-                * Nothing to play, so switch off the power if no data
-                * appears before the timeout.
-                */
-               val = wait_event_interruptible_timeout(
-                       vibra->wq,
-                       vibra->effects[vibra->next_effect].remaining_ms > 0,
-                       msecs_to_jiffies(WAIT_TIMEOUT));
-               if (val > 0)
-                       continue;
+               continue;
+
 switch_off:
                if (vibra->set_power)
                        vibra->set_power(false);
 
+               curr->flags &= ~FF_EFFECT_PLAYING;
                vibra->status = IDLE;
                remove_wait_queue(&vibra->wq, &wait);
                return;
        }
 }
 
+
+/*
+ * Calculate sample table for vibra signal.
+ * Each 32bit sample forms one PWM duty cycle. The vibra is a speaker type 
vibra
+ * that needs 150Hz sine signal to give good vibration force. The wave form is
+ * created by doing a amplitude modulation with PWM. The wave form is always
+ * the same, but we control the strength by changing the amplitude.
+ */
+static void vibra_spi_create_signal(struct vibra_data *vibra,
+                                               struct ff_effect *effect)
+{
+       unsigned int i;
+       u16 strong, weak;
+       u32 gain, div = 0xffffffff / 32;
+       u32 *buf = (u32 *)vibra->einfo.buf;
+
+       strong = effect->u.rumble.strong_magnitude;
+       weak = effect->u.rumble.weak_magnitude;
+
+       gain = strong;
+       gain = gain << 16;
+       gain |= weak;
+       gain = gain / 32;
+
+       /* Calculate 32 bit PWM cycles for a sine signal */
+       for (i = 0; i < WAVE_SIZE; i++)
+               buf[i] = (1 << (sine_lookup[i] * gain / div)) - 1;
+
+}
+
 /*
  * Input/Force feedback guarantees that playback() is called with spinlock held
  * and interrupts off.
  */
-static int vibra_spi_playback(struct input_dev *input, int effect_id, int 
value)
+static int vibra_spi_playback(struct input_dev *input, void *vibra_data,
+                                               struct ff_effect *ff_effect)
 {
-       struct vibra_data *vibra = input_get_drvdata(input);
-       struct vibra_effect_info *einfo = &vibra->effects[effect_id];
-       struct ff_effect *ff_effect = &input->ff->effects[effect_id];
+       struct vibra_data *vibra = (struct vibra_data *) vibra_data;
+       struct vibra_effect_info *einfo = &vibra->einfo;
 
        if (!vibra->workqueue)
                return -ENODEV;
 
-       if (einfo->flags & FF_EFFECT_UPLOADING)
-               return -EBUSY;
-
-       if (value == 0) {
+       if (!ff_effect->u.rumble.strong_magnitude &&
+                                       !ff_effect->u.rumble.weak_magnitude) {
                /* Abort the given effect */
                if (einfo->flags & FF_EFFECT_PLAYING)
                        einfo->flags |= FF_EFFECT_ABORTING;
 
                einfo->flags &= ~FF_EFFECT_QUEUED;
        } else {
-               /* Move the given effect as the next one */
-               vibra->effects[vibra->next_effect].flags &= ~FF_EFFECT_QUEUED;
-
-               vibra->next_effect = effect_id;
                einfo->flags |= FF_EFFECT_QUEUED;
                einfo->flags &= ~FF_EFFECT_ABORTING;
-               einfo->remaining_ms = ff_effect->replay.length;
+               vibra_spi_create_signal(vibra, ff_effect);
 
                if (vibra->status == IDLE) {
                        vibra->status = STARTED;
@@ -211,72 +216,6 @@
        return 0;
 }
 
-static int vibra_spi_upload(struct input_dev *input, struct ff_effect *effect,
-                           struct ff_effect *old)
-{
-       struct vibra_data *vibra = input_get_drvdata(input);
-       struct vibra_effect_info *einfo = &vibra->effects[effect->id];
-       struct ff_periodic_effect *p = &effect->u.periodic;
-       unsigned int datalen;
-       int ret = 0;
-
-       if (effect->type != FF_PERIODIC || p->waveform != FF_CUSTOM)
-               return -EINVAL;
-
-       spin_lock_bh(&vibra->input_dev->event_lock);
-       if (einfo->flags &
-           (FF_EFFECT_QUEUED | FF_EFFECT_PLAYING | FF_EFFECT_UPLOADING)) {
-               spin_unlock_bh(&vibra->input_dev->event_lock);
-               return -EBUSY;
-       }
-
-       einfo->flags |= FF_EFFECT_UPLOADING;
-       spin_unlock_bh(&vibra->input_dev->event_lock);
-
-       datalen = p->custom_len * sizeof(p->custom_data[0]);
-       if (datalen > MAX_EFFECT_SIZE) {
-               pr_err("datalen: %d, MAX_EFFECT_SIZE: %d\n",
-                      datalen, MAX_EFFECT_SIZE);
-
-               ret = -ENOSPC;
-               goto exit;
-       }
-
-       if (einfo->buf && einfo->buflen != datalen) {
-               kfree(einfo->buf);
-               einfo->buf = NULL;
-       }
-
-       if (!einfo->buf) {
-               einfo->buf = kzalloc(datalen, GFP_KERNEL);
-               if (!einfo->buf) {
-                       ret = -ENOMEM;
-                       goto exit;
-               }
-       }
-
-       /*
-        * Input layer has performed copy_from_user() for the effect but not
-        * for custom_data. Moreover, custom_data has basically lost the
-        * information that it originates from user space.
-        */
-       if (copy_from_user(einfo->buf, (void __user *) p->custom_data, datalen))
-               return -EFAULT;
-
-       einfo->buflen = datalen;
-
-       /* Sample length in ms. */
-       einfo->len_ms = 1000 * datalen * BITS_PER_BYTE /
-               vibra->spi_max_speed_hz;
-       if (einfo->len_ms < 1) {
-               pr_err("Effect too short: %d\n", datalen);
-               return -EINVAL;
-       }
-exit:
-       einfo->flags &= ~FF_EFFECT_UPLOADING;
-       return ret;
-}
-
 static int vibra_spi_open(struct input_dev *input)
 {
        struct vibra_data *vibra = input_get_drvdata(input);
@@ -307,7 +246,6 @@
 static int __devinit vibra_spi_probe(struct spi_device *spi)
 {
        struct vibra_data *vibra;
-       struct ff_device *ff;
        struct vibra_spi_platform_data *pdata;
        int ret = -ENOMEM;
 
@@ -353,32 +291,35 @@
        vibra->input_dev->open          = vibra_spi_open;
        vibra->input_dev->close         = vibra_spi_close;
 
-       set_bit(FF_PERIODIC, vibra->input_dev->ffbit);
-       set_bit(FF_CUSTOM, vibra->input_dev->ffbit);
+       set_bit(FF_RUMBLE, vibra->input_dev->ffbit);
 
-       ret = input_ff_create(vibra->input_dev, VIBRA_EFFECTS);
+       ret = input_ff_create_memless(vibra->input_dev, vibra,
+                                                       vibra_spi_playback);
        if (ret) {
-               dev_err(&spi->dev, "Couldn't create input feedback device");
-               goto err_input_ff_create;
+               dev_err(&spi->dev, "Couldn't create ff_memless device");
+               goto err_ff_memless_create;
        }
 
-       ff              = vibra->input_dev->ff;
-       ff->private     = vibra;
-       ff->upload      = vibra_spi_upload;
-       ff->playback    = vibra_spi_playback;
-
        ret = input_register_device(vibra->input_dev);
        if (ret < 0) {
                dev_dbg(&spi->dev, "couldn't register input device\n");
                goto err_input_register;
        }
+       vibra->einfo.buflen = sizeof(u32) * WAVE_SIZE;
+
+       vibra->einfo.buf = kzalloc(vibra->einfo.buflen, GFP_KERNEL);
+       if (!vibra->einfo.buf) {
+               dev_err(&spi->dev, "Not enough memory for sample table\n");
+               goto err_playbuf;
+       }
 
        dev_dbg(&spi->dev, "SPI driven Vibra driver initialized\n");
        return 0;
-
+err_playbuf:
+       input_unregister_device(vibra->input_dev);
 err_input_register:
        input_ff_destroy(vibra->input_dev);
-err_input_ff_create:
+err_ff_memless_create:
        input_free_device(vibra->input_dev);
 err_input_alloc:
 err_spi_setup:
@@ -389,16 +330,15 @@
 static int __devexit vibra_spi_remove(struct spi_device *spi)
 {
        struct vibra_data *vibra = dev_get_drvdata(&spi->dev);
-       int i;
 
-       for (i = 0; i < VIBRA_EFFECTS; i++)
-               kfree(vibra->effects[i].buf);
+       kfree(vibra->einfo.buf);
 
        /*
         * No need to do kfree(vibra) since the following calls
         * input_ff_destroy, which does kfree(ff->private)
         */
        input_unregister_device(vibra->input_dev);
+       kfree(vibra->einfo.buf);
        return 0;
 }
 



Reply via email to