^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for the VIA Chrome integrated camera controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2009,2010 Jonathan Corbet <corbet@lwn.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This work was supported by the One Laptop Per Child project
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/v4l2-image-sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/i2c/ov7670.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <media/videobuf2-dma-sg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/pm_qos.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/via-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/via-gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/via_i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/olpc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define machine_is_olpc(x) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include "via-camera.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) MODULE_ALIAS("platform:viafb-camera");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_DESCRIPTION("VIA framebuffer-based camera controller driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static bool flip_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) module_param(flip_image, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MODULE_PARM_DESC(flip_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "If set, the sensor will be instructed to flip the image vertically.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static bool override_serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) module_param(override_serial, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MODULE_PARM_DESC(override_serial,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) "The camera driver will normally refuse to load if the XO 1.5 serial port is enabled. Set this option to force-enable the camera.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * The structure describing our camera.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) enum viacam_opstate { S_IDLE = 0, S_RUNNING = 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct via_camera {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct v4l2_device v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct v4l2_ctrl_handler ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct video_device vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct v4l2_subdev *sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct platform_device *platdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct viafb_dev *viadev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) enum viacam_opstate opstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct pm_qos_request qos_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * GPIO info for power/reset management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int power_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * I/O memory stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void __iomem *mmio; /* Where the registers live */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void __iomem *fbmem; /* Frame buffer memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 fb_offset; /* Reserved memory offset (FB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Capture buffers and related. The controller supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * up to three, so that's what we have here. These buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * live in frame buffer memory, so we don't call them "DMA".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned int cb_offsets[3]; /* offsets into fb mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u8 __iomem *cb_addrs[3]; /* Kernel-space addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int n_cap_bufs; /* How many are we using? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct vb2_queue vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct list_head buffer_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Video format information. sensor_format is kept in a form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * that we can use to pass to the sensor. We always run the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * sensor in VGA resolution, though, and let the controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * downscale things if need be. So we keep the "real*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * dimensions separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct v4l2_pix_format sensor_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct v4l2_pix_format user_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* buffer for one video frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct via_buffer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* common v4l buffer stuff -- must be first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct vb2_v4l2_buffer vbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct list_head queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * Yes, this is a hack, but there's only going to be one of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * on any system we know of.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static struct via_camera *via_cam_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Flag values, manipulated with bitops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define CF_DMA_ACTIVE 0 /* A frame is incoming */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define CF_CONFIG_NEEDED 1 /* Must configure hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Nasty ugly v4l2 boilerplate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define sensor_call(cam, optype, func, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) v4l2_subdev_call(cam->sensor, optype, func, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Debugging and related.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define cam_err(cam, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dev_err(&(cam)->platdev->dev, fmt, ##arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define cam_warn(cam, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dev_warn(&(cam)->platdev->dev, fmt, ##arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define cam_dbg(cam, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) dev_dbg(&(cam)->platdev->dev, fmt, ##arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Format handling. This is ripped almost directly from Hans's changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * to cafe_ccic.c. It's a little unfortunate; until this change, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * didn't need to know anything about the format except its byte depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * now this information must be managed at this level too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static struct via_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) __u32 pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int bpp; /* Bytes per pixel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } via_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .pixelformat = V4L2_PIX_FMT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .bpp = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* RGB444 and Bayer should be doable, but have never been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tested with this driver. RGB565 seems to work at the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) resolution, but results in color corruption when being scaled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) viacam_set_scaled(), and is disabled as a result. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define N_VIA_FMTS ARRAY_SIZE(via_formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static struct via_format *via_find_format(u32 pixelformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) for (i = 0; i < N_VIA_FMTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (via_formats[i].pixelformat == pixelformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return via_formats + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Not found? Then return the first format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return via_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*--------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * Sensor power/reset management. This piece is OLPC-specific for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * sure; other configurations will have things connected differently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int via_sensor_power_setup(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) cam->power_gpio = viafb_gpio_lookup("VGPIO3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) cam->reset_gpio = viafb_gpio_lookup("VGPIO2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (!gpio_is_valid(cam->power_gpio) || !gpio_is_valid(cam->reset_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dev_err(&cam->platdev->dev, "Unable to find GPIO lines\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = gpio_request(cam->power_gpio, "viafb-camera");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dev_err(&cam->platdev->dev, "Unable to request power GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = gpio_request(cam->reset_gpio, "viafb-camera");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) dev_err(&cam->platdev->dev, "Unable to request reset GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) gpio_free(cam->power_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) gpio_direction_output(cam->power_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) gpio_direction_output(cam->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * Power up the sensor and perform the reset dance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void via_sensor_power_up(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) gpio_set_value(cam->power_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) gpio_set_value(cam->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) msleep(20); /* Probably excessive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) gpio_set_value(cam->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static void via_sensor_power_down(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) gpio_set_value(cam->power_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) gpio_set_value(cam->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static void via_sensor_power_release(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) via_sensor_power_down(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) gpio_free(cam->power_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) gpio_free(cam->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* Sensor ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Manage the ov7670 "flip" bit, which needs special help.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static int viacam_set_flip(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct v4l2_control ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) memset(&ctrl, 0, sizeof(ctrl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ctrl.id = V4L2_CID_VFLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ctrl.value = flip_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return v4l2_s_ctrl(NULL, cam->sensor->ctrl_handler, &ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Configure the sensor. It's up to the caller to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * that the camera is in the correct operating state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static int viacam_configure_sensor(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct v4l2_subdev_format format = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .which = V4L2_SUBDEV_FORMAT_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) v4l2_fill_mbus_format(&format.format, &cam->sensor_format, cam->mbus_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret = sensor_call(cam, core, init, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = sensor_call(cam, pad, set_fmt, NULL, &format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * OV7670 does weird things if flip is set *before* format...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ret = viacam_set_flip(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * Some simple register accessors; they assume that the lock is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * Should we want to support the second capture engine, we could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * hide the register difference by adding 0x1000 to registers in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * 0x300-350 range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static inline void viacam_write_reg(struct via_camera *cam,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int reg, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) iowrite32(value, cam->mmio + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static inline int viacam_read_reg(struct via_camera *cam, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ioread32(cam->mmio + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static inline void viacam_write_reg_mask(struct via_camera *cam,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int reg, int value, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int tmp = viacam_read_reg(cam, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tmp = (tmp & ~mask) | (value & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) viacam_write_reg(cam, reg, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* Interrupt management and handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static irqreturn_t viacam_quick_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct via_camera *cam = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) irqreturn_t ret = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int icv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * All we do here is to clear the interrupts and tell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * the handler thread to wake up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) spin_lock(&cam->viadev->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) icv = viacam_read_reg(cam, VCR_INTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (icv & VCR_IC_EAV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) icv |= VCR_IC_EAV|VCR_IC_EVBI|VCR_IC_FFULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) viacam_write_reg(cam, VCR_INTCTRL, icv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) spin_unlock(&cam->viadev->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * Find the next buffer which has somebody waiting on it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static struct via_buffer *viacam_next_buffer(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (cam->opstate != S_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (list_empty(&cam->buffer_queue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return list_entry(cam->buffer_queue.next, struct via_buffer, queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * The threaded IRQ handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static irqreturn_t viacam_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct via_camera *cam = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct via_buffer *vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int bufn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct sg_table *sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) mutex_lock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * If there is no place to put the data frame, don't bother
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * with anything else.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) vb = viacam_next_buffer(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (vb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * Figure out which buffer we just completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) bufn = (viacam_read_reg(cam, VCR_INTCTRL) & VCR_IC_ACTBUF) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) bufn -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (bufn < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) bufn = cam->n_cap_bufs - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * Copy over the data and let any waiters know.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) sgt = vb2_dma_sg_plane_desc(&vb->vbuf.vb2_buf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) vb->vbuf.vb2_buf.timestamp = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) viafb_dma_copy_out_sg(cam->cb_offsets[bufn], sgt->sgl, sgt->nents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) vb->vbuf.sequence = cam->sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) vb->vbuf.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) list_del(&vb->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) vb2_buffer_done(&vb->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) mutex_unlock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * These functions must mess around with the general interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * control register, which is relevant to much more than just the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * camera. Nothing else uses interrupts, though, as of this writing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Should that situation change, we'll have to improve support at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * the via-core level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static void viacam_int_enable(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) viacam_write_reg(cam, VCR_INTCTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) VCR_IC_INTEN|VCR_IC_EAV|VCR_IC_EVBI|VCR_IC_FFULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) viafb_irq_enable(VDE_I_C0AVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void viacam_int_disable(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) viafb_irq_disable(VDE_I_C0AVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) viacam_write_reg(cam, VCR_INTCTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* Controller operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * Set up our capture buffers in framebuffer memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int viacam_ctlr_cbufs(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int nbuf = cam->viadev->camera_fbmem_size/cam->sensor_format.sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * See how many buffers we can work with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (nbuf >= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) cam->n_cap_bufs = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) viacam_write_reg_mask(cam, VCR_CAPINTC, VCR_CI_3BUFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) VCR_CI_3BUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) } else if (nbuf == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) cam->n_cap_bufs = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) viacam_write_reg_mask(cam, VCR_CAPINTC, 0, VCR_CI_3BUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cam_warn(cam, "Insufficient frame buffer memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * Set them up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) offset = cam->fb_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) for (i = 0; i < cam->n_cap_bufs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) cam->cb_offsets[i] = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) cam->cb_addrs[i] = cam->fbmem + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) viacam_write_reg(cam, VCR_VBUF1 + i*4, offset & VCR_VBUF_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) offset += cam->sensor_format.sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * Set the scaling register for downscaling the image.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * This register works like this... Vertical scaling is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * by bit 26; if that bit is set, downscaling is controlled by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * value in bits 16:25. Those bits are divided by 1024 to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * the scaling factor; setting just bit 25 thus cuts the height
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * in half.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * Horizontal scaling works about the same, but it's enabled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * bit 11, with bits 0:10 giving the numerator of a fraction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * (over 2048) for the scaling value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * This function is naive in that, if the user departs from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * the 3x4 VGA scaling factor, the image will distort. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * could work around that if it really seemed important.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static void viacam_set_scale(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned int avscale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (cam->user_format.width == VGA_WIDTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) avscale = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) sf = (cam->user_format.width*2048)/VGA_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) avscale = VCR_AVS_HEN | sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (cam->user_format.height < VGA_HEIGHT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) sf = (1024*cam->user_format.height)/VGA_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) avscale |= VCR_AVS_VEN | (sf << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) viacam_write_reg(cam, VCR_AVSCALE, avscale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * Configure image-related information into the capture engine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static void viacam_ctlr_image(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int cicreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * Disable clock before messing with stuff - from the via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * sample driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) viacam_write_reg(cam, VCR_CAPINTC, ~(VCR_CI_ENABLE|VCR_CI_CLKEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * Set up the controller for VGA resolution, modulo magic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * offsets from the via sample driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) viacam_write_reg(cam, VCR_HORRANGE, 0x06200120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) viacam_write_reg(cam, VCR_VERTRANGE, 0x01de0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) viacam_set_scale(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * Image size info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) viacam_write_reg(cam, VCR_MAXDATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) (cam->sensor_format.height << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) (cam->sensor_format.bytesperline >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) viacam_write_reg(cam, VCR_MAXVBI, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) viacam_write_reg(cam, VCR_VSTRIDE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) cam->user_format.bytesperline & VCR_VS_STRIDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * Set up the capture interface control register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * everything but the "go" bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * The FIFO threshold is a bit of a magic number; 8 is what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * VIA's sample code uses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cicreg = VCR_CI_CLKEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 0x08000000 | /* FIFO threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) VCR_CI_FLDINV | /* OLPC-specific? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) VCR_CI_VREFINV | /* OLPC-specific? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) VCR_CI_DIBOTH | /* Capture both fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) VCR_CI_CCIR601_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (cam->n_cap_bufs == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cicreg |= VCR_CI_3BUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * YUV formats need different byte swapping than RGB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (cam->user_format.pixelformat == V4L2_PIX_FMT_YUYV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) cicreg |= VCR_CI_YUYV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) cicreg |= VCR_CI_UYVY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) viacam_write_reg(cam, VCR_CAPINTC, cicreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int viacam_config_controller(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) spin_lock_irqsave(&cam->viadev->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ret = viacam_ctlr_cbufs(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) viacam_ctlr_image(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) spin_unlock_irqrestore(&cam->viadev->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) clear_bit(CF_CONFIG_NEEDED, &cam->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * Make it start grabbing data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static void viacam_start_engine(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) spin_lock_irq(&cam->viadev->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) viacam_write_reg_mask(cam, VCR_CAPINTC, VCR_CI_ENABLE, VCR_CI_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) viacam_int_enable(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) (void) viacam_read_reg(cam, VCR_CAPINTC); /* Force post */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) cam->opstate = S_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) spin_unlock_irq(&cam->viadev->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static void viacam_stop_engine(struct via_camera *cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) spin_lock_irq(&cam->viadev->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) viacam_int_disable(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) viacam_write_reg_mask(cam, VCR_CAPINTC, 0, VCR_CI_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) (void) viacam_read_reg(cam, VCR_CAPINTC); /* Force post */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) cam->opstate = S_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) spin_unlock_irq(&cam->viadev->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* vb2 callback ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static struct via_buffer *vb2_to_via_buffer(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return container_of(vbuf, struct via_buffer, vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) static void viacam_vb2_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct via_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct via_buffer *via = vb2_to_via_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) list_add_tail(&via->queue, &cam->buffer_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int viacam_vb2_prepare(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct via_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (vb2_plane_size(vb, 0) < cam->user_format.sizeimage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) cam_dbg(cam,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) "Plane size too small (%lu < %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) vb2_plane_size(vb, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) cam->user_format.sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) vb2_set_plane_payload(vb, 0, cam->user_format.sizeimage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int viacam_vb2_queue_setup(struct vb2_queue *vq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) unsigned int *nbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) unsigned int *num_planes, unsigned int sizes[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct via_camera *cam = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) int size = cam->user_format.sizeimage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (*num_planes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return sizes[0] < size ? -EINVAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *num_planes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) sizes[0] = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int viacam_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct via_camera *cam = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct via_buffer *buf, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (cam->opstate != S_IDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * Configure things if need be.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (test_bit(CF_CONFIG_NEEDED, &cam->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ret = viacam_configure_sensor(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ret = viacam_config_controller(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) cam->sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * If the CPU goes into C3, the DMA transfer gets corrupted and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * users start filing unsightly bug reports. Put in a "latency"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * requirement which will keep the CPU out of the deeper sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * states.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) cpu_latency_qos_add_request(&cam->qos_request, 50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) viacam_start_engine(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) list_for_each_entry_safe(buf, tmp, &cam->buffer_queue, queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) list_del(&buf->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static void viacam_vb2_stop_streaming(struct vb2_queue *vq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct via_camera *cam = vb2_get_drv_priv(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct via_buffer *buf, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) cpu_latency_qos_remove_request(&cam->qos_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) viacam_stop_engine(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) list_for_each_entry_safe(buf, tmp, &cam->buffer_queue, queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) list_del(&buf->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static const struct vb2_ops viacam_vb2_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .queue_setup = viacam_vb2_queue_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .buf_queue = viacam_vb2_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) .buf_prepare = viacam_vb2_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .start_streaming = viacam_vb2_start_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .stop_streaming = viacam_vb2_stop_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) .wait_finish = vb2_ops_wait_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* --------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* File operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static int viacam_open(struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * Note the new user. If this is the first one, we'll also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * need to power up the sensor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) mutex_lock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ret = v4l2_fh_open(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (v4l2_fh_is_singular_file(filp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = viafb_request_dma();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) v4l2_fh_release(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) via_sensor_power_up(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) set_bit(CF_CONFIG_NEEDED, &cam->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) mutex_unlock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static int viacam_release(struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) bool last_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) mutex_lock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) last_open = v4l2_fh_is_singular_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) _vb2_fop_release(filp, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * Last one out needs to turn out the lights.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (last_open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) via_sensor_power_down(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) viafb_release_dma();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) mutex_unlock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static const struct v4l2_file_operations viacam_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .open = viacam_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .release = viacam_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .read = vb2_fop_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .poll = vb2_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .mmap = vb2_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /*----------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * The long list of v4l2 ioctl ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * Only one input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static int viacam_enum_input(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct v4l2_input *input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (input->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) input->type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) strscpy(input->name, "Camera", sizeof(input->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static int viacam_g_input(struct file *filp, void *priv, unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) *i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static int viacam_s_input(struct file *filp, void *priv, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (i != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * Video format stuff. Here is our default format until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * user space messes with things.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static const struct v4l2_pix_format viacam_def_pix_format = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) .width = VGA_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) .height = VGA_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .pixelformat = V4L2_PIX_FMT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .field = V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .bytesperline = VGA_WIDTH * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .sizeimage = VGA_WIDTH * VGA_HEIGHT * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static const u32 via_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) static int viacam_enum_fmt_vid_cap(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct v4l2_fmtdesc *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (fmt->index >= N_VIA_FMTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) fmt->pixelformat = via_formats[fmt->index].pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * Figure out proper image dimensions, but always force the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * sensor to VGA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static void viacam_fmt_pre(struct v4l2_pix_format *userfmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) struct v4l2_pix_format *sensorfmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) *sensorfmt = *userfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (userfmt->width < QCIF_WIDTH || userfmt->height < QCIF_HEIGHT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) userfmt->width = QCIF_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) userfmt->height = QCIF_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (userfmt->width > VGA_WIDTH || userfmt->height > VGA_HEIGHT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) userfmt->width = VGA_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) userfmt->height = VGA_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) sensorfmt->width = VGA_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) sensorfmt->height = VGA_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static void viacam_fmt_post(struct v4l2_pix_format *userfmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct v4l2_pix_format *sensorfmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct via_format *f = via_find_format(userfmt->pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) sensorfmt->bytesperline = sensorfmt->width * f->bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) sensorfmt->sizeimage = sensorfmt->height * sensorfmt->bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) userfmt->pixelformat = sensorfmt->pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) userfmt->field = sensorfmt->field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) userfmt->bytesperline = 2 * userfmt->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) userfmt->sizeimage = userfmt->bytesperline * userfmt->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) userfmt->colorspace = sensorfmt->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) userfmt->ycbcr_enc = sensorfmt->ycbcr_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) userfmt->quantization = sensorfmt->quantization;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) userfmt->xfer_func = sensorfmt->xfer_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * The real work of figuring out a workable format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static int viacam_do_try_fmt(struct via_camera *cam,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct v4l2_pix_format *upix, struct v4l2_pix_format *spix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct v4l2_subdev_pad_config pad_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct v4l2_subdev_format format = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .which = V4L2_SUBDEV_FORMAT_TRY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct via_format *f = via_find_format(upix->pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) upix->pixelformat = f->pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) viacam_fmt_pre(upix, spix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) v4l2_fill_mbus_format(&format.format, spix, f->mbus_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) ret = sensor_call(cam, pad, set_fmt, &pad_cfg, &format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) v4l2_fill_pix_format(spix, &format.format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) viacam_fmt_post(upix, spix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int viacam_try_fmt_vid_cap(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct v4l2_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct v4l2_format sfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static int viacam_g_fmt_vid_cap(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct v4l2_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) fmt->fmt.pix = cam->user_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static int viacam_s_fmt_vid_cap(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct v4l2_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct v4l2_format sfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct via_format *f = via_find_format(fmt->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * Camera must be idle or we can't mess with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * video setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (cam->opstate != S_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * Let the sensor code look over and tweak the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * requested formatting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) ret = viacam_do_try_fmt(cam, &fmt->fmt.pix, &sfmt.fmt.pix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * OK, let's commit to the new format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) cam->user_format = fmt->fmt.pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) cam->sensor_format = sfmt.fmt.pix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) cam->mbus_code = f->mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) ret = viacam_configure_sensor(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ret = viacam_config_controller(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) static int viacam_querycap(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) strscpy(cap->driver, "via-camera", sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) strscpy(cap->card, "via-camera", sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) strscpy(cap->bus_info, "platform:via-camera", sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* G/S_PARM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static int viacam_g_parm(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) struct v4l2_streamparm *parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return v4l2_g_parm_cap(video_devdata(filp), cam->sensor, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static int viacam_s_parm(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) struct v4l2_streamparm *parm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return v4l2_s_parm_cap(video_devdata(filp), cam->sensor, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) static int viacam_enum_framesizes(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct v4l2_frmsizeenum *sizes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (sizes->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) for (i = 0; i < N_VIA_FMTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (sizes->pixel_format == via_formats[i].pixelformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (i >= N_VIA_FMTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) sizes->stepwise.min_width = QCIF_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) sizes->stepwise.min_height = QCIF_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) sizes->stepwise.max_width = VGA_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) sizes->stepwise.max_height = VGA_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) sizes->stepwise.step_width = sizes->stepwise.step_height = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static int viacam_enum_frameintervals(struct file *filp, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct v4l2_frmivalenum *interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct via_camera *cam = video_drvdata(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct v4l2_subdev_frame_interval_enum fie = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .index = interval->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .code = cam->mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .width = cam->sensor_format.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .height = cam->sensor_format.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .which = V4L2_SUBDEV_FORMAT_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) for (i = 0; i < N_VIA_FMTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (interval->pixel_format == via_formats[i].pixelformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (i >= N_VIA_FMTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (interval->width < QCIF_WIDTH || interval->width > VGA_WIDTH ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) interval->height < QCIF_HEIGHT || interval->height > VGA_HEIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) interval->discrete = fie.interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static const struct v4l2_ioctl_ops viacam_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .vidioc_enum_input = viacam_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .vidioc_g_input = viacam_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .vidioc_s_input = viacam_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) .vidioc_enum_fmt_vid_cap = viacam_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) .vidioc_try_fmt_vid_cap = viacam_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .vidioc_g_fmt_vid_cap = viacam_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) .vidioc_s_fmt_vid_cap = viacam_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) .vidioc_querycap = viacam_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) .vidioc_reqbufs = vb2_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) .vidioc_create_bufs = vb2_ioctl_create_bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .vidioc_querybuf = vb2_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) .vidioc_qbuf = vb2_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) .vidioc_dqbuf = vb2_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) .vidioc_expbuf = vb2_ioctl_expbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) .vidioc_streamon = vb2_ioctl_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) .vidioc_streamoff = vb2_ioctl_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) .vidioc_g_parm = viacam_g_parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .vidioc_s_parm = viacam_s_parm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) .vidioc_enum_framesizes = viacam_enum_framesizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) .vidioc_enum_frameintervals = viacam_enum_frameintervals,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /*----------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * Power management.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static int viacam_suspend(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct via_camera *cam = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) enum viacam_opstate state = cam->opstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (cam->opstate != S_IDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) viacam_stop_engine(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) cam->opstate = state; /* So resume restarts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int viacam_resume(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct via_camera *cam = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * Get back to a reasonable operating state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) via_write_reg_mask(VIASR, 0x78, 0, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) via_write_reg_mask(VIASR, 0x1e, 0xc0, 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) viacam_int_disable(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) set_bit(CF_CONFIG_NEEDED, &cam->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * Make sure the sensor's power state is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (!list_empty(&cam->vdev.fh_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) via_sensor_power_up(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) via_sensor_power_down(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * If it was operating, try to restart it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (cam->opstate != S_IDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) mutex_lock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) ret = viacam_configure_sensor(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ret = viacam_config_controller(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) mutex_unlock(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) viacam_start_engine(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) static struct viafb_pm_hooks viacam_pm_hooks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) .suspend = viacam_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) .resume = viacam_resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * Setup stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) static const struct video_device viacam_v4l_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) .name = "via-camera",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) .minor = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) .fops = &viacam_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) .ioctl_ops = &viacam_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) .release = video_device_release_empty, /* Check this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) V4L2_CAP_STREAMING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * The OLPC folks put the serial port on the same pin as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * the camera. They also get grumpy if we break the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * serial port and keep them from using it. So we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * to check the serial enable bit and not step on it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) #define VIACAM_SERIAL_DEVFN 0x88
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) #define VIACAM_SERIAL_CREG 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) #define VIACAM_SERIAL_BIT 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static bool viacam_serial_is_enabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct pci_bus *pbus = pci_find_bus(0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) u8 cbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (!pbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) VIACAM_SERIAL_CREG, &cbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if ((cbyte & VIACAM_SERIAL_BIT) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return false; /* Not enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (!override_serial) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) printk(KERN_NOTICE "Via camera: serial port is enabled, " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) "refusing to load.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) printk(KERN_NOTICE "Specify override_serial=1 to force " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) "module loading.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) printk(KERN_NOTICE "Via camera: overriding serial port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) pci_bus_write_config_byte(pbus, VIACAM_SERIAL_DEVFN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) VIACAM_SERIAL_CREG, cbyte & ~VIACAM_SERIAL_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static struct ov7670_config sensor_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) /* The XO-1.5 (only known user) clocks the camera at 90MHz. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) .clock_speed = 90,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) static int viacam_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct i2c_adapter *sensor_adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct viafb_dev *viadev = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct vb2_queue *vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct i2c_board_info ov7670_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .type = "ov7670",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .addr = 0x42 >> 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .platform_data = &sensor_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * Note that there are actually two capture channels on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * the device. We only deal with one for now. That
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * is encoded here; nothing else assumes it's dealing with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * a unique capture device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) struct via_camera *cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * Ensure that frame buffer memory has been set aside for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * this purpose. As an arbitrary limit, refuse to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * with less than two frames of VGA 16-bit data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) * If we ever support the second port, we'll need to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * aside more memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (viadev->camera_fbmem_size < (VGA_HEIGHT*VGA_WIDTH*4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) printk(KERN_ERR "viacam: insufficient FB memory reserved\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (viadev->engine_mmio == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) printk(KERN_ERR "viacam: No I/O memory, so no pictures\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (machine_is_olpc() && viacam_serial_is_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * Basic structure initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) cam = kzalloc (sizeof(struct via_camera), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (cam == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) via_cam_info = cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) cam->platdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) cam->viadev = viadev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) cam->opstate = S_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) cam->user_format = cam->sensor_format = viacam_def_pix_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) mutex_init(&cam->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) INIT_LIST_HEAD(&cam->buffer_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) cam->mmio = viadev->engine_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) cam->fbmem = viadev->fbmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) cam->fb_offset = viadev->camera_fbmem_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) cam->flags = 1 << CF_CONFIG_NEEDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) cam->mbus_code = via_def_mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * Tell V4L that we exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) dev_err(&pdev->dev, "Unable to register v4l2 device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) goto out_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * Convince the system that we can do DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) pdev->dev.dma_mask = &viadev->pdev->dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dma_set_mask(&pdev->dev, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) * Fire up the capture port. The write to 0x78 looks purely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) * OLPCish; any system will need to tweak 0x1e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) via_write_reg_mask(VIASR, 0x78, 0, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) via_write_reg_mask(VIASR, 0x1e, 0xc0, 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * Get the sensor powered up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ret = via_sensor_power_setup(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) goto out_ctrl_hdl_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) via_sensor_power_up(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * See if we can't find it on the bus. The VIA_PORT_31 assumption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) * is OLPC-specific. 0x42 assumption is ov7670-specific.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) sensor_adapter = viafb_find_i2c_adapter(VIA_PORT_31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev, sensor_adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) &ov7670_info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (cam->sensor == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) dev_err(&pdev->dev, "Unable to find the sensor!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) goto out_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * Get the IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) viacam_int_disable(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) ret = request_threaded_irq(viadev->pdev->irq, viacam_quick_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) viacam_irq, IRQF_SHARED, "via-camera", cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) goto out_power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) vq = &cam->vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) vq->drv_priv = cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) vq->buf_struct_size = sizeof(struct via_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) vq->dev = cam->v4l2_dev.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) vq->ops = &viacam_vb2_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) vq->mem_ops = &vb2_dma_sg_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) vq->lock = &cam->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) ret = vb2_queue_init(vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * Tell V4l2 that we exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) cam->vdev = viacam_v4l_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) cam->vdev.v4l2_dev = &cam->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) cam->vdev.lock = &cam->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) cam->vdev.queue = vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) video_set_drvdata(&cam->vdev, cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) ret = video_register_device(&cam->vdev, VFL_TYPE_VIDEO, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) goto out_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) * Hook into PM events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) viacam_pm_hooks.private = cam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) viafb_pm_register(&viacam_pm_hooks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) /* Power the sensor down until somebody opens the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) via_sensor_power_down(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) out_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) free_irq(viadev->pdev->irq, cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) out_power_down:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) via_sensor_power_release(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) out_ctrl_hdl_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) v4l2_ctrl_handler_free(&cam->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) out_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) v4l2_device_unregister(&cam->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) kfree(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static int viacam_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct via_camera *cam = via_cam_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) struct viafb_dev *viadev = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) video_unregister_device(&cam->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) v4l2_device_unregister(&cam->v4l2_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) viafb_pm_unregister(&viacam_pm_hooks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) free_irq(viadev->pdev->irq, cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) via_sensor_power_release(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) v4l2_ctrl_handler_free(&cam->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) kfree(cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) via_cam_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) static struct platform_driver viacam_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) .name = "viafb-camera",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) .probe = viacam_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) .remove = viacam_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) module_platform_driver(viacam_driver);