Goal
Create a simple dummy driver (called fsr172x
) for the OMAP3530 that bypasses almost all extra functionality just to get the RAW
data from the 12 data lines to a v4l2buf
.
Overview
fsr172x
is a platform-independent v4l2-slave device- controls the sensor device
- interfaces with
v4l2
- is unaware of
isp
omap34xxcam
is the platform-dependent v4l2-master- controls the
isp
- interfaces with
v4l2
- controls the
v4l2
provides a common framework which the application may useisp
image support package?ispccdc
- controls the
ccdc
- controls the
fidcap
is a dummy capture application which utilizesv4l2
fidcap
is designed specifically for use with thefsr172x
and therefore is a bad example
- the master and slave have no knowledge of each other's implementations
- a platform "driver" such as
board-overo-camera
(Gumstix Overo) orboard-omap3beagle-camera.c
(BeagleBoard) connects the two together..
Note: The file contents shown are not complete but rather snippets that give content to the changes. Note: The FSR172X is a stripped down version of the MT9T111. I recommend viewing the V4L2 Example Capture application as well.
Pre-reqs
- Get a copy of
linux-omap-psp
in your~/
- Review this v4l2 struct
Hacking V4L2
Our dummy driver will use a special formats for
- standard:
FSRX
- as opposed toNTSC
,PAL
, etc - colorspace:
FSR
- as opposed toSRGB
These are created from enum
s and #define
s that are completely arbitrary.
The caveat is that any application or driver that depends on these settings
must include this special modified version of the of videodev2.h
.
drivers/media/video/isp/isp.c
This is a patch showing changes I've made for the fsr172x. Once I have this figured out I'll refactor it down into understandable chunks
diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
index 29dd005..2369f54 100644
--- a/drivers/media/video/isp/isp.c
+++ b/drivers/media/video/isp/isp.c
@@ -930,7 +930,7 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_pdev)
return IRQ_HANDLED;
spin_lock_irqsave(&bufs->lock, flags);
- wait_hs_vs = bufs->wait_hs_vs;
+ wait_hs_vs = 0; //bufs->wait_hs_vs; For FSR
if (irqstatus & HS_VS) {
if (bufs->wait_hs_vs) {
bufs->wait_hs_vs--;
@@ -978,12 +978,23 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_pdev)
}
if (irqstatus & CCDC_VD0) {
+ DPRINTK_ISPCTRL("VD0 interupt\n");
if (isp->pipeline.pix.field == V4L2_FIELD_INTERLACED) {
/* Skip even fields, and process only odd fields */
if (isp->current_field != 0)
if (RAW_CAPTURE(isp))
isp_buf_process(dev, bufs);
}
+ else // For FSR - progressive scan, process every field
+ {
+ //DPRINTK_ISPCTRL("Not interlaced\n");
+ if (RAW_CAPTURE(isp))
+ {
+ DPRINTK_ISPCTRL("Processing buff\n");
+ isp_buf_process(dev, bufs);
+ }
+ }
+
if (!ispccdc_busy(&isp->isp_ccdc))
ispccdc_config_shadow_registers(&isp->isp_ccdc);
}
@@ -1363,7 +1374,10 @@ static void isp_set_buf(struct device *dev, struct isp_buf *buf)
&& is_ispresizer_enabled())
ispresizer_set_outaddr(&isp->isp_res, buf->isp_addr);
else if (isp->pipeline.modules & OMAP_ISP_CCDC)
+ {
+ printk("SDR Address set to 0x%08X\n",buf->isp_addr);
ispccdc_set_outaddr(&isp->isp_ccdc, buf->isp_addr);
+ }
}
@@ -1412,7 +1426,10 @@ static int isp_try_pipeline(struct device *dev,
pipe->prv_out = PREVIEW_MEM;
pipe->rsz_in = RSZ_MEM_YUV;
} else {
+ printk("ARRIVED IN: ISP_CCDC\n");
pipe->modules = OMAP_ISP_CCDC;
+ // TODO if this is set in fsr172x, we shouldn't need this here
+ //pix_input->pixelformat = V4L2_PIX_FMT_FSR172X; // Added for FSR
if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10 ||
pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8 ||
pix_input->pixelformat == V4L2_PIX_FMT_SRGGB10 ||
@@ -1431,12 +1448,17 @@ static int isp_try_pipeline(struct device *dev,
} else if (pix_input->pixelformat == V4L2_PIX_FMT_YUYV ||
pix_input->pixelformat == V4L2_PIX_FMT_UYVY) {
if (isp->bt656ifen)
- pipe->ccdc_in = CCDC_YUV_BT;
+ pipe->ccdc_in = CCDC_YUV_BT;
else
- pipe->ccdc_in = CCDC_YUV_SYNC;
+ pipe->ccdc_in = CCDC_YUV_SYNC;
pipe->ccdc_out = CCDC_OTHERS_MEM;
- } else
+ } else if (pix_input->pixelformat == V4L2_PIX_FMT_FSR172X) { // Added for FSR
+ printk("ARRIVED IN: PIPELINE FSR\n");
+ pipe->ccdc_in = CCDC_RAW_FSR;
+ pipe->ccdc_out = CCDC_FSR_MEM;
+ } else {
return -EINVAL;
+ }
}
if (pipe->modules & OMAP_ISP_CCDC) {
@@ -1652,7 +1674,8 @@ static int isp_buf_process(struct device *dev, struct isp_bufs *bufs)
if (ISP_BUFS_IS_EMPTY(bufs))
goto out;
- if (RAW_CAPTURE(isp) && ispccdc_sbl_wait_idle(&isp->isp_ccdc, 1000)) {
+ // We keep getting wait errors... this seems to fix the problem (originally 1000)
+ if (RAW_CAPTURE(isp) && ispccdc_sbl_wait_idle(&isp->isp_ccdc, 2e6)) {
dev_err(dev, "ccdc %d won't become idle!\n",
RAW_CAPTURE(isp));
goto out;
drivers/media/video/isp/ispccdc.c
diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c
index 137a5e6..df7c15d 100644
--- a/drivers/media/video/isp/ispccdc.c
+++ b/drivers/media/video/isp/ispccdc.c
@@ -631,6 +631,23 @@ static int ispccdc_config_datapath(struct isp_ccdc_device *isp_ccdc,
ispccdc_config_vp(isp_ccdc, vpcfg);
ispccdc_enable_vp(isp_ccdc, 1);
break;
+
+ case CCDC_FSR_MEM:
+ printk("ARRIVED IN: CCDC_FSR_MEM\n");
+ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
+ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
+ syn_mode |= ISPCCDC_SYN_MODE_WEN;
+ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
+ isp_reg_and(isp_ccdc->dev, OMAP3_ISP_IOMEM_CCDC,
+ ISPCCDC_CFG, ~ISPCCDC_CFG_WENLOG);
+
+ // TODO aren't these 0 by default?
+ vpcfg.bitshift_sel = 0;
+ vpcfg.freq_sel = 0;
+ ispccdc_config_vp(isp_ccdc, vpcfg);
+ ispccdc_enable_vp(isp_ccdc, 0);
+ break;
+
default:
DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
return -EINVAL;
@@ -700,6 +717,33 @@ static int ispccdc_config_datapath(struct isp_ccdc_device *isp_ccdc,
blkcfg.dcsubval = 0;
ispccdc_config_black_clamp(isp_ccdc, blkcfg);
break;
+ case CCDC_RAW_FSR: // what values do we need here?
+ printk("ARRIVED IN: CCDC_RAW_FSR\n");
+ syncif.ccdc_mastermode = 1; // p1461 1 ==hs/vs output
+ syncif.datapol = 0; // 0 == normal, not one's complement
+ syncif.datsz = DAT12; // 12 lines
+ syncif.fldmode = 0; // 0 == progressive scan, not interlaced
+ syncif.fldout = 0; // (cam_fld) not used when 0 == fldmode
+ syncif.fldpol = 0; // not used when 0 == fldmode
+ syncif.fldstat = 0; // not used when 0 == fldmode, otherwise marks current frame as odd/even
+ syncif.hdpol = 0; // cam_hs polarity 0 == positive
+ syncif.ipmod = RAW; // aka inpmod p1553 should be 0 for raw
+ syncif.vdpol = 0; // cam_vs polarity 0 == positive
+ syncif.bt_r656_en = 0; // 1 == ITU enabled
+
+ // These should next four should always be set when mastermode is enabled
+ syncif.hs_width = 0; // aka hd_vd_wid p1554
+ syncif.vs_width = 0; // aka hd_vd_wid
+ syncif.ppln = (u8) 0x7D01; // 32001 Maybe should be 16001(?) p1555 pixels per line
+ syncif.hlprf = 128; // half line per field or frame
+
+ // isp modules
+ ispccdc_config_imgattr(isp_ccdc, 0); // mosiac filter??, probably should be all 0's
+ ispccdc_config_sync_if(isp_ccdc, syncif); // commit these values to the registers
+
+ // black clamp
+ blkcfg.dcsubval = 0; // black clamp substraction value, probably should be 0
+ ispccdc_config_black_clamp(isp_ccdc, blkcfg);
case CCDC_OTHERS:
break;
default:
@@ -1202,6 +1246,8 @@ int ispccdc_try_pipeline(struct isp_ccdc_device *isp_ccdc,
pipe->ccdc_in_v_st = 0;
pipe->ccdc_out_w = pipe->ccdc_in_w;
pipe->ccdc_out_h = pipe->ccdc_in_h;
+
+ printk("Out pixel height %d\n",pipe->ccdc_out_h);
if (!isp_ccdc->refmt_en
&& pipe->ccdc_out != CCDC_OTHERS_MEM
@@ -1348,6 +1394,7 @@ int ispccdc_s_pipeline(struct isp_ccdc_device *isp_ccdc,
OMAP3_ISP_IOMEM_CCDC,
ISPCCDC_VDINT);
} else {
+ printk("Arrived in vp out mem\n");
ispccdc_config_outlineoffset(isp_ccdc,
pipe->ccdc_out_w * 2, EVENEVEN, 1);
ispccdc_config_outlineoffset(isp_ccdc,
@@ -1367,6 +1414,7 @@ int ispccdc_s_pipeline(struct isp_ccdc_device *isp_ccdc,
}
} else if (pipe->ccdc_out == CCDC_OTHERS_VP_MEM) {
+ printk("Arrived in vp out mem\n");
isp_reg_writel(isp_ccdc->dev,
(pipe->ccdc_in_h_st << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
((pipe->ccdc_in_w - pipe->ccdc_in_h_st) <<
drivers/media/video/isp/ispccdc.h
The FSR uses a type of RAW
capture and has particular memory requirements not currently supported by the ISP
.
These new enum
s allow us to cleanly create new conditional branches in the ISP
/CCDC
code.
/* Enumeration constants for CCDC input output format */
enum ccdc_input {
CCDC_RAW_GRBG,
CCDC_RAW_RGGB,
CCDC_RAW_BGGR,
CCDC_RAW_GBRG,
CCDC_RAW_FSR, // FSR
CCDC_YUV_SYNC,
CCDC_YUV_BT,
CCDC_OTHERS
};
enum ccdc_output {
CCDC_YUV_RSZ,
CCDC_YUV_MEM_RSZ,
CCDC_FSR_MEM, // FSR
CCDC_OTHERS_VP,
CCDC_OTHERS_MEM,
CCDC_OTHERS_VP_MEM
};
arch/arm/mach-omap2/board-overo-camera.c
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/mm.h>
#include <linux/videodev2.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <plat/mux.h>
#include <plat/board.h>
#include <plat/control.h>
#include <media/v4l2-int-device.h>
#include <media/fsr172x.h>
/* Include V4L2 ISP-Camera driver related header file */
#include <../drivers/media/video/omap34xxcam.h>
#include <../drivers/media/video/isp/ispreg.h>
#include "mux.h"
#include "board-overo-camera.h"
#define MODULE_NAME "omap3beaglelmb"
#define CAM_USE_XCLKA 0
#define ISP_FSR172X_MCLK 216000000
#define LEOPARD_RESET_GPIO 98
#if defined(CONFIG_VIDEO_FSR172X) || defined(CONFIG_VIDEO_FSR172X_MODULE)
/* Arbitrary memory handling limit */
#define FSR172X_BIGGEST_FRAME_BYTE_SIZE PAGE_ALIGN(2048 * 1536 * 4)
// TODO can this be moved to fsr driver?
static struct isp_interface_config fsr172x_if_config = {
.ccdc_par_ser = ISP_PARLL,
.dataline_shift = 0x0,
.hsvs_syncdetect = ISPCTRL_SYNC_DETECT_VSRISE,
.strobe = 0x0,
.prestrobe = 0x0,
.shutter = 0x0,
.cam_mclk = ISP_FSR172X_MCLK, // 216MHz
.wenlog = ISPCCDC_CFG_WENLOG_AND, // (0 << 8)
.wait_hs_vs = 2,
.u.par.par_bridge = 0x0, // no bridge
.u.par.par_clk_pol = 0x0,
};
static struct v4l2_ifparm fsr172x_ifparm_s = {
.if_type = V4L2_IF_TYPE_RAW,
.u = {
.raw = {
.frame_start_on_rising_vs = 1,
.bt_sync_correct = 0,
.swap = 0,
.latch_clk_inv = 0,
.nobt_hs_inv = 0, /* active high */
.nobt_vs_inv = 0, /* active high */
.clock_min = FSR172X_CLK_MIN, // 2.048MHz
.clock_max = FSR172X_CLK_MAX, // 2.048MHz
},
},
};
/**
* @brief fsr172x_ifparm - Returns the fsr172x interface parameters
*
* @param p - pointer to v4l2_ifparm structure
*
* @return result of operation - 0 is success
*/
static int fsr172x_ifparm(struct v4l2_ifparm *p)
{
if (p == NULL)
return -EINVAL;
*p = fsr172x_ifparm_s;
return 0;
}
#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
static struct omap34xxcam_hw_config fsr172x_hwc = {
.dev_index = 0,
.dev_minor = 0,
.dev_type = OMAP34XXCAM_SLAVE_SENSOR,
.u.sensor.sensor_isp = 1,
.u.sensor.capture_mem = FSR172X_BIGGEST_FRAME_BYTE_SIZE * 2,
.u.sensor.ival_default = { 1, 10 },
};
#endif
/**
* @brief fsr172x_set_prv_data - Returns fsr172x omap34xx driver private data
*
* @param priv - pointer to omap34xxcam_hw_config structure
*
* @return result of operation - 0 is success
*/
static int fsr172x_set_prv_data(void *priv)
{
#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
struct omap34xxcam_hw_config *hwc = priv;
if (priv == NULL)
return -EINVAL;
hwc->u.sensor = fsr172x_hwc.u.sensor;
hwc->dev_index = fsr172x_hwc.dev_index;
hwc->dev_minor = fsr172x_hwc.dev_minor;
hwc->dev_type = fsr172x_hwc.dev_type;
return 0;
#else
return -EINVAL;
#endif
}
/**
* @brief fsr172x_power_set - Power-on or power-off TVP5146 device
*
* @param power - enum, Power on/off, resume/standby
*
* @return result of operation - 0 is success
*/
static int fsr172x_power_set(struct v4l2_int_device *s, enum v4l2_power power)
{
struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
switch (power) {
case V4L2_POWER_OFF:
case V4L2_POWER_STANDBY:
isp_set_xclk(vdev->cam->isp, 0, CAM_USE_XCLKA);
break;
case V4L2_POWER_ON:
#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
isp_configure_interface(vdev->cam->isp, &fsr172x_if_config);
#endif
break;
default:
return -ENODEV;
break;
}
return 0;
}
struct fsr172x_platform_data fsr172x_pdata = {
.master = "omap34xxcam",
.power_set = fsr172x_power_set,
.priv_data_set = fsr172x_set_prv_data,
.ifparm = fsr172x_ifparm,
/* Some interface dependent params */
.clk_polarity = 0, /* data clocked out on falling edge */
.hs_polarity = 1, /* 0 - Active low, 1- Active high */
.vs_polarity = 1, /* 0 - Active low, 1- Active high */
};
#endif /* #ifdef CONFIG_VIDEO_FSR172X */
static int beagle_cam_probe(struct platform_device *pdev)
{
printk(KERN_INFO MODULE_NAME ": Driver registration complete \n");
return 0;
}
static int beagle_cam_remove(struct platform_device *pdev)
{
// FSR_COMMENT - mux init on remove, but not on insert?
/* MUX init */
omap_ctrl_writew(OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
0x10C); /* CAM_HS */
omap_ctrl_writew(OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
0x10E); /* CAM_VS */
omap_ctrl_writew(OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
0x110); /* CAM_XCLKA */
omap_ctrl_writew(OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
0x112); /* CAM_PCLK */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x116); /* CAM_D0 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x118); /* CAM_D1 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x11A); /* CAM_D2 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x11C); /* CAM_D3 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x11E); /* CAM_D4 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x120); /* CAM_D5 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x122); /* CAM_D6 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x124); /* CAM_D7 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x126); /* CAM_D8 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x128); /* CAM_D9 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x12A); /* CAM_D10 */
omap_ctrl_writew(OMAP_PIN_INPUT | OMAP_MUX_MODE0,
0x12C); /* CAM_D11 */
return 0;
}
static int beagle_cam_suspend(struct device *dev)
{
return 0;
}
static int beagle_cam_resume(struct device *dev)
{
return 0;
}
static struct dev_pm_ops beagle_cam_pm_ops = {
.suspend = beagle_cam_suspend,
.resume = beagle_cam_resume,
};
static struct platform_driver beagle_cam_driver = {
.probe = beagle_cam_probe,
.remove = beagle_cam_remove,
.driver = {
.name = "beagle_cam",
.pm = &beagle_cam_pm_ops,
},
};
/**
* @brief omap3beaglelmb_init - module init function. Should be called before any
* client driver init call
*
* @return result of operation - 0 is success
*/
int __init omap3beaglelmb_init(void)
{
platform_driver_register(&beagle_cam_driver);
return 0;
}
late_initcall(omap3beaglelmb_init);
include/linux/videodev2.h
Note: Although these #define
s are arbitrary, they must match between the file include
d
with the driver and the file include
d in the application.
// Our own special colorspace goes in a section like this
enum v4l2_colorspace {
/* ITU-R 601 -- broadcast NTSC/PAL */
V4L2_COLORSPACE_SMPTE170M = 1,
/* 1125-Line (US) HDTV */
V4L2_COLORSPACE_SMPTE240M = 2,
//
// SEVERAL LINES SKIPPED FOR BREVITY IN THIS EXAMPLE
//
/* For RGB colourspaces, this is probably a good start. */
V4L2_COLORSPACE_SRGB = 8,
/* For colourspaces not in the normal range (FSR172X). */
V4L2_COLORSPACE_FSR172X = 9,
};
// Our own special pixel format goes in a section like this
/*
* V I D E O I M A G E F O R M A T
*/
//
// SEVERAL LINES SKIPPED FOR BREVITY IN THIS EXAMPLE
//
/* Vendor-specific formats */
#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
//
// SEVERAL LINES SKIPPED FOR BREVITY IN THIS EXAMPLE
//
#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
#define V4L2_PIX_FMT_FSR172X v4l2_fourcc('F', 'S', 'R', '0') /* 12bit raw fsr172x */
include/linux/v4l2-int-device.h
Nothing is changed here, but it's worth noting that we'll be using the predefined RAW
mode...
/* Slave interface type. */
enum v4l2_if_type {
/*
* Parallel 8-, 10- or 12-bit interface, used by for example
* on certain image sensors.
*/
V4L2_IF_TYPE_BT656,
V4L2_IF_TYPE_YCbCr,
V4L2_IF_TYPE_RAW,
};
... and its associated struct
struct v4l2_if_type_raw {
/*
* 0: Frame begins when vsync is high.
* 1: Frame begins when vsync changes from low to high.
*/
unsigned frame_start_on_rising_vs:1;
/* Use Bt synchronisation codes for sync correction. */
unsigned bt_sync_correct:1;
/* Swap every two adjacent image data elements. */
unsigned swap:1;
/* Inverted latch clock polarity from slave. */
unsigned latch_clk_inv:1;
/* Hs polarity. 0 is active high, 1 active low. */
unsigned nobt_hs_inv:1;
/* Vs polarity. 0 is active high, 1 active low. */
unsigned nobt_vs_inv:1;
/* Minimum accepted bus clock for slave (in Hz). */
u32 clock_min;
/* Maximum accepted bus clock for slave. */
u32 clock_max;
/*
* Current wish of the slave. May only change in response to
* ioctls that affect image capture.
*/
u32 clock_curr;
};
If we were to create our own, we would need to modify this v4l2 struct:
struct v4l2_ifparm {
enum v4l2_if_type if_type;
union {
struct v4l2_if_type_bt656 bt656;
struct v4l2_if_type_ycbcr ycbcr;
struct v4l2_if_type_raw raw;
} u;
};
In our driver code we will access these settings as v4l2_ifparm
.
arch/arm/mach-omap2/board-overo-camera.c
This board file and its header are the exact same as board-omap3beagle-camera
with the exception that every occurrance of beagle has been replaced with overo and every occurance of mt9t111 has been replaced with fsr172x.
Again, we'll just use RAW
, but if we had created our own FSR
standard, we would need to add to this list:
static struct v4l2_ifparm fsr172x_ifparm_s = {
#if 1
.if_type = V4L2_IF_TYPE_RAW,
.u = {
.raw = {
.frame_start_on_rising_vs = 1,
.bt_sync_correct = 0,
.swap = 0,
.latch_clk_inv = 0,
.nobt_hs_inv = 0, /* active high */
.nobt_vs_inv = 0, /* active high */
.clock_min = FSR172X_CLK_MIN,
.clock_max = FSR172X_CLK_MAX,
},
},
#else
.if_type = V4L2_IF_TYPE_YCbCr,
// REMOVED FOR BREVITY
},
#endif
};
scratchspace
Linux Kernel vs TRM
- omap34xxcam_hw_config.u.sensor.sensor_isp -> ???
- omap34xxcam_hw_config.wait_hs_vs -> ???
- isp_interface_config.u.par.par_bridge -> ???
- omap34xxcam_videodev.cam.isp -> ???
- v4l2_int_device->u.slave->master->priv -> ???
where stuff is
v4l2_ifparm: v4l2-int-device
- fsr172x.c
- board-overo-camera.c
omap34xxcam_hw_config: omap34xxcam
- board-overo-camera.c
which v4l2 calls must we implement?
- ???
what is this mess?
- regulator_put - part of
include/linux/regulator/consumer.h
- for future compatibility. Does nothing as of right now. Just a stubbed out API. - dev_pm_ops - power management for suspending, resuming, etc
- omap34xxcam is a master
- fsr172x is a slave
drivers/media/video/fsr172x.c
// Creating a map between VIDIOC_X_YZ and our internal functions
static struct v4l2_int_ioctl_desc fsr172x_ioctl_desc[] = {
{ .num = vidioc_int_enum_framesizes_num,
.func = (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
{ .num = vidioc_int_enum_frameintervals_num,
.func = (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
{ .num = vidioc_int_dev_init_num,
.func = (v4l2_int_ioctl_func *)ioctl_dev_init },
{ .num = vidioc_int_dev_exit_num,
.func = (v4l2_int_ioctl_func *)ioctl_dev_exit },
{ .num = vidioc_int_s_power_num,
.func = (v4l2_int_ioctl_func *)ioctl_s_power },
{ .num = vidioc_int_g_priv_num,
.func = (v4l2_int_ioctl_func *)ioctl_g_priv },
{ .num = vidioc_int_g_ifparm_num,
.func = (v4l2_int_ioctl_func *)ioctl_g_ifparm },
{ .num = vidioc_int_init_num,
.func = (v4l2_int_ioctl_func *)ioctl_init },
{ .num = vidioc_int_enum_fmt_cap_num,
.func = (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
{ .num = vidioc_int_try_fmt_cap_num,
.func = (v4l2_int_ioctl_func *)ioctl_try_fmt_cap },
{ .num = vidioc_int_g_fmt_cap_num,
.func = (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
{ .num = vidioc_int_s_fmt_cap_num,
.func = (v4l2_int_ioctl_func *)ioctl_s_fmt_cap },
{ .num = vidioc_int_g_parm_num,
.func = (v4l2_int_ioctl_func *)ioctl_g_parm },
{ .num = vidioc_int_s_parm_num,
.func = (v4l2_int_ioctl_func *)ioctl_s_parm },
{ .num = vidioc_int_queryctrl_num,
.func = (v4l2_int_ioctl_func *)ioctl_queryctrl },
{ .num = vidioc_int_g_ctrl_num,
.func = (v4l2_int_ioctl_func *)ioctl_g_ctrl },
{ .num = vidioc_int_s_ctrl_num,
.func = (v4l2_int_ioctl_func *)ioctl_s_ctrl },
{ .num = vidioc_int_s_video_routing_num,
.func = (v4l2_int_ioctl_func *)ioctl_s_routing },
};
static struct v4l2_int_slave fsr172x_slave = {
.ioctls = fsr172x_ioctl_desc,
.num_ioctls = ARRAY_SIZE(fsr172x_ioctl_desc),
};
static struct v4l2_int_device fsr172x_int_device = {
.module = THIS_MODULE,
.name = "fsr172x",
.priv = &fsr172x,
.type = v4l2_int_type_slave,
.u = {
.slave = &fsr172x_slave,
},
};
Note: Most of the ioctl_x_yz
functions refer to V4L2
s VIDIOC_X_YZ
#define
s.
Appendix
V4L2_FRMSIZE_TYPE_DISCRETE
vsV4L2_FRMSIZE_TYPE_STEPWISE
vsV4L2_FRMSIZE_TYPE_CONTINUOUS
- discrete: finite values that don't change
- step-wise: ??
- continuous: ranges from a
min
to amax
by a value ofstep