/* Call with ams_info.lock held! */ int ams_sensor_attach(void) { int result; const u32 *prop; /* Get orientation */ prop = of_get_property(ams_info.of_node, "orientation", NULL); if (!prop) return -ENODEV; ams_info.orient1 = *prop; ams_info.orient2 = *(prop + 1); /* Register freefall interrupt handler */ result = pmf_register_irq_client(ams_info.of_node, "accel-int-1", &ams_freefall_client); if (result < 0) return -ENODEV; /* Reset saved irqs */ ams_info.worker_irqs = 0; /* Register shock interrupt handler */ result = pmf_register_irq_client(ams_info.of_node, "accel-int-2", &ams_shock_client); if (result < 0) goto release_freefall; /* Create device */ ams_info.of_dev = of_platform_device_create(ams_info.of_node, "ams", NULL); if (!ams_info.of_dev) { result = -ENODEV; goto release_shock; } /* Create attributes */ result = device_create_file(&ams_info.of_dev->dev, &dev_attr_current); if (result) goto release_of; ams_info.vflag = !!(ams_info.get_vendor() & 0x10); /* Init input device */ result = ams_input_init(); if (result) goto release_device_file; return result; release_device_file: device_remove_file(&ams_info.of_dev->dev, &dev_attr_current); release_of: of_device_unregister(ams_info.of_dev); release_shock: pmf_unregister_irq_client(&ams_shock_client); release_freefall: pmf_unregister_irq_client(&ams_freefall_client); return result; }
static int pmf_set_notify(struct gpio_runtime *rt, enum notify_type type, notify_func_t notify, void *data) { struct gpio_notification *notif; notify_func_t old; struct pmf_irq_client *irq_client; char *name; int err = -EBUSY; switch (type) { case AOA_NOTIFY_HEADPHONE: notif = &rt->headphone_notify; name = "headphone-detect"; break; case AOA_NOTIFY_LINE_IN: notif = &rt->line_in_notify; name = "linein-detect"; break; case AOA_NOTIFY_LINE_OUT: notif = &rt->line_out_notify; name = "lineout-detect"; break; default: return -EINVAL; } mutex_lock(¬if->mutex); old = notif->notify; if (!old && !notify) { err = 0; goto out_unlock; } if (old && notify) { if (old == notify && notif->data == data) err = 0; goto out_unlock; } if (old && !notify) { irq_client = notif->gpio_private; pmf_unregister_irq_client(irq_client); kfree(irq_client); notif->gpio_private = NULL; } if (!old && notify) { irq_client = kzalloc(sizeof(struct pmf_irq_client), GFP_KERNEL); if (!irq_client) { err = -ENOMEM; goto out_unlock; } irq_client->data = notif; irq_client->handler = pmf_handle_notify_irq; irq_client->owner = THIS_MODULE; err = pmf_register_irq_client(rt->node, name, irq_client); if (err) { printk(KERN_ERR "snd-aoa: gpio layer failed to" " register %s irq (%d)\n", name, err); kfree(irq_client); goto out_unlock; } notif->gpio_private = irq_client; } notif->notify = notify; notif->data = data; err = 0; out_unlock: mutex_unlock(¬if->mutex); return err; }