static int fimc_is_isp_video_enum_input(struct file *file, void *priv, struct v4l2_input *input) { struct fimc_is_core *isp = video_drvdata(file); struct exynos5_fimc_is_sensor_info *sensor_info; sensor_info = isp->pdata->sensor_info[input->index]; dbg_isp("index(%d) sensor(%s)\n", input->index, sensor_info->sensor_name); dbg_isp("pos(%d) sensor_id(%d)\n", sensor_info->sensor_position, sensor_info->sensor_id); dbg_isp("csi_id(%d) flite_id(%d)\n", sensor_info->csi_id, sensor_info->flite_id); dbg_isp("i2c_ch(%d)\n", sensor_info->i2c_channel); if (input->index >= FIMC_IS_MAX_CAMIF_CLIENTS) return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; strncpy(input->name, sensor_info->sensor_name, FIMC_IS_MAX_SENSOR_NAME_LEN); return 0; }
static int fimc_is_isp_video_g_ext_ctrl(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { int ret = 0; struct v4l2_ext_control *ctrl; struct fimc_is_from_info *pinfo = NULL; dbg_isp("%s\n", __func__); ctrl = ctrls->controls; switch (ctrl->id) { case V4L2_CID_CAM_SENSOR_FW_VER: #ifdef CONFIG_USE_VENDER_FEATURE fimc_is_sec_get_sysfs_pinfo(&pinfo); #else pinfo = sysfs_pinfo; #endif if (pinfo != NULL) { strncpy(ctrl->string, pinfo->header_ver, strlen(pinfo->header_ver)); ctrl->string[strlen(pinfo->header_ver)] = '\0'; } break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } return ret; }
static int fimc_is_3a1_video_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { int ret = 0; struct fimc_is_video_ctx *vctx = file->private_data; struct fimc_is_device_ischain *device; BUG_ON(!vctx); dbg_isp("%s\n", __func__); device = vctx->device; if (!device) { merr("device is NULL", vctx); ret = -EINVAL; goto p_err; } switch (ctrl->id) { case V4L2_CID_IS_FORCE_DONE: set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_3ax.state); break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } p_err: return ret; }
static int fimc_is_isp_video_g_ext_ctrl(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { int ret = 0; struct v4l2_ext_control *ctrl; dbg_isp("%s\n", __func__); ctrl = ctrls->controls; switch (ctrl->id) { case V4L2_CID_CAM_SENSOR_FW_VER: if((sysfs_pinfo != NULL) && (sysfs_pinfo->header_ver != NULL)) { strncpy(ctrl->string, sysfs_pinfo->header_ver, strlen(ctrl->string) - 1); ctrl->string[strlen(ctrl->string) - 1] = '\0'; } break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } return ret; }
static int fimc_is_isp_video_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { int ret = 0; struct fimc_is_video_ctx *vctx = file->private_data; dbg_isp("%s\n", __func__); ret = fimc_is_video_streamoff(file, vctx, type); if (ret) merr("fimc_is_video_streamoff is fail(%d)", vctx, ret); return ret; }
static int fimc_is_isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { struct fimc_is_core *isp = video_drvdata(file); strncpy(cap->driver, isp->pdev->name, sizeof(cap->driver) - 1); dbg_isp("%s(devname : %s)\n", __func__, cap->driver); strncpy(cap->card, isp->pdev->name, sizeof(cap->card) - 1); cap->bus_info[0] = 0; cap->version = KERNEL_VERSION(1, 0, 0); cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE; return 0; }
static int fimc_is_isp_video_g_ext_ctrl(struct file *file, void *priv, struct v4l2_ext_controls *ctrls) { int ret = 0; struct v4l2_ext_control *ctrl; dbg_isp("%s\n", __func__); ctrl = ctrls->controls; switch (ctrl->id) { default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } return ret; }
int fimc_is_3a1_video_probe(void *data) { int ret = 0; struct fimc_is_core *core = (struct fimc_is_core *)data; struct fimc_is_video *video = &core->video_3a1; dbg_isp("%s\n", __func__); ret = fimc_is_video_probe(video, data, FIMC_IS_VIDEO_3A1_NAME, FIMC_IS_VIDEO_3A1_NUM, &video->lock, &fimc_is_3a1_video_fops, &fimc_is_3a1_video_ioctl_ops); if (ret != 0) dev_err(&(core->pdev->dev), "%s::Failed to fimc_is_video_probe()\n", __func__); return ret; }
static int fimc_is_isp_video_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { int ret = 0; struct fimc_is_video_ctx *vctx = file->private_data; struct fimc_is_device_ischain *ischain = vctx->device; dbg_isp("%s\n", __func__); switch (ctrl->id) { case V4L2_CID_IS_BDS_WIDTH: ctrl->value = ischain->chain0_width; break; case V4L2_CID_IS_BDS_HEIGHT: ctrl->value = ischain->chain0_height; break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } return ret; }
static int fimc_is_isp_video_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { int ret = 0; int i2c_clk; struct fimc_is_video *video; struct fimc_is_video_ctx *vctx = file->private_data; struct fimc_is_device_ischain *device; struct fimc_is_core *core; BUG_ON(!vctx); BUG_ON(!vctx->device); BUG_ON(!vctx->video); dbg_isp("%s\n", __func__); device = vctx->device; video = vctx->video; core = container_of(video, struct fimc_is_core, video_isp); if (core->resourcemgr.dvfs_ctrl.cur_int_qos == DVFS_L0) i2c_clk = I2C_L0; else i2c_clk = I2C_L1; switch (ctrl->id) { case V4L2_CID_IS_G_CAPABILITY: ret = fimc_is_ischain_g_capability(device, ctrl->value); dbg_isp("V4L2_CID_IS_G_CAPABILITY : %X\n", ctrl->value); break; case V4L2_CID_IS_FORCE_DONE: set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_isp.state); break; case V4L2_CID_IS_DVFS_LOCK: ret = fimc_is_itf_i2c_lock(device, I2C_L0, true); if (ret) { err("fimc_is_itf_i2_clock fail\n"); break; } pm_qos_add_request(&device->user_qos, PM_QOS_DEVICE_THROUGHPUT, ctrl->value); ret = fimc_is_itf_i2c_lock(device, I2C_L0, false); if (ret) { err("fimc_is_itf_i2c_unlock fail\n"); break; } dbg_isp("V4L2_CID_IS_DVFS_LOCK : %d\n", ctrl->value); break; case V4L2_CID_IS_DVFS_UNLOCK: ret = fimc_is_itf_i2c_lock(device, i2c_clk, true); if (ret) { err("fimc_is_itf_i2_clock fail\n"); break; } pm_qos_remove_request(&device->user_qos); ret = fimc_is_itf_i2c_lock(device, i2c_clk, false); if (ret) { err("fimc_is_itf_i2c_unlock fail\n"); break; } dbg_isp("V4L2_CID_IS_DVFS_UNLOCK : %d I2C(%d)\n", ctrl->value, i2c_clk); break; case V4L2_CID_IS_SET_SETFILE: if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) { err("Setting setfile is only avaiable before starting device!! (0x%08x)", ctrl->value); ret = -EINVAL; } else { device->setfile = ctrl->value; } break; case V4L2_CID_IS_COLOR_RANGE: if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) { err("failed to change color range: device started already (0x%08x)", ctrl->value); ret = -EINVAL; } else { device->setfile &= ~FIMC_IS_ISP_CRANGE_MASK; if (ctrl->value) device->setfile |= (FIMC_IS_CRANGE_LIMITED << FIMC_IS_ISP_CRANGE_SHIFT); } break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } return ret; }
static int fimc_is_isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) { dbg_isp("%s\n", __func__); return 0; }
static int fimc_is_isp_video_get_format_mplane(struct file *file, void *fh, struct v4l2_format *format) { dbg_isp("%s\n", __func__); return 0; }
static int fimc_is_isp_video_enum_fmt_mplane(struct file *file, void *priv, struct v4l2_fmtdesc *f) { dbg_isp("%s\n", __func__); return 0; }
static int fimc_is_isp_video_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { int ret = 0; int i2c_clk; struct fimc_is_video *video; struct fimc_is_video_ctx *vctx = file->private_data; struct fimc_is_device_ischain *device; struct fimc_is_core *core; BUG_ON(!vctx); BUG_ON(!vctx->device); BUG_ON(!vctx->video); dbg_isp("%s\n", __func__); device = vctx->device; video = vctx->video; core = container_of(video, struct fimc_is_core, video_isp); if (core->resourcemgr.dvfs_ctrl.cur_int_qos == DVFS_L0) i2c_clk = I2C_L0; else i2c_clk = I2C_L1; switch (ctrl->id) { case V4L2_CID_IS_DEBUG_DUMP: info("Print fimc-is info dump by HAL"); if (device != NULL) { fimc_is_hw_logdump(device->interface); fimc_is_hw_regdump(device->interface); CALL_POPS(device, print_clk, device->pdev); } if (ctrl->value) { err("BUG_ON from HAL"); BUG(); } break; case V4L2_CID_IS_DEBUG_SYNC_LOG: fimc_is_logsync(device->interface, ctrl->value, IS_MSG_TEST_SYNC_LOG); break; case V4L2_CID_IS_HAL_VERSION: if (ctrl->value < 0 || ctrl->value >= IS_HAL_VER_MAX) { merr("hal version(%d) is invalid", vctx, ctrl->value); ret = -EINVAL; goto p_err; } core->resourcemgr.hal_version = ctrl->value; break; case V4L2_CID_IS_G_CAPABILITY: ret = fimc_is_ischain_g_capability(device, ctrl->value); dbg_isp("V4L2_CID_IS_G_CAPABILITY : %X\n", ctrl->value); break; case V4L2_CID_IS_FORCE_DONE: set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_isp.state); break; case V4L2_CID_IS_DVFS_LOCK: ret = fimc_is_itf_i2c_lock(device, I2C_L0, true); if (ret) { err("fimc_is_itf_i2_clock fail\n"); break; } pm_qos_add_request(&device->user_qos, PM_QOS_DEVICE_THROUGHPUT, ctrl->value); ret = fimc_is_itf_i2c_lock(device, I2C_L0, false); if (ret) { err("fimc_is_itf_i2c_unlock fail\n"); break; } dbg_isp("V4L2_CID_IS_DVFS_LOCK : %d\n", ctrl->value); break; case V4L2_CID_IS_DVFS_UNLOCK: ret = fimc_is_itf_i2c_lock(device, i2c_clk, true); if (ret) { err("fimc_is_itf_i2_clock fail\n"); break; } pm_qos_remove_request(&device->user_qos); ret = fimc_is_itf_i2c_lock(device, i2c_clk, false); if (ret) { err("fimc_is_itf_i2c_unlock fail\n"); break; } dbg_isp("V4L2_CID_IS_DVFS_UNLOCK : %d I2C(%d)\n", ctrl->value, i2c_clk); break; case V4L2_CID_IS_SET_SETFILE: if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) { err("Setting setfile is only avaiable before starting device!! (0x%08x)", ctrl->value); ret = -EINVAL; } else { device->setfile = ctrl->value; minfo("[ISP:V] setfile: 0x%08X\n", vctx, ctrl->value); } break; case V4L2_CID_IS_COLOR_RANGE: if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) { err("failed to change color range: device started already (0x%08x)", ctrl->value); ret = -EINVAL; } else { device->color_range &= ~FIMC_IS_ISP_CRANGE_MASK; if (ctrl->value) device->color_range |= (FIMC_IS_CRANGE_LIMITED << FIMC_IS_ISP_CRANGE_SHIFT); } break; case V4L2_CID_IS_MAP_BUFFER: { /* hack for 64bit addr */ ulong value_to_addr; struct fimc_is_queue *queue; struct fimc_is_framemgr *framemgr; struct fimc_is_frame *frame; struct dma_buf *dmabuf; struct dma_buf_attachment *attachment; dma_addr_t dva; struct v4l2_buffer *buf; struct v4l2_plane *planes; size_t size; u32 write, plane, group_id; size = sizeof(struct v4l2_buffer); buf = kmalloc(size, GFP_KERNEL); if (!buf) { merr("kmalloc is fail", vctx); ret = -EINVAL; goto p_err; } /* hack for 64bit addr */ value_to_addr = ctrl->value; ret = copy_from_user(buf, (void __user *)value_to_addr, size); if (ret) { merr("copy_from_user is fail(%d)", vctx, ret); kfree(buf); ret = -EINVAL; goto p_err; } if (!V4L2_TYPE_IS_MULTIPLANAR(buf->type)) { merr("single plane is not supported", vctx); kfree(buf); ret = -EINVAL; goto p_err; } if (buf->index >= FRAMEMGR_MAX_REQUEST) { merr("buffer index is invalid(%d)", vctx, buf->index); kfree(buf); ret = -EINVAL; goto p_err; } if (buf->length > VIDEO_MAX_PLANES) { merr("planes[%d] is invalid", vctx, buf->length); kfree(buf); ret = -EINVAL; goto p_err; } queue = GET_QUEUE(vctx, buf->type); if (queue->vbq->memory != V4L2_MEMORY_DMABUF) { merr("memory type(%d) is not supported", vctx, queue->vbq->memory); kfree(buf); ret = -EINVAL; goto p_err; } size = sizeof(struct v4l2_plane) * buf->length; planes = kmalloc(size, GFP_KERNEL); if (IS_ERR(planes)) { merr("kmalloc is fail(%p)", vctx, planes); kfree(buf); ret = -EINVAL; goto p_err; } ret = copy_from_user(planes, (void __user *)buf->m.planes, size); if (ret) { merr("copy_from_user is fail(%d)", vctx, ret); kfree(planes); kfree(buf); ret = -EINVAL; goto p_err; } framemgr = &queue->framemgr; frame = &framemgr->frame[buf->index]; if (test_bit(FRAME_MAP_MEM, &frame->memory)) { merr("this buffer(%d) is already mapped", vctx, buf->index); kfree(planes); kfree(buf); ret = -EINVAL; goto p_err; } /* only last buffer need to map */ if (buf->length >= 1) { plane = buf->length - 1; } else { merr("buffer length is not correct(%d)", vctx, buf->length); kfree(planes); kfree(buf); ret = -EINVAL; goto p_err; } dmabuf = dma_buf_get(planes[plane].m.fd); if (IS_ERR(dmabuf)) { merr("dma_buf_get is fail(%p)", vctx, dmabuf); kfree(planes); kfree(buf); ret = -EINVAL; goto p_err; } attachment = dma_buf_attach(dmabuf, &device->pdev->dev); if (IS_ERR(attachment)) { merr("dma_buf_attach is fail(%p)", vctx, attachment); kfree(planes); kfree(buf); dma_buf_put(dmabuf); ret = -EINVAL; goto p_err; } write = !V4L2_TYPE_IS_OUTPUT(buf->type); dva = ion_iovmm_map(attachment, 0, dmabuf->size, write, plane); if (IS_ERR_VALUE(dva)) { merr("ion_iovmm_map is fail(%pa)", vctx, &dva); kfree(planes); kfree(buf); dma_buf_detach(dmabuf, attachment); dma_buf_put(dmabuf); ret = -EINVAL; goto p_err; } group_id = GROUP_ID(device->group_isp.id); ret = fimc_is_itf_map(device, group_id, dva, dmabuf->size); if (ret) { merr("fimc_is_itf_map is fail(%d)", vctx, ret); kfree(planes); kfree(buf); dma_buf_detach(dmabuf, attachment); dma_buf_put(dmabuf); goto p_err; } minfo("[ISP:V] buffer%d.plane%d mapping\n", vctx, buf->index, plane); set_bit(FRAME_MAP_MEM, &frame->memory); dma_buf_detach(dmabuf, attachment); dma_buf_put(dmabuf); kfree(planes); kfree(buf); } break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } p_err: return ret; }
static int fimc_is_isp_video_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { int ret = 0; int i2c_clk; struct fimc_is_video_ctx *vctx = file->private_data; struct fimc_is_device_ischain *device; struct fimc_is_core *core; BUG_ON(!vctx); dbg_isp("%s\n", __func__); device = vctx->device; if (!device) { merr("device is NULL", vctx); ret = -EINVAL; goto p_err; } core = vctx->video->core; if (!core) { merr("core is NULL", vctx); ret = -EINVAL; goto p_err; } if (core->clock.dvfs_level == DVFS_L0) i2c_clk = I2C_L0; else i2c_clk = I2C_L1; switch (ctrl->id) { case V4L2_CID_IS_G_CAPABILITY: ret = fimc_is_ischain_g_capability(device, ctrl->value); dbg_isp("V4L2_CID_IS_G_CAPABILITY : %X\n", ctrl->value); break; case V4L2_CID_IS_FORCE_DONE: set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_isp.state); break; case V4L2_CID_IS_DVFS_LOCK: ret = fimc_is_itf_i2c_lock(device, I2C_L0, true); if (ret) { err("fimc_is_itf_i2_clock fail\n"); break; } pm_qos_add_request(&device->user_qos, PM_QOS_DEVICE_THROUGHPUT, ctrl->value); ret = fimc_is_itf_i2c_lock(device, I2C_L0, false); if (ret) { err("fimc_is_itf_i2c_unlock fail\n"); break; } dbg_isp("V4L2_CID_IS_DVFS_LOCK : %d\n", ctrl->value); break; case V4L2_CID_IS_DVFS_UNLOCK: ret = fimc_is_itf_i2c_lock(device, i2c_clk, true); if (ret) { err("fimc_is_itf_i2_clock fail\n"); break; } pm_qos_remove_request(&device->user_qos); ret = fimc_is_itf_i2c_lock(device, i2c_clk, false); if (ret) { err("fimc_is_itf_i2c_unlock fail\n"); break; } dbg_isp("V4L2_CID_IS_DVFS_UNLOCK : %d I2C(%d)\n", ctrl->value, i2c_clk); break; default: err("unsupported ioctl(%d)\n", ctrl->id); ret = -EINVAL; break; } p_err: return ret; }