/* * ccdc_ioctl - CCDC module private ioctl's * @sd: VPFE CCDC V4L2 subdevice * @cmd: ioctl command * @arg: ioctl argument * * Return 0 on success or a negative error code otherwise. */ static long resizer_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd); struct imp_logical_channel *rsz_conf_chan = &resizer->channel; struct device *dev = resizer->subdev.v4l2_dev->dev; int ret = 0; switch (cmd) { case RSZ_S_CONFIG: { struct rsz_channel_config *user_config = (struct rsz_channel_config *)arg; dev_dbg(dev, "RSZ_S_CONFIG:\n"); if (!ret) { ret = imp_set_resizer_config(dev, rsz_conf_chan, user_config); } } break; case RSZ_G_CONFIG: { struct rsz_channel_config *user_config = (struct rsz_channel_config *)arg; dev_err(dev, "RSZ_G_CONFIG:%d:%d\n", user_config->chain, user_config->len); if (ISNULL(user_config->config)) { ret = -EINVAL; dev_err(dev, "error in PREV_GET_CONFIG\n"); goto ERROR; } ret = imp_get_resize_config(dev, rsz_conf_chan, user_config); } break; default: printk(KERN_ERR "invalid command\n"); } ERROR: return ret; }
/* =====================rsz_ioctl=========================== This function will process IOCTL commands sent by the application and control the device IO operations. */ static int rsz_doioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0, prio; unsigned mode, user_mode; /*get the configuratin of this channel from private_date member of file */ struct imp_logical_channel *rsz_conf_chan = (struct imp_logical_channel *)file->private_data; if (ISNULL(rsz_conf_chan)) { dev_err(rsz_device, "channel ptr is null\n"); return -EFAULT; } if (ISNULL((void *)arg)) { dev_err(rsz_device, "arg ptr is null\n"); return -EFAULT; } mode = imp_hw_if->get_resize_oper_mode(); switch (cmd) { case RSZ_QUERYBUF: case RSZ_REQBUF: case RSZ_RESIZE: case RSZ_RECONFIG: { if (mode == IMP_MODE_CONTINUOUS) return -EACCES; } break; } switch (cmd) { case RSZ_S_OPER_MODE: { dev_dbg(rsz_device, "RSZ_S_OPER_MODE:\n"); user_mode = *((unsigned long *)arg); if (rsz_conf_chan->mode != IMP_MODE_INVALID) { dev_err(rsz_device, "Mode set for this channel already\n"); ret = -EINVAL; goto ERROR; } if (user_mode >= IMP_MODE_INVALID) { dev_err(rsz_device, "Invalid mode\n"); ret = -EINVAL; goto ERROR; } imp_hw_if->set_resize_oper_mode(user_mode); mode = imp_hw_if->get_resize_oper_mode(); if (user_mode != mode) { dev_err(rsz_device, "Operation mode doesn't match" " with current hw mode\n"); ret = -EINVAL; goto ERROR; } ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { rsz_conf_chan->mode = mode; mutex_unlock(&(rsz_conf_chan->lock)); } dev_dbg(rsz_device, "RSZ_S_OPER_MODE: Operation mode set to %d", user_mode); } break; /* if case is to query for buffer address */ case RSZ_G_OPER_MODE: { dev_dbg(rsz_device, "RSZ_G_OPER_MODE:\n"); *((unsigned long *)arg) = rsz_conf_chan->mode; dev_dbg(rsz_device, "RSZ_G_OPER_MODE: mode = %d", rsz_conf_chan->mode); } break; case RSZ_S_CONFIG: { dev_dbg(rsz_device, "RSZ_S_CONFIG:\n"); ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { ret = imp_set_resizer_config(rsz_device, rsz_conf_chan, (struct rsz_channel_config *)arg); mutex_unlock(&(rsz_conf_chan->lock)); } } break; case RSZ_G_CONFIG: { struct rsz_channel_config *user_config = (struct rsz_channel_config *)arg; dev_err(rsz_device, "RSZ_G_CONFIG:%d:%d:%d\n", user_config->oper_mode, user_config->chain, user_config->len); if (ISNULL(user_config->config)) { ret = -EINVAL; dev_err(rsz_device, "error in PREV_GET_CONFIG\n"); goto ERROR; } ret = imp_get_resize_config(rsz_device, rsz_conf_chan, user_config); } break; case RSZ_QUERYBUF: { dev_dbg(rsz_device, "RSZ_QUERYBUF:\n"); ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { ret = imp_common_query_buffer(rsz_device, rsz_conf_chan, (struct imp_buffer *)arg); mutex_unlock(&(rsz_conf_chan->lock)); } } break; /* if case is to request buffers */ case RSZ_REQBUF: { dev_dbg(rsz_device, "RSZ_REQBUF:\n"); ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { ret = imp_common_request_buffer(rsz_device, rsz_conf_chan, (struct imp_reqbufs *) arg); mutex_unlock(&(rsz_conf_chan->lock)); } } break; /* if the case is to do resize */ case RSZ_S_PRIORITY: { prio = *((unsigned long *)arg); dev_dbg(rsz_device, "RSZ_S_PRIORITY: priority = %d\n", prio); /* Check the prioroty range and assign the priority */ if (prio > MAX_PRIORITY || prio < MIN_PRIORITY) { ret = -EINVAL; goto ERROR; } else { ret = mutex_lock_interruptible( &(rsz_conf_chan->lock)); if (!ret) { rsz_conf_chan->priority = prio; mutex_unlock(&(rsz_conf_chan->lock)); } } dev_dbg(rsz_device, "\n resizer_Priority:end"); } break; /* This ioctl is used to get the priority of the current logic channel */ case RSZ_G_PRIORITY: { dev_dbg(rsz_device, "RSZ_S_PRIORITY: \n"); /* Get the priority from the channel */ *((unsigned long *)arg) = rsz_conf_chan->priority; } break; case RSZ_RESIZE: { dev_dbg(rsz_device, "RSZ_RESIZE: \n"); ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { ret = imp_common_start_resize(rsz_device, rsz_conf_chan, (struct imp_convert *) arg); mutex_unlock(&(rsz_conf_chan->lock)); } } break; case RSZ_RECONFIG: { dev_dbg(rsz_device, "RSZ_RECONFIG: \n"); ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { ret = imp_common_reconfig_resizer(rsz_device, (struct rsz_reconfig *)arg, rsz_conf_chan); mutex_unlock(&(rsz_conf_chan->lock)); } } break; #ifdef CONFIG_IMP_DEBUG case RSZ_DUMP_HW_CONFIG: { dev_dbg(rsz_device, "RSZ_DUMP_HW_CONFIG: \n"); ret = mutex_lock_interruptible(&(rsz_conf_chan->lock)); if (!ret) { if (imp_hw_if->dump_hw_config) imp_hw_if->dump_hw_config(); mutex_unlock(&(rsz_conf_chan->lock)); } } break; #endif default: dev_dbg(rsz_device, "resizer_ioctl: Invalid Command Value"); ret = -EINVAL; } ERROR: return ret; } /*End of function IOCTL */