Lines Matching +full:vga +full:- +full:format
1 // SPDX-License-Identifier: GPL-2.0-only
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-ioctl.h>
20 #include <media/v4l2-ctrls.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-image-sizes.h>
24 #include <media/videobuf2-dma-sg.h>
26 #include <linux/dma-mapping.h>
28 #include <linux/via-core.h>
37 #include "via-camera.h"
39 MODULE_ALIAS("platform:viafb-camera");
41 MODULE_DESCRIPTION("VIA framebuffer-based camera controller driver");
52 …efuse to load if the XO 1.5 serial port is enabled. Set this option to force-enable the camera.");
87 u8 __iomem *cb_addrs[3]; /* Kernel-space addresses */
93 * Video format information. sensor_format is kept in a form
95 * sensor in VGA resolution, though, and let the controller
106 /* common v4l buffer stuff -- must be first */
128 v4l2_subdev_call(cam->sensor, optype, func, ##args)
134 dev_err(&(cam)->platdev->dev, fmt, ##arg)
136 dev_warn(&(cam)->platdev->dev, fmt, ##arg)
138 dev_dbg(&(cam)->platdev->dev, fmt, ##arg)
141 * Format handling. This is ripped almost directly from Hans's changes
143 * didn't need to know anything about the format except its byte depth;
170 /* Not found? Then return the first format. */ in via_find_format()
175 /*--------------------------------------------------------------------------*/
177 * Sensor power/reset management. This piece is OLPC-specific for
182 struct device *dev = &cam->platdev->dev; in via_sensor_power_setup()
184 cam->power_gpio = devm_gpiod_get(dev, "VGPIO3", GPIOD_OUT_LOW); in via_sensor_power_setup()
185 if (IS_ERR(cam->power_gpio)) in via_sensor_power_setup()
186 return dev_err_probe(dev, PTR_ERR(cam->power_gpio), in via_sensor_power_setup()
190 cam->reset_gpio = devm_gpiod_get(dev, "VGPIO2", GPIOD_OUT_HIGH); in via_sensor_power_setup()
191 if (IS_ERR(cam->reset_gpio)) in via_sensor_power_setup()
192 return dev_err_probe(dev, PTR_ERR(cam->reset_gpio), in via_sensor_power_setup()
203 gpiod_set_value(cam->power_gpio, 1); in via_sensor_power_up()
204 gpiod_set_value(cam->reset_gpio, 1); in via_sensor_power_up()
206 gpiod_set_value(cam->reset_gpio, 0); in via_sensor_power_up()
212 gpiod_set_value(cam->power_gpio, 0); in via_sensor_power_down()
213 gpiod_set_value(cam->reset_gpio, 1); in via_sensor_power_down()
222 /* --------------------------------------------------------------------------*/
235 return v4l2_s_ctrl(NULL, cam->sensor->ctrl_handler, &ctrl); in viacam_set_flip()
244 struct v4l2_subdev_format format = { in viacam_configure_sensor() local
249 v4l2_fill_mbus_format(&format.format, &cam->sensor_format, cam->mbus_code); in viacam_configure_sensor()
252 ret = sensor_call(cam, pad, set_fmt, NULL, &format); in viacam_configure_sensor()
254 * OV7670 does weird things if flip is set *before* format... in viacam_configure_sensor()
263 /* --------------------------------------------------------------------------*/
269 * 0x300-350 range.
274 iowrite32(value, cam->mmio + reg); in viacam_write_reg()
279 return ioread32(cam->mmio + reg); in viacam_read_reg()
292 /* --------------------------------------------------------------------------*/
305 spin_lock(&cam->viadev->reg_lock); in viacam_quick_irq()
312 spin_unlock(&cam->viadev->reg_lock); in viacam_quick_irq()
321 if (cam->opstate != S_RUNNING) in viacam_next_buffer()
323 if (list_empty(&cam->buffer_queue)) in viacam_next_buffer()
325 return list_entry(cam->buffer_queue.next, struct via_buffer, queue); in viacam_next_buffer()
338 mutex_lock(&cam->lock); in viacam_irq()
350 bufn -= 1; in viacam_irq()
352 bufn = cam->n_cap_bufs - 1; in viacam_irq()
356 sgt = vb2_dma_sg_plane_desc(&vb->vbuf.vb2_buf, 0); in viacam_irq()
357 vb->vbuf.vb2_buf.timestamp = ktime_get_ns(); in viacam_irq()
358 viafb_dma_copy_out_sg(cam->cb_offsets[bufn], sgt->sgl, sgt->nents); in viacam_irq()
359 vb->vbuf.sequence = cam->sequence++; in viacam_irq()
360 vb->vbuf.field = V4L2_FIELD_NONE; in viacam_irq()
361 list_del(&vb->queue); in viacam_irq()
362 vb2_buffer_done(&vb->vbuf.vb2_buf, VB2_BUF_STATE_DONE); in viacam_irq()
364 mutex_unlock(&cam->lock); in viacam_irq()
374 * the via-core level.
391 /* --------------------------------------------------------------------------*/
399 int nbuf = cam->viadev->camera_fbmem_size/cam->sensor_format.sizeimage; in viacam_ctlr_cbufs()
407 cam->n_cap_bufs = 3; in viacam_ctlr_cbufs()
411 cam->n_cap_bufs = 2; in viacam_ctlr_cbufs()
415 return -ENOMEM; in viacam_ctlr_cbufs()
420 offset = cam->fb_offset; in viacam_ctlr_cbufs()
421 for (i = 0; i < cam->n_cap_bufs; i++) { in viacam_ctlr_cbufs()
422 cam->cb_offsets[i] = offset; in viacam_ctlr_cbufs()
423 cam->cb_addrs[i] = cam->fbmem + offset; in viacam_ctlr_cbufs()
425 offset += cam->sensor_format.sizeimage; in viacam_ctlr_cbufs()
444 * the 3x4 VGA scaling factor, the image will distort. We
452 if (cam->user_format.width == VGA_WIDTH) in viacam_set_scale()
455 sf = (cam->user_format.width*2048)/VGA_WIDTH; in viacam_set_scale()
458 if (cam->user_format.height < VGA_HEIGHT) { in viacam_set_scale()
459 sf = (1024*cam->user_format.height)/VGA_HEIGHT; in viacam_set_scale()
467 * Configure image-related information into the capture engine.
474 * Disable clock before messing with stuff - from the via in viacam_ctlr_image()
479 * Set up the controller for VGA resolution, modulo magic in viacam_ctlr_image()
489 (cam->sensor_format.height << 16) | in viacam_ctlr_image()
490 (cam->sensor_format.bytesperline >> 3)); in viacam_ctlr_image()
493 cam->user_format.bytesperline & VCR_VS_STRIDE); in viacam_ctlr_image()
503 VCR_CI_FLDINV | /* OLPC-specific? */ in viacam_ctlr_image()
504 VCR_CI_VREFINV | /* OLPC-specific? */ in viacam_ctlr_image()
507 if (cam->n_cap_bufs == 3) in viacam_ctlr_image()
512 if (cam->user_format.pixelformat == V4L2_PIX_FMT_YUYV) in viacam_ctlr_image()
525 spin_lock_irqsave(&cam->viadev->reg_lock, flags); in viacam_config_controller()
529 spin_unlock_irqrestore(&cam->viadev->reg_lock, flags); in viacam_config_controller()
530 clear_bit(CF_CONFIG_NEEDED, &cam->flags); in viacam_config_controller()
539 spin_lock_irq(&cam->viadev->reg_lock); in viacam_start_engine()
543 cam->opstate = S_RUNNING; in viacam_start_engine()
544 spin_unlock_irq(&cam->viadev->reg_lock); in viacam_start_engine()
550 spin_lock_irq(&cam->viadev->reg_lock); in viacam_stop_engine()
554 cam->opstate = S_IDLE; in viacam_stop_engine()
555 spin_unlock_irq(&cam->viadev->reg_lock); in viacam_stop_engine()
559 /* --------------------------------------------------------------------------*/
571 struct via_camera *cam = vb2_get_drv_priv(vb->vb2_queue); in viacam_vb2_queue()
574 list_add_tail(&via->queue, &cam->buffer_queue); in viacam_vb2_queue()
579 struct via_camera *cam = vb2_get_drv_priv(vb->vb2_queue); in viacam_vb2_prepare()
581 if (vb2_plane_size(vb, 0) < cam->user_format.sizeimage) { in viacam_vb2_prepare()
585 cam->user_format.sizeimage); in viacam_vb2_prepare()
586 return -EINVAL; in viacam_vb2_prepare()
589 vb2_set_plane_payload(vb, 0, cam->user_format.sizeimage); in viacam_vb2_prepare()
600 int size = cam->user_format.sizeimage; in viacam_vb2_queue_setup()
603 return sizes[0] < size ? -EINVAL : 0; in viacam_vb2_queue_setup()
616 if (cam->opstate != S_IDLE) { in viacam_vb2_start_streaming()
617 ret = -EBUSY; in viacam_vb2_start_streaming()
623 if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) { in viacam_vb2_start_streaming()
631 cam->sequence = 0; in viacam_vb2_start_streaming()
638 cpu_latency_qos_add_request(&cam->qos_request, 50); in viacam_vb2_start_streaming()
642 list_for_each_entry_safe(buf, tmp, &cam->buffer_queue, queue) { in viacam_vb2_start_streaming()
643 list_del(&buf->queue); in viacam_vb2_start_streaming()
644 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED); in viacam_vb2_start_streaming()
654 cpu_latency_qos_remove_request(&cam->qos_request); in viacam_vb2_stop_streaming()
657 list_for_each_entry_safe(buf, tmp, &cam->buffer_queue, queue) { in viacam_vb2_stop_streaming()
658 list_del(&buf->queue); in viacam_vb2_stop_streaming()
659 vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); in viacam_vb2_stop_streaming()
673 /* --------------------------------------------------------------------------*/
685 mutex_lock(&cam->lock); in viacam_open()
697 set_bit(CF_CONFIG_NEEDED, &cam->flags); in viacam_open()
700 mutex_unlock(&cam->lock); in viacam_open()
709 mutex_lock(&cam->lock); in viacam_release()
719 mutex_unlock(&cam->lock); in viacam_release()
733 /*----------------------------------------------------------------------------*/
744 if (input->index != 0) in viacam_enum_input()
745 return -EINVAL; in viacam_enum_input()
747 input->type = V4L2_INPUT_TYPE_CAMERA; in viacam_enum_input()
748 strscpy(input->name, "Camera", sizeof(input->name)); in viacam_enum_input()
761 return -EINVAL; in viacam_s_input()
766 * Video format stuff. Here is our default format until
784 if (fmt->index >= N_VIA_FMTS) in viacam_enum_fmt_vid_cap()
785 return -EINVAL; in viacam_enum_fmt_vid_cap()
786 fmt->pixelformat = via_formats[fmt->index].pixelformat; in viacam_enum_fmt_vid_cap()
792 * sensor to VGA.
798 if (userfmt->width < QCIF_WIDTH || userfmt->height < QCIF_HEIGHT) { in viacam_fmt_pre()
799 userfmt->width = QCIF_WIDTH; in viacam_fmt_pre()
800 userfmt->height = QCIF_HEIGHT; in viacam_fmt_pre()
802 if (userfmt->width > VGA_WIDTH || userfmt->height > VGA_HEIGHT) { in viacam_fmt_pre()
803 userfmt->width = VGA_WIDTH; in viacam_fmt_pre()
804 userfmt->height = VGA_HEIGHT; in viacam_fmt_pre()
806 sensorfmt->width = VGA_WIDTH; in viacam_fmt_pre()
807 sensorfmt->height = VGA_HEIGHT; in viacam_fmt_pre()
813 struct via_format *f = via_find_format(userfmt->pixelformat); in viacam_fmt_post()
815 sensorfmt->bytesperline = sensorfmt->width * f->bpp; in viacam_fmt_post()
816 sensorfmt->sizeimage = sensorfmt->height * sensorfmt->bytesperline; in viacam_fmt_post()
817 userfmt->pixelformat = sensorfmt->pixelformat; in viacam_fmt_post()
818 userfmt->field = sensorfmt->field; in viacam_fmt_post()
819 userfmt->bytesperline = 2 * userfmt->width; in viacam_fmt_post()
820 userfmt->sizeimage = userfmt->bytesperline * userfmt->height; in viacam_fmt_post()
821 userfmt->colorspace = sensorfmt->colorspace; in viacam_fmt_post()
822 userfmt->ycbcr_enc = sensorfmt->ycbcr_enc; in viacam_fmt_post()
823 userfmt->quantization = sensorfmt->quantization; in viacam_fmt_post()
824 userfmt->xfer_func = sensorfmt->xfer_func; in viacam_fmt_post()
829 * The real work of figuring out a workable format.
839 struct v4l2_subdev_format format = { in viacam_do_try_fmt() local
842 struct via_format *f = via_find_format(upix->pixelformat); in viacam_do_try_fmt()
844 upix->pixelformat = f->pixelformat; in viacam_do_try_fmt()
846 v4l2_fill_mbus_format(&format.format, spix, f->mbus_code); in viacam_do_try_fmt()
847 ret = sensor_call(cam, pad, set_fmt, &pad_state, &format); in viacam_do_try_fmt()
848 v4l2_fill_pix_format(spix, &format.format); in viacam_do_try_fmt()
861 return viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); in viacam_try_fmt_vid_cap()
870 fmt->fmt.pix = cam->user_format; in viacam_g_fmt_vid_cap()
880 struct via_format *f = via_find_format(fmt->fmt.pix.pixelformat); in viacam_s_fmt_vid_cap()
886 if (cam->opstate != S_IDLE) in viacam_s_fmt_vid_cap()
887 return -EBUSY; in viacam_s_fmt_vid_cap()
892 ret = viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); in viacam_s_fmt_vid_cap()
896 * OK, let's commit to the new format. in viacam_s_fmt_vid_cap()
898 cam->user_format = fmt->fmt.pix; in viacam_s_fmt_vid_cap()
899 cam->sensor_format = sfmt.fmt.pix; in viacam_s_fmt_vid_cap()
900 cam->mbus_code = f->mbus_code; in viacam_s_fmt_vid_cap()
910 strscpy(cap->driver, "via-camera", sizeof(cap->driver)); in viacam_querycap()
911 strscpy(cap->card, "via-camera", sizeof(cap->card)); in viacam_querycap()
912 strscpy(cap->bus_info, "platform:via-camera", sizeof(cap->bus_info)); in viacam_querycap()
923 return v4l2_g_parm_cap(video_devdata(filp), cam->sensor, parm); in viacam_g_parm()
931 return v4l2_s_parm_cap(video_devdata(filp), cam->sensor, parm); in viacam_s_parm()
939 if (sizes->index != 0) in viacam_enum_framesizes()
940 return -EINVAL; in viacam_enum_framesizes()
942 if (sizes->pixel_format == via_formats[i].pixelformat) in viacam_enum_framesizes()
945 return -EINVAL; in viacam_enum_framesizes()
946 sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; in viacam_enum_framesizes()
947 sizes->stepwise.min_width = QCIF_WIDTH; in viacam_enum_framesizes()
948 sizes->stepwise.min_height = QCIF_HEIGHT; in viacam_enum_framesizes()
949 sizes->stepwise.max_width = VGA_WIDTH; in viacam_enum_framesizes()
950 sizes->stepwise.max_height = VGA_HEIGHT; in viacam_enum_framesizes()
951 sizes->stepwise.step_width = sizes->stepwise.step_height = 1; in viacam_enum_framesizes()
960 .index = interval->index, in viacam_enum_frameintervals()
961 .code = cam->mbus_code, in viacam_enum_frameintervals()
962 .width = cam->sensor_format.width, in viacam_enum_frameintervals()
963 .height = cam->sensor_format.height, in viacam_enum_frameintervals()
970 if (interval->pixel_format == via_formats[i].pixelformat) in viacam_enum_frameintervals()
973 return -EINVAL; in viacam_enum_frameintervals()
974 if (interval->width < QCIF_WIDTH || interval->width > VGA_WIDTH || in viacam_enum_frameintervals()
975 interval->height < QCIF_HEIGHT || interval->height > VGA_HEIGHT) in viacam_enum_frameintervals()
976 return -EINVAL; in viacam_enum_frameintervals()
980 interval->type = V4L2_FRMIVAL_TYPE_DISCRETE; in viacam_enum_frameintervals()
981 interval->discrete = fie.interval; in viacam_enum_frameintervals()
1011 /*----------------------------------------------------------------------------*/
1021 enum viacam_opstate state = cam->opstate; in viacam_suspend()
1023 if (cam->opstate != S_IDLE) { in viacam_suspend()
1025 cam->opstate = state; /* So resume restarts */ in viacam_suspend()
1042 set_bit(CF_CONFIG_NEEDED, &cam->flags); in viacam_resume()
1046 if (!list_empty(&cam->vdev.fh_list)) in viacam_resume()
1053 if (cam->opstate != S_IDLE) { in viacam_resume()
1054 mutex_lock(&cam->lock); in viacam_resume()
1058 mutex_unlock(&cam->lock); in viacam_resume()
1078 .name = "via-camera",
1079 .minor = -1,
1122 /* The XO-1.5 (only known user) clocks the camera at 90MHz. */
1130 struct viafb_dev *viadev = pdev->dev.platform_data; in viacam_probe()
1149 * with less than two frames of VGA 16-bit data. in viacam_probe()
1154 if (viadev->camera_fbmem_size < (VGA_HEIGHT*VGA_WIDTH*4)) { in viacam_probe()
1156 return -ENOMEM; in viacam_probe()
1158 if (viadev->engine_mmio == NULL) { in viacam_probe()
1160 return -ENOMEM; in viacam_probe()
1164 return -EBUSY; in viacam_probe()
1171 return -ENOMEM; in viacam_probe()
1173 cam->platdev = pdev; in viacam_probe()
1174 cam->viadev = viadev; in viacam_probe()
1175 cam->opstate = S_IDLE; in viacam_probe()
1176 cam->user_format = cam->sensor_format = viacam_def_pix_format; in viacam_probe()
1177 mutex_init(&cam->lock); in viacam_probe()
1178 INIT_LIST_HEAD(&cam->buffer_queue); in viacam_probe()
1179 cam->mmio = viadev->engine_mmio; in viacam_probe()
1180 cam->fbmem = viadev->fbmem; in viacam_probe()
1181 cam->fb_offset = viadev->camera_fbmem_offset; in viacam_probe()
1182 cam->flags = 1 << CF_CONFIG_NEEDED; in viacam_probe()
1183 cam->mbus_code = via_def_mbus_code; in viacam_probe()
1187 ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); in viacam_probe()
1189 dev_err(&pdev->dev, "Unable to register v4l2 device\n"); in viacam_probe()
1192 ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10); in viacam_probe()
1195 cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler; in viacam_probe()
1199 pdev->dev.dma_mask = &viadev->pdev->dma_mask; in viacam_probe()
1200 ret = dma_set_mask(&pdev->dev, 0xffffffff); in viacam_probe()
1219 * is OLPC-specific. 0x42 assumption is ov7670-specific. in viacam_probe()
1222 cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev, sensor_adapter, in viacam_probe()
1224 if (cam->sensor == NULL) { in viacam_probe()
1225 dev_err(&pdev->dev, "Unable to find the sensor!\n"); in viacam_probe()
1226 ret = -ENODEV; in viacam_probe()
1233 ret = request_threaded_irq(viadev->pdev->irq, viacam_quick_irq, in viacam_probe()
1234 viacam_irq, IRQF_SHARED, "via-camera", cam); in viacam_probe()
1238 vq = &cam->vq; in viacam_probe()
1239 vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; in viacam_probe()
1240 vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; in viacam_probe()
1241 vq->drv_priv = cam; in viacam_probe()
1242 vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; in viacam_probe()
1243 vq->buf_struct_size = sizeof(struct via_buffer); in viacam_probe()
1244 vq->dev = cam->v4l2_dev.dev; in viacam_probe()
1246 vq->ops = &viacam_vb2_ops; in viacam_probe()
1247 vq->mem_ops = &vb2_dma_sg_memops; in viacam_probe()
1248 vq->lock = &cam->lock; in viacam_probe()
1254 cam->vdev = viacam_v4l_template; in viacam_probe()
1255 cam->vdev.v4l2_dev = &cam->v4l2_dev; in viacam_probe()
1256 cam->vdev.lock = &cam->lock; in viacam_probe()
1257 cam->vdev.queue = vq; in viacam_probe()
1258 video_set_drvdata(&cam->vdev, cam); in viacam_probe()
1259 ret = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1); in viacam_probe()
1276 free_irq(viadev->pdev->irq, cam); in viacam_probe()
1280 v4l2_ctrl_handler_free(&cam->ctrl_handler); in viacam_probe()
1282 v4l2_device_unregister(&cam->v4l2_dev); in viacam_probe()
1291 struct viafb_dev *viadev = pdev->dev.platform_data; in viacam_remove()
1293 video_unregister_device(&cam->vdev); in viacam_remove()
1294 v4l2_device_unregister(&cam->v4l2_dev); in viacam_remove()
1298 free_irq(viadev->pdev->irq, cam); in viacam_remove()
1300 v4l2_ctrl_handler_free(&cam->ctrl_handler); in viacam_remove()
1307 .name = "viafb-camera",