Lines Matching +full:simple +full:- +full:framebuffer
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-ioctl.h>
20 #include <media/v4l2-chip-ident.h>
21 #include <media/videobuf-dma-sg.h>
23 #include <linux/dma-mapping.h>
25 #include <linux/via-core.h>
26 #include <linux/via-gpio.h>
30 #include "via-camera.h"
32 MODULE_ALIAS("platform:viafb-camera");
34 MODULE_DESCRIPTION("VIA framebuffer-based camera controller driver");
48 "to force-enable the camera.");
90 u8 *cb_addrs[3]; /* Kernel-space addresses */
129 v4l2_subdev_call(cam->sensor, optype, func, ##args)
135 dev_err(&(cam)->platdev->dev, fmt, ##arg);
137 dev_warn(&(cam)->platdev->dev, fmt, ##arg);
139 dev_dbg(&(cam)->platdev->dev, fmt, ##arg);
178 /*--------------------------------------------------------------------------*/
180 * Sensor power/reset management. This piece is OLPC-specific for
187 cam->power_gpio = viafb_gpio_lookup("VGPIO3"); in via_sensor_power_setup()
188 cam->reset_gpio = viafb_gpio_lookup("VGPIO2"); in via_sensor_power_setup()
189 if (cam->power_gpio < 0 || cam->reset_gpio < 0) { in via_sensor_power_setup()
190 dev_err(&cam->platdev->dev, "Unable to find GPIO lines\n"); in via_sensor_power_setup()
191 return -EINVAL; in via_sensor_power_setup()
193 ret = gpio_request(cam->power_gpio, "viafb-camera"); in via_sensor_power_setup()
195 dev_err(&cam->platdev->dev, "Unable to request power GPIO\n"); in via_sensor_power_setup()
198 ret = gpio_request(cam->reset_gpio, "viafb-camera"); in via_sensor_power_setup()
200 dev_err(&cam->platdev->dev, "Unable to request reset GPIO\n"); in via_sensor_power_setup()
201 gpio_free(cam->power_gpio); in via_sensor_power_setup()
204 gpio_direction_output(cam->power_gpio, 0); in via_sensor_power_setup()
205 gpio_direction_output(cam->reset_gpio, 0); in via_sensor_power_setup()
214 gpio_set_value(cam->power_gpio, 1); in via_sensor_power_up()
215 gpio_set_value(cam->reset_gpio, 0); in via_sensor_power_up()
217 gpio_set_value(cam->reset_gpio, 1); in via_sensor_power_up()
223 gpio_set_value(cam->power_gpio, 0); in via_sensor_power_down()
224 gpio_set_value(cam->reset_gpio, 0); in via_sensor_power_down()
231 gpio_free(cam->power_gpio); in via_sensor_power_release()
232 gpio_free(cam->reset_gpio); in via_sensor_power_release()
235 /* --------------------------------------------------------------------------*/
260 v4l2_fill_mbus_format(&mbus_fmt, &cam->sensor_format, cam->mbus_code); in viacam_configure_sensor()
274 /* --------------------------------------------------------------------------*/
276 * Some simple register accessors; they assume that the lock is held.
280 * 0x300-350 range.
285 iowrite32(value, cam->mmio + reg); in viacam_write_reg()
290 return ioread32(cam->mmio + reg); in viacam_read_reg()
303 /* --------------------------------------------------------------------------*/
316 spin_lock(&cam->viadev->reg_lock); in viacam_quick_irq()
323 spin_unlock(&cam->viadev->reg_lock); in viacam_quick_irq()
335 spin_lock_irqsave(&cam->viadev->reg_lock, flags); in viacam_next_buffer()
336 if (cam->opstate != S_RUNNING) in viacam_next_buffer()
338 if (list_empty(&cam->buffer_queue)) in viacam_next_buffer()
340 buf = list_entry(cam->buffer_queue.next, struct videobuf_buffer, queue); in viacam_next_buffer()
341 if (!waitqueue_active(&buf->done)) {/* Nobody waiting */ in viacam_next_buffer()
345 list_del(&buf->queue); in viacam_next_buffer()
346 buf->state = VIDEOBUF_ACTIVE; in viacam_next_buffer()
348 spin_unlock_irqrestore(&cam->viadev->reg_lock, flags); in viacam_next_buffer()
373 bufn -= 1; in viacam_irq()
375 bufn = cam->n_cap_bufs - 1; in viacam_irq()
380 viafb_dma_copy_out_sg(cam->cb_offsets[bufn], vdma->sglist, vdma->sglen); in viacam_irq()
381 vb->state = VIDEOBUF_DONE; in viacam_irq()
382 vb->size = cam->user_format.sizeimage; in viacam_irq()
383 wake_up(&vb->done); in viacam_irq()
394 * the via-core level.
411 /* --------------------------------------------------------------------------*/
415 * Set up our capture buffers in framebuffer memory.
419 int nbuf = cam->viadev->camera_fbmem_size/cam->sensor_format.sizeimage; in viacam_ctlr_cbufs()
427 cam->n_cap_bufs = 3; in viacam_ctlr_cbufs()
431 cam->n_cap_bufs = 2; in viacam_ctlr_cbufs()
435 return -ENOMEM; in viacam_ctlr_cbufs()
440 offset = cam->fb_offset; in viacam_ctlr_cbufs()
441 for (i = 0; i < cam->n_cap_bufs; i++) { in viacam_ctlr_cbufs()
442 cam->cb_offsets[i] = offset; in viacam_ctlr_cbufs()
443 cam->cb_addrs[i] = cam->fbmem + offset; in viacam_ctlr_cbufs()
445 offset += cam->sensor_format.sizeimage; in viacam_ctlr_cbufs()
472 if (cam->user_format.width == VGA_WIDTH) in viacam_set_scale()
475 sf = (cam->user_format.width*2048)/VGA_WIDTH; in viacam_set_scale()
478 if (cam->user_format.height < VGA_HEIGHT) { in viacam_set_scale()
479 sf = (1024*cam->user_format.height)/VGA_HEIGHT; in viacam_set_scale()
487 * Configure image-related information into the capture engine.
494 * Disable clock before messing with stuff - from the via in viacam_ctlr_image()
509 (cam->sensor_format.height << 16) | in viacam_ctlr_image()
510 (cam->sensor_format.bytesperline >> 3)); in viacam_ctlr_image()
513 cam->user_format.bytesperline & VCR_VS_STRIDE); in viacam_ctlr_image()
523 VCR_CI_FLDINV | /* OLPC-specific? */ in viacam_ctlr_image()
524 VCR_CI_VREFINV | /* OLPC-specific? */ in viacam_ctlr_image()
527 if (cam->n_cap_bufs == 3) in viacam_ctlr_image()
532 if (cam->user_format.pixelformat == V4L2_PIX_FMT_YUYV) in viacam_ctlr_image()
545 spin_lock_irqsave(&cam->viadev->reg_lock, flags); in viacam_config_controller()
549 spin_unlock_irqrestore(&cam->viadev->reg_lock, flags); in viacam_config_controller()
550 clear_bit(CF_CONFIG_NEEDED, &cam->flags); in viacam_config_controller()
559 spin_lock_irq(&cam->viadev->reg_lock); in viacam_start_engine()
560 cam->next_buf = 0; in viacam_start_engine()
564 cam->opstate = S_RUNNING; in viacam_start_engine()
565 spin_unlock_irq(&cam->viadev->reg_lock); in viacam_start_engine()
571 spin_lock_irq(&cam->viadev->reg_lock); in viacam_stop_engine()
575 cam->opstate = S_IDLE; in viacam_stop_engine()
576 spin_unlock_irq(&cam->viadev->reg_lock); in viacam_stop_engine()
580 /* --------------------------------------------------------------------------*/
591 struct via_camera *cam = q->priv_data; in viacam_vb_buf_setup()
593 *size = cam->user_format.sizeimage; in viacam_vb_buf_setup()
605 struct via_camera *cam = q->priv_data; in viacam_vb_buf_prepare()
607 vb->size = cam->user_format.sizeimage; in viacam_vb_buf_prepare()
608 vb->width = cam->user_format.width; /* bytesperline???? */ in viacam_vb_buf_prepare()
609 vb->height = cam->user_format.height; in viacam_vb_buf_prepare()
610 vb->field = field; in viacam_vb_buf_prepare()
611 if (vb->state == VIDEOBUF_NEEDS_INIT) { in viacam_vb_buf_prepare()
616 vb->state = VIDEOBUF_PREPARED; in viacam_vb_buf_prepare()
628 struct via_camera *cam = q->priv_data; in viacam_vb_buf_queue()
634 vb->state = VIDEOBUF_QUEUED; in viacam_vb_buf_queue()
635 list_add_tail(&vb->queue, &cam->buffer_queue); in viacam_vb_buf_queue()
644 struct via_camera *cam = q->priv_data; in viacam_vb_buf_release()
646 videobuf_dma_unmap(&cam->platdev->dev, videobuf_to_dma(vb)); in viacam_vb_buf_release()
648 vb->state = VIDEOBUF_NEEDS_INIT; in viacam_vb_buf_release()
658 /* --------------------------------------------------------------------------*/
665 filp->private_data = cam; in viacam_open()
670 mutex_lock(&cam->lock); in viacam_open()
671 if (cam->users == 0) { in viacam_open()
675 mutex_unlock(&cam->lock); in viacam_open()
679 set_bit(CF_CONFIG_NEEDED, &cam->flags); in viacam_open()
683 videobuf_queue_sg_init(&cam->vb_queue, &viacam_vb_ops, in viacam_open()
684 &cam->platdev->dev, &cam->viadev->reg_lock, in viacam_open()
688 (cam->users)++; in viacam_open()
689 mutex_unlock(&cam->lock); in viacam_open()
697 mutex_lock(&cam->lock); in viacam_release()
698 (cam->users)--; in viacam_release()
703 if (filp == cam->owner) { in viacam_release()
704 videobuf_stop(&cam->vb_queue); in viacam_release()
711 if (cam->opstate != S_IDLE) in viacam_release()
713 cam->owner = NULL; in viacam_release()
718 if (cam->users == 0) { in viacam_release()
719 videobuf_mmap_free(&cam->vb_queue); in viacam_release()
723 mutex_unlock(&cam->lock); in viacam_release()
736 mutex_lock(&cam->lock); in viacam_read()
740 if (cam->owner && cam->owner != filp) { in viacam_read()
741 ret = -EBUSY; in viacam_read()
744 cam->owner = filp; in viacam_read()
748 if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) { in viacam_read()
760 INIT_LIST_HEAD(&cam->buffer_queue); in viacam_read()
762 ret = videobuf_read_stream(&cam->vb_queue, buffer, len, pos, 0, in viacam_read()
763 filp->f_flags & O_NONBLOCK); in viacam_read()
768 mutex_unlock(&cam->lock); in viacam_read()
777 return videobuf_poll_stream(filp, &cam->vb_queue, pt); in viacam_poll()
785 return videobuf_mmap_mapper(&cam->vb_queue, vma); in viacam_mmap()
800 /*----------------------------------------------------------------------------*/
810 ident->ident = V4L2_IDENT_NONE; in viacam_g_chip_ident()
811 ident->revision = 0; in viacam_g_chip_ident()
812 if (v4l2_chip_match_host(&ident->match)) { in viacam_g_chip_ident()
813 ident->ident = V4L2_IDENT_VIA_VX855; in viacam_g_chip_ident()
828 mutex_lock(&cam->lock); in viacam_queryctrl()
830 mutex_unlock(&cam->lock); in viacam_queryctrl()
841 mutex_lock(&cam->lock); in viacam_g_ctrl()
843 mutex_unlock(&cam->lock); in viacam_g_ctrl()
854 mutex_lock(&cam->lock); in viacam_s_ctrl()
856 mutex_unlock(&cam->lock); in viacam_s_ctrl()
866 if (input->index != 0) in viacam_enum_input()
867 return -EINVAL; in viacam_enum_input()
869 input->type = V4L2_INPUT_TYPE_CAMERA; in viacam_enum_input()
870 input->std = V4L2_STD_ALL; /* Not sure what should go here */ in viacam_enum_input()
871 strcpy(input->name, "Camera"); in viacam_enum_input()
884 return -EINVAL; in viacam_s_input()
911 if (fmt->index >= N_VIA_FMTS) in viacam_enum_fmt_vid_cap()
912 return -EINVAL; in viacam_enum_fmt_vid_cap()
913 strlcpy(fmt->description, via_formats[fmt->index].desc, in viacam_enum_fmt_vid_cap()
914 sizeof(fmt->description)); in viacam_enum_fmt_vid_cap()
915 fmt->pixelformat = via_formats[fmt->index].pixelformat; in viacam_enum_fmt_vid_cap()
927 if (userfmt->width < QCIF_WIDTH || userfmt->height < QCIF_HEIGHT) { in viacam_fmt_pre()
928 userfmt->width = QCIF_WIDTH; in viacam_fmt_pre()
929 userfmt->height = QCIF_HEIGHT; in viacam_fmt_pre()
931 if (userfmt->width > VGA_WIDTH || userfmt->height > VGA_HEIGHT) { in viacam_fmt_pre()
932 userfmt->width = VGA_WIDTH; in viacam_fmt_pre()
933 userfmt->height = VGA_HEIGHT; in viacam_fmt_pre()
935 sensorfmt->width = VGA_WIDTH; in viacam_fmt_pre()
936 sensorfmt->height = VGA_HEIGHT; in viacam_fmt_pre()
942 struct via_format *f = via_find_format(userfmt->pixelformat); in viacam_fmt_post()
944 sensorfmt->bytesperline = sensorfmt->width * f->bpp; in viacam_fmt_post()
945 sensorfmt->sizeimage = sensorfmt->height * sensorfmt->bytesperline; in viacam_fmt_post()
946 userfmt->pixelformat = sensorfmt->pixelformat; in viacam_fmt_post()
947 userfmt->field = sensorfmt->field; in viacam_fmt_post()
948 userfmt->bytesperline = 2 * userfmt->width; in viacam_fmt_post()
949 userfmt->sizeimage = userfmt->bytesperline * userfmt->height; in viacam_fmt_post()
961 struct via_format *f = via_find_format(upix->pixelformat); in viacam_do_try_fmt()
963 upix->pixelformat = f->pixelformat; in viacam_do_try_fmt()
965 v4l2_fill_mbus_format(&mbus_fmt, upix, f->mbus_code); in viacam_do_try_fmt()
981 mutex_lock(&cam->lock); in viacam_try_fmt_vid_cap()
982 ret = viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); in viacam_try_fmt_vid_cap()
983 mutex_unlock(&cam->lock); in viacam_try_fmt_vid_cap()
993 mutex_lock(&cam->lock); in viacam_g_fmt_vid_cap()
994 fmt->fmt.pix = cam->user_format; in viacam_g_fmt_vid_cap()
995 mutex_unlock(&cam->lock); in viacam_g_fmt_vid_cap()
1005 struct via_format *f = via_find_format(fmt->fmt.pix.pixelformat); in viacam_s_fmt_vid_cap()
1011 mutex_lock(&cam->lock); in viacam_s_fmt_vid_cap()
1012 if (cam->opstate != S_IDLE) { in viacam_s_fmt_vid_cap()
1013 ret = -EBUSY; in viacam_s_fmt_vid_cap()
1020 ret = viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix); in viacam_s_fmt_vid_cap()
1026 cam->user_format = fmt->fmt.pix; in viacam_s_fmt_vid_cap()
1027 cam->sensor_format = sfmt.fmt.pix; in viacam_s_fmt_vid_cap()
1028 cam->mbus_code = f->mbus_code; in viacam_s_fmt_vid_cap()
1033 mutex_unlock(&cam->lock); in viacam_s_fmt_vid_cap()
1040 strcpy(cap->driver, "via-camera"); in viacam_querycap()
1041 strcpy(cap->card, "via-camera"); in viacam_querycap()
1042 cap->version = 1; in viacam_querycap()
1043 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | in viacam_querycap()
1049 * Streaming operations - pure videobuf stuff.
1056 return videobuf_reqbufs(&cam->vb_queue, rb); in viacam_reqbufs()
1064 return videobuf_querybuf(&cam->vb_queue, buf); in viacam_querybuf()
1071 return videobuf_qbuf(&cam->vb_queue, buf); in viacam_qbuf()
1078 return videobuf_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK); in viacam_dqbuf()
1087 return -EINVAL; in viacam_streamon()
1089 mutex_lock(&cam->lock); in viacam_streamon()
1090 if (cam->opstate != S_IDLE) { in viacam_streamon()
1091 ret = -EBUSY; in viacam_streamon()
1097 if (cam->owner && cam->owner != filp) { in viacam_streamon()
1098 ret = -EBUSY; in viacam_streamon()
1101 cam->owner = filp; in viacam_streamon()
1105 if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) { in viacam_streamon()
1119 pm_qos_add_request(&cam->qos_request, PM_QOS_CPU_DMA_LATENCY, 50); in viacam_streamon()
1123 INIT_LIST_HEAD(&cam->buffer_queue); in viacam_streamon()
1124 ret = videobuf_streamon(&cam->vb_queue); in viacam_streamon()
1128 mutex_unlock(&cam->lock); in viacam_streamon()
1138 return -EINVAL; in viacam_streamoff()
1139 mutex_lock(&cam->lock); in viacam_streamoff()
1140 if (cam->opstate != S_RUNNING) { in viacam_streamoff()
1141 ret = -EINVAL; in viacam_streamoff()
1144 pm_qos_remove_request(&cam->qos_request); in viacam_streamoff()
1151 ret = videobuf_streamoff(&cam->vb_queue); in viacam_streamoff()
1152 INIT_LIST_HEAD(&cam->buffer_queue); in viacam_streamoff()
1154 mutex_unlock(&cam->lock); in viacam_streamoff()
1166 mutex_lock(&cam->lock); in viacam_g_parm()
1168 mutex_unlock(&cam->lock); in viacam_g_parm()
1169 parm->parm.capture.readbuffers = cam->n_cap_bufs; in viacam_g_parm()
1179 mutex_lock(&cam->lock); in viacam_s_parm()
1181 mutex_unlock(&cam->lock); in viacam_s_parm()
1182 parm->parm.capture.readbuffers = cam->n_cap_bufs; in viacam_s_parm()
1189 if (sizes->index != 0) in viacam_enum_framesizes()
1190 return -EINVAL; in viacam_enum_framesizes()
1191 sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; in viacam_enum_framesizes()
1192 sizes->stepwise.min_width = QCIF_WIDTH; in viacam_enum_framesizes()
1193 sizes->stepwise.min_height = QCIF_HEIGHT; in viacam_enum_framesizes()
1194 sizes->stepwise.max_width = VGA_WIDTH; in viacam_enum_framesizes()
1195 sizes->stepwise.max_height = VGA_HEIGHT; in viacam_enum_framesizes()
1196 sizes->stepwise.step_width = sizes->stepwise.step_height = 1; in viacam_enum_framesizes()
1206 mutex_lock(&cam->lock); in viacam_enum_frameintervals()
1208 mutex_unlock(&cam->lock); in viacam_enum_frameintervals()
1240 /*----------------------------------------------------------------------------*/
1250 enum viacam_opstate state = cam->opstate; in viacam_suspend()
1252 if (cam->opstate != S_IDLE) { in viacam_suspend()
1254 cam->opstate = state; /* So resume restarts */ in viacam_suspend()
1271 set_bit(CF_CONFIG_NEEDED, &cam->flags); in viacam_resume()
1275 if (cam->users > 0) in viacam_resume()
1282 if (cam->opstate != S_IDLE) { in viacam_resume()
1283 mutex_lock(&cam->lock); in viacam_resume()
1287 mutex_unlock(&cam->lock); in viacam_resume()
1307 .name = "via-camera",
1308 .minor = -1,
1354 struct viafb_dev *viadev = pdev->dev.platform_data; in viacam_probe()
1367 * with less than two frames of VGA 16-bit data. in viacam_probe()
1372 if (viadev->camera_fbmem_size < (VGA_HEIGHT*VGA_WIDTH*4)) { in viacam_probe()
1374 return -ENOMEM; in viacam_probe()
1376 if (viadev->engine_mmio == NULL) { in viacam_probe()
1378 return -ENOMEM; in viacam_probe()
1382 return -EBUSY; in viacam_probe()
1389 return -ENOMEM; in viacam_probe()
1391 cam->platdev = pdev; in viacam_probe()
1392 cam->viadev = viadev; in viacam_probe()
1393 cam->users = 0; in viacam_probe()
1394 cam->owner = NULL; in viacam_probe()
1395 cam->opstate = S_IDLE; in viacam_probe()
1396 cam->user_format = cam->sensor_format = viacam_def_pix_format; in viacam_probe()
1397 mutex_init(&cam->lock); in viacam_probe()
1398 INIT_LIST_HEAD(&cam->buffer_queue); in viacam_probe()
1399 cam->mmio = viadev->engine_mmio; in viacam_probe()
1400 cam->fbmem = viadev->fbmem; in viacam_probe()
1401 cam->fb_offset = viadev->camera_fbmem_offset; in viacam_probe()
1402 cam->flags = 1 << CF_CONFIG_NEEDED; in viacam_probe()
1403 cam->mbus_code = via_def_mbus_code; in viacam_probe()
1407 ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); in viacam_probe()
1409 dev_err(&pdev->dev, "Unable to register v4l2 device\n"); in viacam_probe()
1415 pdev->dev.dma_mask = &viadev->pdev->dma_mask; in viacam_probe()
1416 dma_set_mask(&pdev->dev, 0xffffffff); in viacam_probe()
1433 * is OLPC-specific. 0x42 assumption is ov7670-specific. in viacam_probe()
1436 cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, sensor_adapter, in viacam_probe()
1438 if (cam->sensor == NULL) { in viacam_probe()
1439 dev_err(&pdev->dev, "Unable to find the sensor!\n"); in viacam_probe()
1440 ret = -ENODEV; in viacam_probe()
1447 ret = request_threaded_irq(viadev->pdev->irq, viacam_quick_irq, in viacam_probe()
1448 viacam_irq, IRQF_SHARED, "via-camera", cam); in viacam_probe()
1454 cam->vdev = viacam_v4l_template; in viacam_probe()
1455 cam->vdev.v4l2_dev = &cam->v4l2_dev; in viacam_probe()
1456 ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); in viacam_probe()
1459 video_set_drvdata(&cam->vdev, cam); in viacam_probe()
1474 free_irq(viadev->pdev->irq, cam); in viacam_probe()
1478 v4l2_device_unregister(&cam->v4l2_dev); in viacam_probe()
1485 struct viafb_dev *viadev = pdev->dev.platform_data; in viacam_remove()
1487 video_unregister_device(&cam->vdev); in viacam_remove()
1488 v4l2_device_unregister(&cam->v4l2_dev); in viacam_remove()
1489 free_irq(viadev->pdev->irq, cam); in viacam_remove()
1497 .name = "viafb-camera",