Lines Matching +full:queue +full:- +full:sizes

1 // SPDX-License-Identifier: GPL-2.0
3 * video-i2c.c - Support for I2C transport video devices
8 * - Panasonic AMG88xx Grid-Eye Sensors
9 * - Melexis MLX90640 Thermal Cameras
23 #include <linux/nvmem-provider.h>
28 #include <media/v4l2-common.h>
29 #include <media/v4l2-device.h>
30 #include <media/v4l2-event.h>
31 #include <media/v4l2-fh.h>
32 #include <media/v4l2-ioctl.h>
33 #include <media/videobuf2-v4l2.h>
34 #include <media/videobuf2-vmalloc.h>
36 #define VIDEO_I2C_DRIVER "video-i2c"
159 return regmap_bulk_read(data->regmap, MLX90640_EEPROM_START_ADDR + offset, val, bytes); in mlx90640_nvram_read()
172 return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf, in amg88xx_xfer()
173 data->chip->buffer_size); in amg88xx_xfer()
178 return regmap_bulk_read(data->regmap, MLX90640_RAM_START_ADDR, buf, in mlx90640_xfer()
179 data->chip->buffer_size); in mlx90640_xfer()
187 if (data->frame_interval.numerator == data->frame_interval.denominator) in amg88xx_setup()
192 return regmap_update_bits(data->regmap, AMG88XX_REG_FPSC, mask, val); in amg88xx_setup()
199 for (n = 0; n < data->chip->num_frame_intervals - 1; n++) { in mlx90640_setup()
200 if (V4L2_FRACT_COMPARE(data->frame_interval, ==, in mlx90640_setup()
201 data->chip->frame_intervals[n])) in mlx90640_setup()
205 idx = data->chip->num_frame_intervals - n - 1; in mlx90640_setup()
207 return regmap_update_bits(data->regmap, MLX90640_REG_CTL1, in mlx90640_setup()
216 ret = regmap_write(data->regmap, AMG88XX_REG_PCTL, AMG88XX_PCTL_NORMAL); in amg88xx_set_power_on()
222 ret = regmap_write(data->regmap, AMG88XX_REG_RST, AMG88XX_RST_INIT); in amg88xx_set_power_on()
228 ret = regmap_write(data->regmap, AMG88XX_REG_RST, AMG88XX_RST_FLAG); in amg88xx_set_power_on()
244 ret = regmap_write(data->regmap, AMG88XX_REG_PCTL, AMG88XX_PCTL_SLEEP); in amg88xx_set_power_off()
286 tmp = pm_runtime_resume_and_get(regmap_get_device(data->regmap)); in amg88xx_read()
290 tmp = regmap_bulk_read(data->regmap, AMG88XX_REG_TTHL, &buf, 2); in amg88xx_read()
291 pm_runtime_put_autosuspend(regmap_get_device(data->regmap)); in amg88xx_read()
303 tmp = -(tmp & 0x7ff); in amg88xx_read()
322 struct device *dev = regmap_get_device(data->regmap); in amg88xx_hwmon_init()
393 unsigned int sizes[], struct device *alloc_devs[]) in queue_setup() argument
396 unsigned int size = data->chip->buffer_size; in queue_setup()
400 *nbuffers = 2 - q_num_bufs; in queue_setup()
403 return sizes[0] < size ? -EINVAL : 0; in queue_setup()
406 sizes[0] = size; in queue_setup()
414 struct video_i2c_data *data = vb2_get_drv_priv(vb->vb2_queue); in buffer_prepare()
415 unsigned int size = data->chip->buffer_size; in buffer_prepare()
418 return -EINVAL; in buffer_prepare()
420 vbuf->field = V4L2_FIELD_NONE; in buffer_prepare()
429 struct video_i2c_data *data = vb2_get_drv_priv(vb->vb2_queue); in buffer_queue()
433 spin_lock(&data->slock); in buffer_queue()
434 list_add_tail(&buf->list, &data->vid_cap_active); in buffer_queue()
435 spin_unlock(&data->slock); in buffer_queue()
441 u32 delay = mult_frac(1000000UL, data->frame_interval.numerator, in video_i2c_thread_vid_cap()
442 data->frame_interval.denominator); in video_i2c_thread_vid_cap()
454 spin_lock(&data->slock); in video_i2c_thread_vid_cap()
456 if (!list_empty(&data->vid_cap_active)) { in video_i2c_thread_vid_cap()
457 vid_cap_buf = list_last_entry(&data->vid_cap_active, in video_i2c_thread_vid_cap()
459 list_del(&vid_cap_buf->list); in video_i2c_thread_vid_cap()
462 spin_unlock(&data->slock); in video_i2c_thread_vid_cap()
465 struct vb2_buffer *vb2_buf = &vid_cap_buf->vb.vb2_buf; in video_i2c_thread_vid_cap()
469 ret = data->chip->xfer(data, vbuf); in video_i2c_thread_vid_cap()
470 vb2_buf->timestamp = ktime_get_ns(); in video_i2c_thread_vid_cap()
471 vid_cap_buf->vb.sequence = data->sequence++; in video_i2c_thread_vid_cap()
479 schedule_delay = end_us - current_us; in video_i2c_thread_vid_cap()
494 spin_lock(&data->slock); in video_i2c_del_list()
496 list_for_each_entry_safe(buf, tmp, &data->vid_cap_active, list) { in video_i2c_del_list()
497 list_del(&buf->list); in video_i2c_del_list()
498 vb2_buffer_done(&buf->vb.vb2_buf, state); in video_i2c_del_list()
501 spin_unlock(&data->slock); in video_i2c_del_list()
507 struct device *dev = regmap_get_device(data->regmap); in start_streaming()
510 if (data->kthread_vid_cap) in start_streaming()
517 ret = data->chip->setup(data); in start_streaming()
521 data->sequence = 0; in start_streaming()
522 data->kthread_vid_cap = kthread_run(video_i2c_thread_vid_cap, data, in start_streaming()
523 "%s-vid-cap", data->v4l2_dev.name); in start_streaming()
524 ret = PTR_ERR_OR_ZERO(data->kthread_vid_cap); in start_streaming()
540 if (data->kthread_vid_cap == NULL) in stop_streaming()
543 kthread_stop(data->kthread_vid_cap); in stop_streaming()
544 data->kthread_vid_cap = NULL; in stop_streaming()
545 pm_runtime_put_autosuspend(regmap_get_device(data->regmap)); in stop_streaming()
562 struct device *dev = regmap_get_device(data->regmap); in video_i2c_querycap()
565 strscpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver)); in video_i2c_querycap()
566 strscpy(vcap->card, data->vdev.name, sizeof(vcap->card)); in video_i2c_querycap()
568 sprintf(vcap->bus_info, "I2C:%d-%d", client->adapter->nr, client->addr); in video_i2c_querycap()
582 return (inp > 0) ? -EINVAL : 0; in video_i2c_s_input()
588 if (vin->index > 0) in video_i2c_enum_input()
589 return -EINVAL; in video_i2c_enum_input()
591 strscpy(vin->name, "Camera", sizeof(vin->name)); in video_i2c_enum_input()
593 vin->type = V4L2_INPUT_TYPE_CAMERA; in video_i2c_enum_input()
602 enum v4l2_buf_type type = fmt->type; in video_i2c_enum_fmt_vid_cap()
604 if (fmt->index > 0) in video_i2c_enum_fmt_vid_cap()
605 return -EINVAL; in video_i2c_enum_fmt_vid_cap()
607 *fmt = *data->chip->format; in video_i2c_enum_fmt_vid_cap()
608 fmt->type = type; in video_i2c_enum_fmt_vid_cap()
617 const struct v4l2_frmsize_discrete *size = data->chip->size; in video_i2c_enum_framesizes()
620 if (fsize->index > 0) in video_i2c_enum_framesizes()
621 return -EINVAL; in video_i2c_enum_framesizes()
623 if (fsize->pixel_format != data->chip->format->pixelformat) in video_i2c_enum_framesizes()
624 return -EINVAL; in video_i2c_enum_framesizes()
626 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; in video_i2c_enum_framesizes()
627 fsize->discrete.width = size->width; in video_i2c_enum_framesizes()
628 fsize->discrete.height = size->height; in video_i2c_enum_framesizes()
637 const struct v4l2_frmsize_discrete *size = data->chip->size; in video_i2c_enum_frameintervals()
639 if (fe->index >= data->chip->num_frame_intervals) in video_i2c_enum_frameintervals()
640 return -EINVAL; in video_i2c_enum_frameintervals()
642 if (fe->width != size->width || fe->height != size->height) in video_i2c_enum_frameintervals()
643 return -EINVAL; in video_i2c_enum_frameintervals()
645 fe->type = V4L2_FRMIVAL_TYPE_DISCRETE; in video_i2c_enum_frameintervals()
646 fe->discrete = data->chip->frame_intervals[fe->index]; in video_i2c_enum_frameintervals()
655 const struct v4l2_frmsize_discrete *size = data->chip->size; in video_i2c_try_fmt_vid_cap()
656 struct v4l2_pix_format *pix = &fmt->fmt.pix; in video_i2c_try_fmt_vid_cap()
657 unsigned int bpp = data->chip->bpp / 8; in video_i2c_try_fmt_vid_cap()
659 pix->width = size->width; in video_i2c_try_fmt_vid_cap()
660 pix->height = size->height; in video_i2c_try_fmt_vid_cap()
661 pix->pixelformat = data->chip->format->pixelformat; in video_i2c_try_fmt_vid_cap()
662 pix->field = V4L2_FIELD_NONE; in video_i2c_try_fmt_vid_cap()
663 pix->bytesperline = pix->width * bpp; in video_i2c_try_fmt_vid_cap()
664 pix->sizeimage = pix->bytesperline * pix->height; in video_i2c_try_fmt_vid_cap()
665 pix->colorspace = V4L2_COLORSPACE_RAW; in video_i2c_try_fmt_vid_cap()
675 if (vb2_is_busy(&data->vb_vidq)) in video_i2c_s_fmt_vid_cap()
676 return -EBUSY; in video_i2c_s_fmt_vid_cap()
686 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) in video_i2c_g_parm()
687 return -EINVAL; in video_i2c_g_parm()
689 parm->parm.capture.readbuffers = 1; in video_i2c_g_parm()
690 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; in video_i2c_g_parm()
691 parm->parm.capture.timeperframe = data->frame_interval; in video_i2c_g_parm()
702 for (i = 0; i < data->chip->num_frame_intervals - 1; i++) { in video_i2c_s_parm()
703 if (V4L2_FRACT_COMPARE(parm->parm.capture.timeperframe, <=, in video_i2c_s_parm()
704 data->chip->frame_intervals[i])) in video_i2c_s_parm()
707 data->frame_interval = data->chip->frame_intervals[i]; in video_i2c_s_parm()
739 v4l2_device_unregister(&data->v4l2_dev); in video_i2c_release()
740 mutex_destroy(&data->lock); in video_i2c_release()
741 mutex_destroy(&data->queue_lock); in video_i2c_release()
742 regmap_exit(data->regmap); in video_i2c_release()
750 struct vb2_queue *queue; in video_i2c_probe() local
751 int ret = -ENODEV; in video_i2c_probe()
755 return -ENOMEM; in video_i2c_probe()
757 data->chip = i2c_get_match_data(client); in video_i2c_probe()
758 if (!data->chip) in video_i2c_probe()
761 data->regmap = regmap_init_i2c(client, data->chip->regmap_config); in video_i2c_probe()
762 if (IS_ERR(data->regmap)) { in video_i2c_probe()
763 ret = PTR_ERR(data->regmap); in video_i2c_probe()
767 v4l2_dev = &data->v4l2_dev; in video_i2c_probe()
768 strscpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name)); in video_i2c_probe()
770 ret = v4l2_device_register(&client->dev, v4l2_dev); in video_i2c_probe()
774 mutex_init(&data->lock); in video_i2c_probe()
775 mutex_init(&data->queue_lock); in video_i2c_probe()
777 queue = &data->vb_vidq; in video_i2c_probe()
778 queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in video_i2c_probe()
779 queue->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR | VB2_READ; in video_i2c_probe()
780 queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; in video_i2c_probe()
781 queue->drv_priv = data; in video_i2c_probe()
782 queue->buf_struct_size = sizeof(struct video_i2c_buffer); in video_i2c_probe()
783 queue->min_queued_buffers = 1; in video_i2c_probe()
784 queue->ops = &video_i2c_video_qops; in video_i2c_probe()
785 queue->mem_ops = &vb2_vmalloc_memops; in video_i2c_probe()
786 queue->lock = &data->queue_lock; in video_i2c_probe()
788 ret = vb2_queue_init(queue); in video_i2c_probe()
792 data->vdev.queue = queue; in video_i2c_probe()
794 snprintf(data->vdev.name, sizeof(data->vdev.name), in video_i2c_probe()
795 "I2C %d-%d Transport Video", in video_i2c_probe()
796 client->adapter->nr, client->addr); in video_i2c_probe()
798 data->vdev.v4l2_dev = v4l2_dev; in video_i2c_probe()
799 data->vdev.fops = &video_i2c_fops; in video_i2c_probe()
800 data->vdev.lock = &data->lock; in video_i2c_probe()
801 data->vdev.ioctl_ops = &video_i2c_ioctl_ops; in video_i2c_probe()
802 data->vdev.release = video_i2c_release; in video_i2c_probe()
803 data->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | in video_i2c_probe()
806 spin_lock_init(&data->slock); in video_i2c_probe()
807 INIT_LIST_HEAD(&data->vid_cap_active); in video_i2c_probe()
809 data->frame_interval = data->chip->frame_intervals[0]; in video_i2c_probe()
811 video_set_drvdata(&data->vdev, data); in video_i2c_probe()
814 if (data->chip->set_power) { in video_i2c_probe()
815 ret = data->chip->set_power(data, true); in video_i2c_probe()
820 pm_runtime_get_noresume(&client->dev); in video_i2c_probe()
821 pm_runtime_set_active(&client->dev); in video_i2c_probe()
822 pm_runtime_enable(&client->dev); in video_i2c_probe()
823 pm_runtime_set_autosuspend_delay(&client->dev, 2000); in video_i2c_probe()
824 pm_runtime_use_autosuspend(&client->dev); in video_i2c_probe()
826 if (data->chip->hwmon_init) { in video_i2c_probe()
827 ret = data->chip->hwmon_init(data); in video_i2c_probe()
829 dev_warn(&client->dev, in video_i2c_probe()
834 if (data->chip->nvmem_config) { in video_i2c_probe()
835 struct nvmem_config *config = data->chip->nvmem_config; in video_i2c_probe()
838 config->priv = data; in video_i2c_probe()
839 config->dev = &client->dev; in video_i2c_probe()
841 device = devm_nvmem_register(&client->dev, config); in video_i2c_probe()
844 dev_warn(&client->dev, in video_i2c_probe()
849 ret = video_register_device(&data->vdev, VFL_TYPE_VIDEO, -1); in video_i2c_probe()
853 pm_runtime_put_autosuspend(&client->dev); in video_i2c_probe()
858 pm_runtime_disable(&client->dev); in video_i2c_probe()
859 pm_runtime_set_suspended(&client->dev); in video_i2c_probe()
860 pm_runtime_put_noidle(&client->dev); in video_i2c_probe()
862 if (data->chip->set_power) in video_i2c_probe()
863 data->chip->set_power(data, false); in video_i2c_probe()
867 mutex_destroy(&data->lock); in video_i2c_probe()
868 mutex_destroy(&data->queue_lock); in video_i2c_probe()
871 regmap_exit(data->regmap); in video_i2c_probe()
883 pm_runtime_get_sync(&client->dev); in video_i2c_remove()
884 pm_runtime_disable(&client->dev); in video_i2c_remove()
885 pm_runtime_set_suspended(&client->dev); in video_i2c_remove()
886 pm_runtime_put_noidle(&client->dev); in video_i2c_remove()
888 if (data->chip->set_power) in video_i2c_remove()
889 data->chip->set_power(data, false); in video_i2c_remove()
891 video_unregister_device(&data->vdev); in video_i2c_remove()
900 if (!data->chip->set_power) in video_i2c_pm_runtime_suspend()
903 return data->chip->set_power(data, false); in video_i2c_pm_runtime_suspend()
910 if (!data->chip->set_power) in video_i2c_pm_runtime_resume()
913 return data->chip->set_power(data, true); in video_i2c_pm_runtime_resume()