static int rotator_ioctl(struct inode *inode, struct file *file, u32 cmd, unsigned long arg) { struct rot_ctrl *ctrl = &s5p_rot; struct rot_param *params; struct rot_param *parg; int ret; if (rotator_get_status(ctrl) != S5P_ROT_STATREG_STATUS_IDLE) { printk(KERN_ERR "Rotator state : %x\n", rotator_get_status(ctrl)); return -EBUSY; } mutex_lock(&ctrl->lock); params = (struct rot_param *)file->private_data; parg = (struct rot_param *)arg; ret = copy_from_user(params, parg, sizeof(struct rot_param)); if (ret) { printk(KERN_ERR "%s: error : copy_from_user\n", __func__); mutex_unlock(&ctrl->lock); return -EINVAL; } ret = rotator_check_vars(params); if (ret) { printk(KERN_ERR "%s: invalid parameters\n", __func__); mutex_unlock(&ctrl->lock); return -EINVAL; } /* set parameter to regs */ rotator_set_src(ctrl, params); rotator_set_dst(ctrl, params); rotator_set_fmt(ctrl, params); rotator_set_degree_flip(ctrl, params); rotator_start(ctrl); ctrl->status = ROT_RUN; if (!(file->f_flags & O_NONBLOCK)) { ret = wait_event_timeout(ctrl->wq, (ctrl->status == ROT_IDLE), ROTATOR_TIMEOUT); if (ret == 0) { ctrl->status = ROT_IDLE; printk(KERN_ERR "%s: Interrupt timeout\n", __func__); } } mutex_unlock(&ctrl->lock); return 0; }
static u32 rotator_poll(struct file *file, poll_table *wait) { struct rot_ctrl *ctrl = &s5p_rot; u32 mask = 0; poll_wait(file, &ctrl->wq, wait); if (rotator_get_status(ctrl) == S5P_ROT_STATREG_STATUS_IDLE) mask = POLLOUT | POLLWRNORM; return mask; }
/* button isr */ static irqreturn_t rnb4_rot_input_irq(int irq, void *dev_id) { struct rnb4_rot_input *rnb4_rot_input = dev_id; #if defined(CONFIG_ARCH_PARROT_USE_ROTATOR) if(irq == IRQ_ROTATOR_START) { if(rotator_get_status(0) == ROTATOR_EVENT_LEFT) { input_report_key(rnb4_rot_input->input, KEY_DOWN, 1); input_report_key(rnb4_rot_input->input, KEY_DOWN, 0); input_sync(rnb4_rot_input->input); } else { input_report_key(rnb4_rot_input->input, KEY_UP, 1); input_report_key(rnb4_rot_input->input, KEY_UP, 0); input_sync(rnb4_rot_input->input); } } #else //defined(CONFIG_ARCH_PARROT_USE_ROTATOR) /*********************************************************** * software management of a 4 state rotator: * - wait for each state to occur before sending the event * - if an unexpected event occur, return in a wait for the first state * (in this case a rnb4_rot:ERR will be issued) ***********************************************************/ int button = irq - IRQ_GPIO_START, cur_dir; static int last = 0xFF, direction = 0xFF, valid = 0xFF; if(irq == rnb4_rot_input->irq[0]) cur_dir = gpio_get_value(rnb4_rot_input->gpio[0]); else cur_dir = gpio_get_value(rnb4_rot_input->gpio[1]); if(cur_dir > 0) cur_dir = 1; if(valid == 0xFF) { last = button; direction = cur_dir; valid = 0; } else if (valid == 0) { // change of irq and same gpio level if(last != button && direction == cur_dir) { valid = 1; } else { // restart from here printk("rnb4_rot:ERR\n"); last = button; direction = cur_dir; valid = 0; } } else if (valid == 1) { // same irq and different gpio level if(last == button && direction != cur_dir) { valid = 2; } else { // restart from here last = button; direction = cur_dir; valid = 0; printk("rnb4_rot:ERR\n"); } } else {// different irq and same gpio level if(last != button && direction != cur_dir) { if(last > button) { input_report_key(rnb4_rot_input->input, KEY_UP, 1); input_report_key(rnb4_rot_input->input, KEY_UP, 0); input_sync(rnb4_rot_input->input); } else { input_report_key(rnb4_rot_input->input, KEY_DOWN, 1); input_report_key(rnb4_rot_input->input, KEY_DOWN, 0); input_sync(rnb4_rot_input->input); } last = 0xFF; direction = 0xFF; valid = 0xFF; } else { // restart from here printk("rnb4_rot:ERR\n"); last = button; direction = cur_dir; valid = 0; } } #endif //defined(ARCH_PARROT_USE_ROTATOR) return IRQ_HANDLED; }