Merge tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - remove of atomisp driver from staging, as nobody would have time to dedicate huge efforts to fix all the problems there. Also, we have a feeling that the driver may not even run the way it is. - move Zoran driver to staging, in order to be either fixed to use VB2 and the proper media kAPIs or to be removed - remove videobuf-dvb driver, with is unused for a while - some V4L2 documentation fixes/improvements - new sensor drivers: imx258 and ov7251 - a new driver was added to allow using I2C transparent drivers - several improvements at the ddbridge driver - several improvements at the ISDB pt1 driver, making it more coherent with the DVB framework - added a new platform driver for MIPI CSI-2 RX: cadence - now, all media drivers can be compiled on x86 with COMPILE_TEST - almost all media drivers now build on non-x86 architectures with COMPILE_TEST - lots of other random stuff: cleanups, support for new board models, bug fixes, etc * tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (464 commits) media: omap2: fix compile-testing with FB_OMAP2=m media: media/radio/Kconfig: add back RADIO_ISA media: v4l2-ioctl.c: fix missing unlock in __video_do_ioctl() media: pxa_camera: ignore -ENOIOCTLCMD from v4l2_subdev_call for s_power media: arch: sh: migor: Fix TW9910 PDN gpio media: staging: tegra-vde: Reset VDE regardless of memory client resetting failure media: marvel-ccic: mmp: select VIDEOBUF2_VMALLOC/DMA_CONTIG media: marvel-ccic: allow ccic and mmp drivers to coexist media: uvcvideo: Prevent setting unavailable flags media: ddbridge: conditionally enable fast TS for stv0910-equipped bridges media: dvb-frontends/stv0910: make TS speed configurable media: ddbridge/mci: add identifiers to function definition arguments media: ddbridge/mci: protect against out-of-bounds array access in stop() media: rc: ensure input/lirc device can be opened after register media: rc: nuvoton: Keep device enabled during reg init media: rc: nuvoton: Keep track of users on CIR enable/disable media: rc: nuvoton: Tweak the interrupt enabling dance media: uvcvideo: Support realtek's UVC 1.5 device media: uvcvideo: Fix driver reference counting media: gspca_zc3xx: Enable short exposure times for OV7648 ...
This commit is contained in:
@@ -575,6 +575,17 @@ config VIDEO_APTINA_PLL
|
||||
config VIDEO_SMIAPP_PLL
|
||||
tristate
|
||||
|
||||
config VIDEO_IMX258
|
||||
tristate "Sony IMX258 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the Sony
|
||||
IMX258 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx258.
|
||||
|
||||
config VIDEO_IMX274
|
||||
tristate "Sony IMX274 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
@@ -688,6 +699,18 @@ config VIDEO_OV5695
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov5695.
|
||||
|
||||
config VIDEO_OV7251
|
||||
tristate "OmniVision OV7251 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||
OV7251 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov7251.
|
||||
|
||||
config VIDEO_OV772X
|
||||
tristate "OmniVision OV772x sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
@@ -974,6 +997,19 @@ config VIDEO_M52790
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called m52790.
|
||||
|
||||
config VIDEO_I2C
|
||||
tristate "I2C transport video support"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
select VIDEOBUF2_VMALLOC
|
||||
---help---
|
||||
Enable the I2C transport video support which supports the
|
||||
following:
|
||||
* Panasonic AMG88xx Grid-Eye Sensors
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called video-i2c
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Sensors used on soc_camera driver"
|
||||
|
@@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_OV5647) += ov5647.o
|
||||
obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
|
||||
obj-$(CONFIG_VIDEO_OV5695) += ov5695.o
|
||||
obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
|
||||
obj-$(CONFIG_VIDEO_OV7251) += ov7251.o
|
||||
obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
|
||||
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
|
||||
@@ -96,9 +97,11 @@ obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
|
||||
obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
|
||||
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
|
||||
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
|
||||
obj-$(CONFIG_VIDEO_I2C) += video-i2c.o
|
||||
obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
|
||||
obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
|
||||
obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
|
||||
obj-$(CONFIG_VIDEO_IMX258) += imx258.o
|
||||
obj-$(CONFIG_VIDEO_IMX274) += imx274.o
|
||||
|
||||
obj-$(CONFIG_SDR_MAX2175) += max2175.o
|
||||
|
@@ -321,17 +321,17 @@ static const struct v4l2_subdev_video_ops adv748x_afe_video_ops = {
|
||||
static int adv748x_afe_propagate_pixelrate(struct adv748x_afe *afe)
|
||||
{
|
||||
struct v4l2_subdev *tx;
|
||||
unsigned int width, height, fps;
|
||||
|
||||
tx = adv748x_get_remote_sd(&afe->pads[ADV748X_AFE_SOURCE]);
|
||||
if (!tx)
|
||||
return -ENOLINK;
|
||||
|
||||
width = 720;
|
||||
height = afe->curr_norm & V4L2_STD_525_60 ? 480 : 576;
|
||||
fps = afe->curr_norm & V4L2_STD_525_60 ? 30 : 25;
|
||||
|
||||
return adv748x_csi2_set_pixelrate(tx, width * height * fps);
|
||||
/*
|
||||
* The ADV748x ADC sampling frequency is twice the externally supplied
|
||||
* clock whose frequency is required to be 28.63636 MHz. It oversamples
|
||||
* with a factor of 4 resulting in a pixel rate of 14.3180180 MHz.
|
||||
*/
|
||||
return adv748x_csi2_set_pixelrate(tx, 14318180);
|
||||
}
|
||||
|
||||
static int adv748x_afe_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
|
@@ -402,8 +402,6 @@ static int adv748x_hdmi_propagate_pixelrate(struct adv748x_hdmi *hdmi)
|
||||
{
|
||||
struct v4l2_subdev *tx;
|
||||
struct v4l2_dv_timings timings;
|
||||
struct v4l2_bt_timings *bt = &timings.bt;
|
||||
unsigned int fps;
|
||||
|
||||
tx = adv748x_get_remote_sd(&hdmi->pads[ADV748X_HDMI_SOURCE]);
|
||||
if (!tx)
|
||||
@@ -411,11 +409,7 @@ static int adv748x_hdmi_propagate_pixelrate(struct adv748x_hdmi *hdmi)
|
||||
|
||||
adv748x_hdmi_query_dv_timings(&hdmi->sd, &timings);
|
||||
|
||||
fps = DIV_ROUND_CLOSEST_ULL(bt->pixelclock,
|
||||
V4L2_DV_BT_FRAME_WIDTH(bt) *
|
||||
V4L2_DV_BT_FRAME_HEIGHT(bt));
|
||||
|
||||
return adv748x_csi2_set_pixelrate(tx, bt->width * bt->height * fps);
|
||||
return adv748x_csi2_set_pixelrate(tx, timings.bt.pixelclock);
|
||||
}
|
||||
|
||||
static int adv748x_hdmi_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
|
@@ -732,8 +732,8 @@ static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
/* power up cec section */
|
||||
adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x01);
|
||||
/* legacy mode and clear all rx buffers */
|
||||
adv7511_cec_write(sd, 0x4a, 0x00);
|
||||
adv7511_cec_write(sd, 0x4a, 0x07);
|
||||
adv7511_cec_write(sd, 0x4a, 0);
|
||||
adv7511_cec_write_and_or(sd, 0x11, 0xfe, 0); /* initially disable tx */
|
||||
/* enabled irqs: */
|
||||
/* tx: ready */
|
||||
@@ -831,8 +831,8 @@ static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
*/
|
||||
adv7511_cec_write_and_or(sd, 0x12, ~0x70, max(1, attempts - 1) << 4);
|
||||
|
||||
/* blocking, clear cec tx irq status */
|
||||
adv7511_wr_and_or(sd, 0x97, 0xc7, 0x38);
|
||||
/* clear cec tx irq status */
|
||||
adv7511_wr(sd, 0x97, 0x38);
|
||||
|
||||
/* write data */
|
||||
for (i = 0; i < len; i++)
|
||||
@@ -917,9 +917,6 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
|
||||
else if (adv7511_have_hotplug(sd))
|
||||
irqs |= MASK_ADV7511_EDID_RDY_INT;
|
||||
|
||||
adv7511_wr_and_or(sd, 0x95, 0xc0,
|
||||
(state->cec_enabled_adap && enable) ? 0x39 : 0x00);
|
||||
|
||||
/*
|
||||
* This i2c write can fail (approx. 1 in 1000 writes). But it
|
||||
* is essential that this register is correct, so retry it
|
||||
@@ -933,9 +930,11 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
|
||||
irqs_rd = adv7511_rd(sd, 0x94);
|
||||
} while (retries-- && irqs_rd != irqs);
|
||||
|
||||
if (irqs_rd == irqs)
|
||||
return;
|
||||
v4l2_err(sd, "Could not set interrupts: hw failure?\n");
|
||||
if (irqs_rd != irqs)
|
||||
v4l2_err(sd, "Could not set interrupts: hw failure?\n");
|
||||
|
||||
adv7511_wr_and_or(sd, 0x95, 0xc0,
|
||||
(state->cec_enabled_adap && enable) ? 0x39 : 0x00);
|
||||
}
|
||||
|
||||
/* Interrupt handler */
|
||||
@@ -982,8 +981,8 @@ static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
for (i = 0; i < msg.len; i++)
|
||||
msg.msg[i] = adv7511_cec_read(sd, i + 0x15);
|
||||
|
||||
adv7511_cec_write(sd, 0x4a, 1); /* toggle to re-enable rx 1 */
|
||||
adv7511_cec_write(sd, 0x4a, 0);
|
||||
adv7511_cec_write(sd, 0x4a, 0); /* toggle to re-enable rx 1 */
|
||||
adv7511_cec_write(sd, 0x4a, 1);
|
||||
cec_received_msg(state->cec_adap, &msg);
|
||||
}
|
||||
}
|
||||
@@ -1778,6 +1777,7 @@ static void adv7511_init_setup(struct v4l2_subdev *sd)
|
||||
|
||||
/* legacy mode */
|
||||
adv7511_cec_write(sd, 0x4a, 0x00);
|
||||
adv7511_cec_write(sd, 0x4a, 0x07);
|
||||
|
||||
if (cec_clk % 750000 != 0)
|
||||
v4l2_err(sd, "%s: cec_clk %d, not multiple of 750 Khz\n",
|
||||
|
1318
drivers/media/i2c/imx258.c
Normal file
1318
drivers/media/i2c/imx258.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -87,7 +87,7 @@
|
||||
#define IMX274_SHR_LIMIT_CONST (4)
|
||||
|
||||
/*
|
||||
* Constants for sensor reset delay
|
||||
* Min and max sensor reset delay (microseconds)
|
||||
*/
|
||||
#define IMX274_RESET_DELAY1 (2000)
|
||||
#define IMX274_RESET_DELAY2 (2200)
|
||||
@@ -107,15 +107,15 @@
|
||||
/*
|
||||
* IMX274 register definitions
|
||||
*/
|
||||
#define IMX274_FRAME_LENGTH_ADDR_1 0x30FA /* VMAX, MSB */
|
||||
#define IMX274_FRAME_LENGTH_ADDR_2 0x30F9 /* VMAX */
|
||||
#define IMX274_FRAME_LENGTH_ADDR_3 0x30F8 /* VMAX, LSB */
|
||||
#define IMX274_SHR_REG_MSB 0x300D /* SHR */
|
||||
#define IMX274_SHR_REG_LSB 0x300C /* SHR */
|
||||
#define IMX274_SVR_REG_MSB 0x300F /* SVR */
|
||||
#define IMX274_SVR_REG_LSB 0x300E /* SVR */
|
||||
#define IMX274_VMAX_REG_1 0x30FA /* VMAX, MSB */
|
||||
#define IMX274_VMAX_REG_2 0x30F9 /* VMAX */
|
||||
#define IMX274_VMAX_REG_3 0x30F8 /* VMAX, LSB */
|
||||
#define IMX274_HMAX_REG_MSB 0x30F7 /* HMAX */
|
||||
#define IMX274_HMAX_REG_LSB 0x30F6 /* HMAX */
|
||||
#define IMX274_COARSE_TIME_ADDR_MSB 0x300D /* SHR */
|
||||
#define IMX274_COARSE_TIME_ADDR_LSB 0x300C /* SHR */
|
||||
#define IMX274_ANALOG_GAIN_ADDR_LSB 0x300A /* ANALOG GAIN LSB */
|
||||
#define IMX274_ANALOG_GAIN_ADDR_MSB 0x300B /* ANALOG GAIN MSB */
|
||||
#define IMX274_DIGITAL_GAIN_REG 0x3012 /* Digital Gain */
|
||||
@@ -144,22 +144,13 @@ enum imx274_mode {
|
||||
IMX274_MODE_3840X2160,
|
||||
IMX274_MODE_1920X1080,
|
||||
IMX274_MODE_1280X720,
|
||||
|
||||
IMX274_MODE_START_STREAM_1,
|
||||
IMX274_MODE_START_STREAM_2,
|
||||
IMX274_MODE_START_STREAM_3,
|
||||
IMX274_MODE_START_STREAM_4,
|
||||
IMX274_MODE_STOP_STREAM
|
||||
};
|
||||
|
||||
/*
|
||||
* imx274 format related structure
|
||||
*/
|
||||
struct imx274_frmfmt {
|
||||
u32 mbus_code;
|
||||
enum v4l2_colorspace colorspace;
|
||||
struct v4l2_frmsize_discrete size;
|
||||
enum imx274_mode mode;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -489,24 +480,15 @@ static const struct reg_8 *mode_table[] = {
|
||||
[IMX274_MODE_3840X2160] = imx274_mode1_3840x2160_raw10,
|
||||
[IMX274_MODE_1920X1080] = imx274_mode3_1920x1080_raw10,
|
||||
[IMX274_MODE_1280X720] = imx274_mode5_1280x720_raw10,
|
||||
|
||||
[IMX274_MODE_START_STREAM_1] = imx274_start_1,
|
||||
[IMX274_MODE_START_STREAM_2] = imx274_start_2,
|
||||
[IMX274_MODE_START_STREAM_3] = imx274_start_3,
|
||||
[IMX274_MODE_START_STREAM_4] = imx274_start_4,
|
||||
[IMX274_MODE_STOP_STREAM] = imx274_stop,
|
||||
};
|
||||
|
||||
/*
|
||||
* imx274 format related structure
|
||||
*/
|
||||
static const struct imx274_frmfmt imx274_formats[] = {
|
||||
{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {3840, 2160},
|
||||
IMX274_MODE_3840X2160},
|
||||
{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1920, 1080},
|
||||
IMX274_MODE_1920X1080},
|
||||
{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1280, 720},
|
||||
IMX274_MODE_1280X720},
|
||||
{ {3840, 2160} },
|
||||
{ {1920, 1080} },
|
||||
{ {1280, 720} },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -737,11 +719,11 @@ static int imx274_mode_regs(struct stimx274 *priv, int mode)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_1]);
|
||||
err = imx274_write_table(priv, imx274_start_1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_2]);
|
||||
err = imx274_write_table(priv, imx274_start_2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -766,7 +748,7 @@ static int imx274_start_stream(struct stimx274 *priv)
|
||||
* give it 1 extra ms for margin
|
||||
*/
|
||||
msleep_range(11);
|
||||
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_3]);
|
||||
err = imx274_write_table(priv, imx274_start_3);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -776,7 +758,7 @@ static int imx274_start_stream(struct stimx274 *priv)
|
||||
* give it 1 extra ms for margin
|
||||
*/
|
||||
msleep_range(8);
|
||||
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_4]);
|
||||
err = imx274_write_table(priv, imx274_start_4);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -890,9 +872,8 @@ static int imx274_set_fmt(struct v4l2_subdev *sd,
|
||||
int index;
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"%s: width = %d height = %d code = %d mbus_code = %d\n",
|
||||
__func__, fmt->width, fmt->height, fmt->code,
|
||||
imx274_formats[imx274->mode_index].mbus_code);
|
||||
"%s: width = %d height = %d code = %d\n",
|
||||
__func__, fmt->width, fmt->height, fmt->code);
|
||||
|
||||
mutex_lock(&imx274->lock);
|
||||
|
||||
@@ -971,7 +952,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
|
||||
if (!ret) {
|
||||
/*
|
||||
* exposure time range is decided by frame interval
|
||||
* need to update it after frame interal changes
|
||||
* need to update it after frame interval changes
|
||||
*/
|
||||
min = IMX274_MIN_EXPOSURE_TIME;
|
||||
max = fi->interval.numerator * 1000000
|
||||
@@ -984,7 +965,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
|
||||
}
|
||||
|
||||
/* update exposure time accordingly */
|
||||
imx274_set_exposure(imx274, imx274->ctrls.exposure->val);
|
||||
imx274_set_exposure(imx274, ctrl->val);
|
||||
|
||||
dev_dbg(&imx274->client->dev, "set frame interval to %uus\n",
|
||||
fi->interval.numerator * 1000000
|
||||
@@ -1088,8 +1069,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on)
|
||||
goto fail;
|
||||
} else {
|
||||
/* stop stream */
|
||||
ret = imx274_write_table(imx274,
|
||||
mode_table[IMX274_MODE_STOP_STREAM]);
|
||||
ret = imx274_write_table(imx274, imx274_stop);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
@@ -1133,15 +1113,15 @@ static int imx274_get_frame_length(struct stimx274 *priv, u32 *val)
|
||||
svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
|
||||
|
||||
/* vmax */
|
||||
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_3, ®_val[0]);
|
||||
err = imx274_read_reg(priv, IMX274_VMAX_REG_3, ®_val[0]);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_2, ®_val[1]);
|
||||
err = imx274_read_reg(priv, IMX274_VMAX_REG_2, ®_val[1]);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_1, ®_val[2]);
|
||||
err = imx274_read_reg(priv, IMX274_VMAX_REG_1, ®_val[2]);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
@@ -1300,10 +1280,10 @@ fail:
|
||||
static inline void imx274_calculate_coarse_time_regs(struct reg_8 regs[2],
|
||||
u32 coarse_time)
|
||||
{
|
||||
regs->addr = IMX274_COARSE_TIME_ADDR_MSB;
|
||||
regs->addr = IMX274_SHR_REG_MSB;
|
||||
regs->val = (coarse_time >> IMX274_SHIFT_8_BITS)
|
||||
& IMX274_MASK_LSB_8_BITS;
|
||||
(regs + 1)->addr = IMX274_COARSE_TIME_ADDR_LSB;
|
||||
(regs + 1)->addr = IMX274_SHR_REG_LSB;
|
||||
(regs + 1)->val = (coarse_time) & IMX274_MASK_LSB_8_BITS;
|
||||
}
|
||||
|
||||
@@ -1471,13 +1451,13 @@ static int imx274_set_test_pattern(struct stimx274 *priv, int val)
|
||||
static inline void imx274_calculate_frame_length_regs(struct reg_8 regs[3],
|
||||
u32 frame_length)
|
||||
{
|
||||
regs->addr = IMX274_FRAME_LENGTH_ADDR_1;
|
||||
regs->addr = IMX274_VMAX_REG_1;
|
||||
regs->val = (frame_length >> IMX274_SHIFT_16_BITS)
|
||||
& IMX274_MASK_LSB_4_BITS;
|
||||
(regs + 1)->addr = IMX274_FRAME_LENGTH_ADDR_2;
|
||||
(regs + 1)->addr = IMX274_VMAX_REG_2;
|
||||
(regs + 1)->val = (frame_length >> IMX274_SHIFT_8_BITS)
|
||||
& IMX274_MASK_LSB_8_BITS;
|
||||
(regs + 2)->addr = IMX274_FRAME_LENGTH_ADDR_3;
|
||||
(regs + 2)->addr = IMX274_VMAX_REG_3;
|
||||
(regs + 2)->val = (frame_length) & IMX274_MASK_LSB_8_BITS;
|
||||
}
|
||||
|
||||
@@ -1786,7 +1766,7 @@ static int imx274_remove(struct i2c_client *client)
|
||||
struct stimx274 *imx274 = to_imx274(sd);
|
||||
|
||||
/* stop stream */
|
||||
imx274_write_table(imx274, mode_table[IMX274_MODE_STOP_STREAM]);
|
||||
imx274_write_table(imx274, imx274_stop);
|
||||
|
||||
v4l2_async_unregister_subdev(sd);
|
||||
v4l2_ctrl_handler_free(&imx274->ctrls.handler);
|
||||
|
@@ -739,6 +739,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
struct rc_dev *rc = NULL;
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
unsigned short addr = client->addr;
|
||||
bool probe_tx = (id->driver_data & FLAG_TX) != 0;
|
||||
int err;
|
||||
|
||||
if ((id->driver_data & FLAG_HDPVR) && !enable_hdpvr) {
|
||||
@@ -800,6 +801,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
|
||||
RC_PROTO_BIT_RC6_6A_32;
|
||||
ir_codes = RC_MAP_HAUPPAUGE;
|
||||
probe_tx = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -892,7 +894,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
|
||||
INIT_DELAYED_WORK(&ir->work, ir_work);
|
||||
|
||||
if (id->driver_data & FLAG_TX) {
|
||||
if (probe_tx) {
|
||||
ir->tx_c = i2c_new_dummy(client->adapter, 0x70);
|
||||
if (!ir->tx_c) {
|
||||
dev_err(&client->dev, "failed to setup tx i2c address");
|
||||
|
@@ -1796,7 +1796,6 @@ MODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids);
|
||||
static struct i2c_driver ov13858_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ov13858",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ov13858_pm_ops,
|
||||
.acpi_match_table = ACPI_PTR(ov13858_acpi_ids),
|
||||
},
|
||||
|
@@ -307,6 +307,10 @@ struct ov2640_priv {
|
||||
|
||||
struct gpio_desc *resetb_gpio;
|
||||
struct gpio_desc *pwdn_gpio;
|
||||
|
||||
struct mutex lock; /* lock to protect streaming and power_count */
|
||||
bool streaming;
|
||||
int power_count;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -709,9 +713,20 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
struct v4l2_subdev *sd =
|
||||
&container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
/* v4l2_ctrl_lock() locks our own mutex */
|
||||
|
||||
/*
|
||||
* If the device is not powered up by the host driver, do not apply any
|
||||
* controls to H/W at this time. Instead the controls will be restored
|
||||
* when the streaming is started.
|
||||
*/
|
||||
if (!priv->power_count)
|
||||
return 0;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -763,12 +778,9 @@ static int ov2640_s_register(struct v4l2_subdev *sd,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ov2640_s_power(struct v4l2_subdev *sd, int on)
|
||||
static void ov2640_set_power(struct ov2640_priv *priv, int on)
|
||||
{
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
if (priv->pwdn_gpio)
|
||||
gpiod_direction_output(priv->pwdn_gpio, !on);
|
||||
if (on && priv->resetb_gpio) {
|
||||
@@ -778,6 +790,25 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on)
|
||||
gpiod_set_value(priv->resetb_gpio, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ov2640_s_power(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
/*
|
||||
* If the power count is modified from 0 to != 0 or from != 0 to 0,
|
||||
* update the power state.
|
||||
*/
|
||||
if (priv->power_count == !on)
|
||||
ov2640_set_power(priv, on);
|
||||
priv->power_count += on ? 1 : -1;
|
||||
WARN_ON(priv->power_count < 0);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -798,16 +829,13 @@ static const struct ov2640_win_size *ov2640_select_win(u32 width, u32 height)
|
||||
static int ov2640_set_params(struct i2c_client *client,
|
||||
const struct ov2640_win_size *win, u32 code)
|
||||
{
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
const struct regval_list *selected_cfmt_regs;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
/* select win */
|
||||
priv->win = win;
|
||||
if (!win)
|
||||
return -EINVAL;
|
||||
|
||||
/* select format */
|
||||
priv->cfmt_code = 0;
|
||||
switch (code) {
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_BE:
|
||||
dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
|
||||
@@ -846,13 +874,13 @@ static int ov2640_set_params(struct i2c_client *client,
|
||||
goto err;
|
||||
|
||||
/* select preamble */
|
||||
dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name);
|
||||
dev_dbg(&client->dev, "%s: Set size to %s", __func__, win->name);
|
||||
ret = ov2640_write_array(client, ov2640_size_change_preamble_regs);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* set size win */
|
||||
ret = ov2640_write_array(client, priv->win->regs);
|
||||
ret = ov2640_write_array(client, win->regs);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
@@ -872,14 +900,11 @@ static int ov2640_set_params(struct i2c_client *client,
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
priv->cfmt_code = code;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_err(&client->dev, "%s: Error %d", __func__, ret);
|
||||
ov2640_reset(client);
|
||||
priv->win = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -915,11 +940,15 @@ static int ov2640_set_fmt(struct v4l2_subdev *sd,
|
||||
{
|
||||
struct v4l2_mbus_framefmt *mf = &format->format;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
const struct ov2640_win_size *win;
|
||||
int ret = 0;
|
||||
|
||||
if (format->pad)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
/* select suitable win */
|
||||
win = ov2640_select_win(mf->width, mf->height);
|
||||
mf->width = win->width;
|
||||
@@ -941,10 +970,24 @@ static int ov2640_set_fmt(struct v4l2_subdev *sd,
|
||||
break;
|
||||
}
|
||||
|
||||
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
return ov2640_set_params(client, win, mf->code);
|
||||
cfg->try_fmt = *mf;
|
||||
return 0;
|
||||
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
if (priv->streaming) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
/* select win */
|
||||
priv->win = win;
|
||||
/* select format */
|
||||
priv->cfmt_code = mf->code;
|
||||
} else {
|
||||
cfg->try_fmt = *mf;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
@@ -979,6 +1022,28 @@ static int ov2640_get_selection(struct v4l2_subdev *sd,
|
||||
}
|
||||
}
|
||||
|
||||
static int ov2640_s_stream(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
if (priv->streaming == !on) {
|
||||
if (on) {
|
||||
ret = ov2640_set_params(client, priv->win,
|
||||
priv->cfmt_code);
|
||||
if (!ret)
|
||||
ret = __v4l2_ctrl_handler_setup(&priv->hdl);
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
priv->streaming = on;
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov2640_video_probe(struct i2c_client *client)
|
||||
{
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
@@ -1014,8 +1079,6 @@ static int ov2640_video_probe(struct i2c_client *client)
|
||||
"%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
|
||||
devname, pid, ver, midh, midl);
|
||||
|
||||
ret = v4l2_ctrl_handler_setup(&priv->hdl);
|
||||
|
||||
done:
|
||||
ov2640_s_power(&priv->subdev, 0);
|
||||
return ret;
|
||||
@@ -1040,9 +1103,14 @@ static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
|
||||
.set_fmt = ov2640_set_fmt,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
|
||||
.s_stream = ov2640_s_stream,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops ov2640_subdev_ops = {
|
||||
.core = &ov2640_subdev_core_ops,
|
||||
.pad = &ov2640_subdev_pad_ops,
|
||||
.video = &ov2640_subdev_video_ops,
|
||||
};
|
||||
|
||||
static int ov2640_probe_dt(struct i2c_client *client,
|
||||
@@ -1116,7 +1184,9 @@ static int ov2640_probe(struct i2c_client *client,
|
||||
|
||||
v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
|
||||
priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
mutex_init(&priv->lock);
|
||||
v4l2_ctrl_handler_init(&priv->hdl, 2);
|
||||
priv->hdl.lock = &priv->lock;
|
||||
v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
|
||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||
v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
|
||||
@@ -1150,6 +1220,7 @@ err_videoprobe:
|
||||
media_entity_cleanup(&priv->subdev.entity);
|
||||
err_hdl:
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
mutex_destroy(&priv->lock);
|
||||
err_clk:
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
@@ -1161,6 +1232,7 @@ static int ov2640_remove(struct i2c_client *client)
|
||||
|
||||
v4l2_async_unregister_subdev(&priv->subdev);
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
mutex_destroy(&priv->lock);
|
||||
media_entity_cleanup(&priv->subdev.entity);
|
||||
v4l2_device_unregister_subdev(&priv->subdev);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
@@ -60,6 +60,8 @@
|
||||
#define OV5640_REG_AEC_PK_MANUAL 0x3503
|
||||
#define OV5640_REG_AEC_PK_REAL_GAIN 0x350a
|
||||
#define OV5640_REG_AEC_PK_VTS 0x350c
|
||||
#define OV5640_REG_TIMING_DVPHO 0x3808
|
||||
#define OV5640_REG_TIMING_DVPVO 0x380a
|
||||
#define OV5640_REG_TIMING_HTS 0x380c
|
||||
#define OV5640_REG_TIMING_VTS 0x380e
|
||||
#define OV5640_REG_TIMING_TC_REG21 0x3821
|
||||
@@ -91,6 +93,9 @@
|
||||
#define OV5640_REG_SDE_CTRL5 0x5585
|
||||
#define OV5640_REG_AVG_READOUT 0x56a1
|
||||
|
||||
#define OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT 1
|
||||
#define OV5640_SCLK_ROOT_DIVIDER_DEFAULT 2
|
||||
|
||||
enum ov5640_mode_id {
|
||||
OV5640_MODE_QCIF_176_144 = 0,
|
||||
OV5640_MODE_QVGA_320_240,
|
||||
@@ -165,8 +170,10 @@ struct reg_value {
|
||||
struct ov5640_mode_info {
|
||||
enum ov5640_mode_id id;
|
||||
enum ov5640_downsize_mode dn_mode;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 hact;
|
||||
u32 htot;
|
||||
u32 vact;
|
||||
u32 vtot;
|
||||
const struct reg_value *reg_data;
|
||||
u32 reg_data_size;
|
||||
};
|
||||
@@ -187,6 +194,7 @@ struct ov5640_ctrls {
|
||||
struct v4l2_ctrl *gain;
|
||||
};
|
||||
struct v4l2_ctrl *brightness;
|
||||
struct v4l2_ctrl *light_freq;
|
||||
struct v4l2_ctrl *saturation;
|
||||
struct v4l2_ctrl *contrast;
|
||||
struct v4l2_ctrl *hue;
|
||||
@@ -248,7 +256,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
||||
{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
|
||||
{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
|
||||
{0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
|
||||
{0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
|
||||
{0x3037, 0x13, 0, 0}, {0x3630, 0x36, 0, 0},
|
||||
{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
|
||||
{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
|
||||
{0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
|
||||
@@ -265,9 +273,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -339,9 +345,7 @@ static const struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -360,9 +364,7 @@ static const struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -381,9 +383,7 @@ static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -393,8 +393,7 @@ static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
|
||||
{0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
|
||||
{0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
|
||||
{0x3035, 0x12, 0, 0},
|
||||
};
|
||||
|
||||
static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
||||
@@ -404,9 +403,7 @@ static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -415,8 +412,7 @@ static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
|
||||
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
|
||||
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
|
||||
{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
|
||||
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
|
||||
{0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
|
||||
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
|
||||
};
|
||||
|
||||
static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
||||
@@ -426,9 +422,7 @@ static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
|
||||
{0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -447,9 +441,7 @@ static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
|
||||
{0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -468,9 +460,7 @@ static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
|
||||
{0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -489,9 +479,7 @@ static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
|
||||
{0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -510,9 +498,7 @@ static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -531,9 +517,7 @@ static const struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
|
||||
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -552,9 +536,7 @@ static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
|
||||
{0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -573,9 +555,7 @@ static const struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
|
||||
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
|
||||
{0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
|
||||
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -595,9 +575,7 @@ static const struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
|
||||
{0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
|
||||
{0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
|
||||
{0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
|
||||
@@ -617,9 +595,7 @@ static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
|
||||
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
|
||||
{0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
|
||||
{0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
|
||||
{0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
|
||||
@@ -639,9 +615,7 @@ static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
|
||||
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
||||
{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
|
||||
{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
|
||||
{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
|
||||
{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -655,10 +629,8 @@ static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
|
||||
{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
|
||||
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
|
||||
{0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
|
||||
{0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
|
||||
{0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
|
||||
{0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
|
||||
{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
|
||||
{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
|
||||
@@ -676,9 +648,7 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
||||
{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
|
||||
{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
|
||||
{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
|
||||
{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -692,10 +662,8 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
|
||||
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
|
||||
{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
|
||||
{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
|
||||
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
|
||||
{0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
|
||||
{0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
|
||||
{0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
|
||||
{0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
|
||||
{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
|
||||
{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
|
||||
{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
|
||||
@@ -712,9 +680,7 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
||||
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
|
||||
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
|
||||
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
|
||||
{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
|
||||
{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
|
||||
{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
|
||||
{0x3810, 0x00, 0, 0},
|
||||
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
|
||||
{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
|
||||
{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
|
||||
@@ -728,66 +694,84 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
|
||||
|
||||
/* power-on sensor init reg table */
|
||||
static const struct ov5640_mode_info ov5640_mode_init_data = {
|
||||
0, SUBSAMPLING, 640, 480, ov5640_init_setting_30fps_VGA,
|
||||
0, SUBSAMPLING, 640, 1896, 480, 984,
|
||||
ov5640_init_setting_30fps_VGA,
|
||||
ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
|
||||
};
|
||||
|
||||
static const struct ov5640_mode_info
|
||||
ov5640_mode_data[OV5640_NUM_FRAMERATES][OV5640_NUM_MODES] = {
|
||||
{
|
||||
{OV5640_MODE_QCIF_176_144, SUBSAMPLING, 176, 144,
|
||||
{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||
176, 1896, 144, 984,
|
||||
ov5640_setting_15fps_QCIF_176_144,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
|
||||
{OV5640_MODE_QVGA_320_240, SUBSAMPLING, 320, 240,
|
||||
{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||
320, 1896, 240, 984,
|
||||
ov5640_setting_15fps_QVGA_320_240,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
|
||||
{OV5640_MODE_VGA_640_480, SUBSAMPLING, 640, 480,
|
||||
{OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||
640, 1896, 480, 1080,
|
||||
ov5640_setting_15fps_VGA_640_480,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
|
||||
{OV5640_MODE_NTSC_720_480, SUBSAMPLING, 720, 480,
|
||||
{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||
720, 1896, 480, 984,
|
||||
ov5640_setting_15fps_NTSC_720_480,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
|
||||
{OV5640_MODE_PAL_720_576, SUBSAMPLING, 720, 576,
|
||||
{OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||
720, 1896, 576, 984,
|
||||
ov5640_setting_15fps_PAL_720_576,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
|
||||
{OV5640_MODE_XGA_1024_768, SUBSAMPLING, 1024, 768,
|
||||
{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||
1024, 1896, 768, 1080,
|
||||
ov5640_setting_15fps_XGA_1024_768,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
|
||||
{OV5640_MODE_720P_1280_720, SUBSAMPLING, 1280, 720,
|
||||
{OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||
1280, 1892, 720, 740,
|
||||
ov5640_setting_15fps_720P_1280_720,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
|
||||
{OV5640_MODE_1080P_1920_1080, SCALING, 1920, 1080,
|
||||
{OV5640_MODE_1080P_1920_1080, SCALING,
|
||||
1920, 2500, 1080, 1120,
|
||||
ov5640_setting_15fps_1080P_1920_1080,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
|
||||
{OV5640_MODE_QSXGA_2592_1944, SCALING, 2592, 1944,
|
||||
{OV5640_MODE_QSXGA_2592_1944, SCALING,
|
||||
2592, 2844, 1944, 1968,
|
||||
ov5640_setting_15fps_QSXGA_2592_1944,
|
||||
ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
|
||||
}, {
|
||||
{OV5640_MODE_QCIF_176_144, SUBSAMPLING, 176, 144,
|
||||
{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
|
||||
176, 1896, 144, 984,
|
||||
ov5640_setting_30fps_QCIF_176_144,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
|
||||
{OV5640_MODE_QVGA_320_240, SUBSAMPLING, 320, 240,
|
||||
{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
|
||||
320, 1896, 240, 984,
|
||||
ov5640_setting_30fps_QVGA_320_240,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
|
||||
{OV5640_MODE_VGA_640_480, SUBSAMPLING, 640, 480,
|
||||
{OV5640_MODE_VGA_640_480, SUBSAMPLING,
|
||||
640, 1896, 480, 1080,
|
||||
ov5640_setting_30fps_VGA_640_480,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
|
||||
{OV5640_MODE_NTSC_720_480, SUBSAMPLING, 720, 480,
|
||||
{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
|
||||
720, 1896, 480, 984,
|
||||
ov5640_setting_30fps_NTSC_720_480,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
|
||||
{OV5640_MODE_PAL_720_576, SUBSAMPLING, 720, 576,
|
||||
{OV5640_MODE_PAL_720_576, SUBSAMPLING,
|
||||
720, 1896, 576, 984,
|
||||
ov5640_setting_30fps_PAL_720_576,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
|
||||
{OV5640_MODE_XGA_1024_768, SUBSAMPLING, 1024, 768,
|
||||
{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
|
||||
1024, 1896, 768, 1080,
|
||||
ov5640_setting_30fps_XGA_1024_768,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
|
||||
{OV5640_MODE_720P_1280_720, SUBSAMPLING, 1280, 720,
|
||||
{OV5640_MODE_720P_1280_720, SUBSAMPLING,
|
||||
1280, 1892, 720, 740,
|
||||
ov5640_setting_30fps_720P_1280_720,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
|
||||
{OV5640_MODE_1080P_1920_1080, SCALING, 1920, 1080,
|
||||
{OV5640_MODE_1080P_1920_1080, SCALING,
|
||||
1920, 2500, 1080, 1120,
|
||||
ov5640_setting_30fps_1080P_1920_1080,
|
||||
ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
|
||||
{OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
|
||||
{OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, 0, 0, NULL, 0},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1377,6 +1361,30 @@ static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
|
||||
return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp);
|
||||
}
|
||||
|
||||
static int ov5640_set_timings(struct ov5640_dev *sensor,
|
||||
const struct ov5640_mode_info *mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ov5640_mode_info *
|
||||
ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
|
||||
int width, int height, bool nearest)
|
||||
@@ -1390,10 +1398,10 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
|
||||
if (!mode->reg_data)
|
||||
continue;
|
||||
|
||||
if ((nearest && mode->width <= width &&
|
||||
mode->height <= height) ||
|
||||
(!nearest && mode->width == width &&
|
||||
mode->height == height))
|
||||
if ((nearest && mode->hact <= width &&
|
||||
mode->vact <= height) ||
|
||||
(!nearest && mode->hact == width &&
|
||||
mode->vact == height))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1568,7 +1576,8 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
|
||||
* change mode directly
|
||||
*/
|
||||
static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
|
||||
const struct ov5640_mode_info *mode)
|
||||
const struct ov5640_mode_info *mode,
|
||||
s32 exposure)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1584,7 +1593,8 @@ static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
|
||||
ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, V4L2_EXPOSURE_AUTO);
|
||||
|
||||
return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure);
|
||||
}
|
||||
|
||||
static int ov5640_set_mode(struct ov5640_dev *sensor,
|
||||
@@ -1592,6 +1602,7 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
|
||||
{
|
||||
const struct ov5640_mode_info *mode = sensor->current_mode;
|
||||
enum ov5640_downsize_mode dn_mode, orig_dn_mode;
|
||||
s32 exposure;
|
||||
int ret;
|
||||
|
||||
dn_mode = mode->dn_mode;
|
||||
@@ -1601,7 +1612,9 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
|
||||
ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, V4L2_EXPOSURE_MANUAL);
|
||||
|
||||
exposure = sensor->ctrls.auto_exp->val;
|
||||
ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1617,9 +1630,13 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
|
||||
* change inside subsampling or scaling
|
||||
* download firmware directly
|
||||
*/
|
||||
ret = ov5640_set_mode_direct(sensor, mode);
|
||||
ret = ov5640_set_mode_direct(sensor, mode, exposure);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5640_set_timings(sensor, mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -1654,6 +1671,12 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
|
||||
(ilog2(OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT) << 2) |
|
||||
ilog2(OV5640_SCLK_ROOT_DIVIDER_DEFAULT));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* now restore the last capture mode */
|
||||
ret = ov5640_set_mode(sensor, &ov5640_mode_init_data);
|
||||
if (ret < 0)
|
||||
@@ -1871,8 +1894,8 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
|
||||
mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
|
||||
if (!mode)
|
||||
return -EINVAL;
|
||||
fmt->width = mode->width;
|
||||
fmt->height = mode->height;
|
||||
fmt->width = mode->hact;
|
||||
fmt->height = mode->vact;
|
||||
|
||||
if (new_mode)
|
||||
*new_mode = mode;
|
||||
@@ -2155,6 +2178,21 @@ static int ov5640_set_ctrl_test_pattern(struct ov5640_dev *sensor, int value)
|
||||
0xa4, value ? 0xa4 : 0);
|
||||
}
|
||||
|
||||
static int ov5640_set_ctrl_light_freq(struct ov5640_dev *sensor, int value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov5640_mod_reg(sensor, OV5640_REG_HZ5060_CTRL01, BIT(7),
|
||||
(value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) ?
|
||||
0 : BIT(7));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ov5640_mod_reg(sensor, OV5640_REG_HZ5060_CTRL00, BIT(2),
|
||||
(value == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) ?
|
||||
BIT(2) : 0);
|
||||
}
|
||||
|
||||
static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
|
||||
@@ -2223,6 +2261,9 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_TEST_PATTERN:
|
||||
ret = ov5640_set_ctrl_test_pattern(sensor, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_POWER_LINE_FREQUENCY:
|
||||
ret = ov5640_set_ctrl_light_freq(sensor, ctrl->val);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
@@ -2285,6 +2326,12 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
|
||||
ARRAY_SIZE(test_pattern_menu) - 1,
|
||||
0, 0, test_pattern_menu);
|
||||
|
||||
ctrls->light_freq =
|
||||
v4l2_ctrl_new_std_menu(hdl, ops,
|
||||
V4L2_CID_POWER_LINE_FREQUENCY,
|
||||
V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
|
||||
V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
|
||||
|
||||
if (hdl->error) {
|
||||
ret = hdl->error;
|
||||
goto free_ctrls;
|
||||
@@ -2315,10 +2362,10 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
|
||||
return -EINVAL;
|
||||
|
||||
fse->min_width =
|
||||
ov5640_mode_data[0][fse->index].width;
|
||||
ov5640_mode_data[0][fse->index].hact;
|
||||
fse->max_width = fse->min_width;
|
||||
fse->min_height =
|
||||
ov5640_mode_data[0][fse->index].height;
|
||||
ov5640_mode_data[0][fse->index].vact;
|
||||
fse->max_height = fse->min_height;
|
||||
|
||||
return 0;
|
||||
@@ -2382,14 +2429,14 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
|
||||
mode = sensor->current_mode;
|
||||
|
||||
frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
|
||||
mode->width, mode->height);
|
||||
mode->hact, mode->vact);
|
||||
if (frame_rate < 0)
|
||||
frame_rate = OV5640_15_FPS;
|
||||
|
||||
sensor->current_fr = frame_rate;
|
||||
sensor->frame_interval = fi->interval;
|
||||
sensor->current_mode = ov5640_find_mode(sensor, frame_rate, mode->width,
|
||||
mode->height, true);
|
||||
sensor->current_mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
|
||||
mode->vact, true);
|
||||
sensor->pending_mode_change = true;
|
||||
out:
|
||||
mutex_unlock(&sensor->lock);
|
||||
@@ -2536,8 +2583,8 @@ static int ov5640_probe(struct i2c_client *client,
|
||||
|
||||
sensor->ae_target = 52;
|
||||
|
||||
endpoint = fwnode_graph_get_next_endpoint(
|
||||
of_fwnode_handle(client->dev.of_node), NULL);
|
||||
endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
|
||||
NULL);
|
||||
if (!endpoint) {
|
||||
dev_err(dev, "endpoint node not found\n");
|
||||
return -EINVAL;
|
||||
|
@@ -600,11 +600,13 @@ static int ov5645_write_reg(struct ov5645 *ov5645, u16 reg, u8 val)
|
||||
regbuf[2] = val;
|
||||
|
||||
ret = i2c_master_send(ov5645->i2c_client, regbuf, 3);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(ov5645->dev, "%s: write reg error %d: reg=%x, val=%x\n",
|
||||
__func__, ret, reg, val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov5645_read_reg(struct ov5645 *ov5645, u16 reg, u8 *val)
|
||||
|
@@ -1385,7 +1385,6 @@ MODULE_DEVICE_TABLE(of, ov5695_of_match);
|
||||
static struct i2c_driver ov5695_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ov5695",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ov5695_pm_ops,
|
||||
.of_match_table = of_match_ptr(ov5695_of_match),
|
||||
},
|
||||
|
1503
drivers/media/i2c/ov7251.c
Normal file
1503
drivers/media/i2c/ov7251.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1035,7 +1035,7 @@ static int ov772x_set_params(struct ov772x_priv *priv,
|
||||
|
||||
/* Set COM8. */
|
||||
if (priv->band_filter) {
|
||||
ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1);
|
||||
ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, BNDF_ON_OFF);
|
||||
if (!ret)
|
||||
ret = ov772x_mask_set(client, BDBASE,
|
||||
0xff, 256 - priv->band_filter);
|
||||
|
@@ -953,7 +953,7 @@ static int ov7740_init_controls(struct ov7740 *ov7740)
|
||||
struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
|
||||
int ret;
|
||||
|
||||
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 2);
|
||||
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -980,27 +980,39 @@ static int ov7740_init_controls(struct ov7740 *ov7740)
|
||||
V4L2_CID_HFLIP, 0, 1, 1, 0);
|
||||
ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
|
||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||
|
||||
ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
|
||||
V4L2_CID_GAIN, 0, 1023, 1, 500);
|
||||
if (ov7740->gain)
|
||||
ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
|
||||
ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
|
||||
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
|
||||
|
||||
ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
|
||||
if (ov7740->exposure)
|
||||
ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
|
||||
ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
|
||||
&ov7740_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE_AUTO,
|
||||
V4L2_EXPOSURE_MANUAL, 0,
|
||||
V4L2_EXPOSURE_AUTO);
|
||||
|
||||
ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
|
||||
v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
|
||||
v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
|
||||
v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
|
||||
V4L2_EXPOSURE_MANUAL, false);
|
||||
v4l2_ctrl_cluster(2, &ov7740->hflip);
|
||||
|
||||
if (ctrl_hdlr->error) {
|
||||
ret = ctrl_hdlr->error;
|
||||
dev_err(&client->dev, "controls initialisation failed (%d)\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "%s control init failed (%d)\n",
|
||||
@@ -1074,7 +1086,7 @@ static int ov7740_probe(struct i2c_client *client,
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
|
||||
sd->internal_ops = &ov7740_subdev_internal_ops;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
|
@@ -1001,7 +1001,7 @@ static int smiapp_read_nvm(struct smiapp_sensor *sensor,
|
||||
if (rval)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
for (i = 1000; i > 0; i--) {
|
||||
rval = smiapp_read(
|
||||
sensor,
|
||||
SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS, &s);
|
||||
@@ -1012,11 +1012,10 @@ static int smiapp_read_nvm(struct smiapp_sensor *sensor,
|
||||
if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
|
||||
break;
|
||||
|
||||
if (--i == 0) {
|
||||
rval = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
if (!i) {
|
||||
rval = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < SMIAPP_NVM_PAGE_SIZE; i++) {
|
||||
|
@@ -2569,7 +2569,7 @@ static int tda1997x_probe(struct i2c_client *client,
|
||||
snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
|
||||
id->name, i2c_adapter_id(client->adapter),
|
||||
client->addr);
|
||||
sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
sd->entity.function = MEDIA_ENT_F_DTV_DECODER;
|
||||
sd->entity.ops = &tda1997x_media_ops;
|
||||
|
||||
@@ -2723,7 +2723,7 @@ static int tda1997x_probe(struct i2c_client *client,
|
||||
state->pads);
|
||||
if (ret) {
|
||||
v4l_err(client, "failed entity_init: %d", ret);
|
||||
goto err_free_mutex;
|
||||
goto err_free_handler;
|
||||
}
|
||||
|
||||
ret = v4l2_async_register_subdev(sd);
|
||||
|
@@ -319,136 +319,136 @@ struct i2c_reg_value {
|
||||
/* Default values as sugested at TVP5150AM1 datasheet */
|
||||
static const struct i2c_reg_value tvp5150_init_default[] = {
|
||||
{ /* 0x00 */
|
||||
TVP5150_VD_IN_SRC_SEL_1,0x00
|
||||
TVP5150_VD_IN_SRC_SEL_1, 0x00
|
||||
},
|
||||
{ /* 0x01 */
|
||||
TVP5150_ANAL_CHL_CTL,0x15
|
||||
TVP5150_ANAL_CHL_CTL, 0x15
|
||||
},
|
||||
{ /* 0x02 */
|
||||
TVP5150_OP_MODE_CTL,0x00
|
||||
TVP5150_OP_MODE_CTL, 0x00
|
||||
},
|
||||
{ /* 0x03 */
|
||||
TVP5150_MISC_CTL,0x01
|
||||
TVP5150_MISC_CTL, 0x01
|
||||
},
|
||||
{ /* 0x06 */
|
||||
TVP5150_COLOR_KIL_THSH_CTL,0x10
|
||||
TVP5150_COLOR_KIL_THSH_CTL, 0x10
|
||||
},
|
||||
{ /* 0x07 */
|
||||
TVP5150_LUMA_PROC_CTL_1,0x60
|
||||
TVP5150_LUMA_PROC_CTL_1, 0x60
|
||||
},
|
||||
{ /* 0x08 */
|
||||
TVP5150_LUMA_PROC_CTL_2,0x00
|
||||
TVP5150_LUMA_PROC_CTL_2, 0x00
|
||||
},
|
||||
{ /* 0x09 */
|
||||
TVP5150_BRIGHT_CTL,0x80
|
||||
TVP5150_BRIGHT_CTL, 0x80
|
||||
},
|
||||
{ /* 0x0a */
|
||||
TVP5150_SATURATION_CTL,0x80
|
||||
TVP5150_SATURATION_CTL, 0x80
|
||||
},
|
||||
{ /* 0x0b */
|
||||
TVP5150_HUE_CTL,0x00
|
||||
TVP5150_HUE_CTL, 0x00
|
||||
},
|
||||
{ /* 0x0c */
|
||||
TVP5150_CONTRAST_CTL,0x80
|
||||
TVP5150_CONTRAST_CTL, 0x80
|
||||
},
|
||||
{ /* 0x0d */
|
||||
TVP5150_DATA_RATE_SEL,0x47
|
||||
TVP5150_DATA_RATE_SEL, 0x47
|
||||
},
|
||||
{ /* 0x0e */
|
||||
TVP5150_LUMA_PROC_CTL_3,0x00
|
||||
TVP5150_LUMA_PROC_CTL_3, 0x00
|
||||
},
|
||||
{ /* 0x0f */
|
||||
TVP5150_CONF_SHARED_PIN,0x08
|
||||
TVP5150_CONF_SHARED_PIN, 0x08
|
||||
},
|
||||
{ /* 0x11 */
|
||||
TVP5150_ACT_VD_CROP_ST_MSB,0x00
|
||||
TVP5150_ACT_VD_CROP_ST_MSB, 0x00
|
||||
},
|
||||
{ /* 0x12 */
|
||||
TVP5150_ACT_VD_CROP_ST_LSB,0x00
|
||||
TVP5150_ACT_VD_CROP_ST_LSB, 0x00
|
||||
},
|
||||
{ /* 0x13 */
|
||||
TVP5150_ACT_VD_CROP_STP_MSB,0x00
|
||||
TVP5150_ACT_VD_CROP_STP_MSB, 0x00
|
||||
},
|
||||
{ /* 0x14 */
|
||||
TVP5150_ACT_VD_CROP_STP_LSB,0x00
|
||||
TVP5150_ACT_VD_CROP_STP_LSB, 0x00
|
||||
},
|
||||
{ /* 0x15 */
|
||||
TVP5150_GENLOCK,0x01
|
||||
TVP5150_GENLOCK, 0x01
|
||||
},
|
||||
{ /* 0x16 */
|
||||
TVP5150_HORIZ_SYNC_START,0x80
|
||||
TVP5150_HORIZ_SYNC_START, 0x80
|
||||
},
|
||||
{ /* 0x18 */
|
||||
TVP5150_VERT_BLANKING_START,0x00
|
||||
TVP5150_VERT_BLANKING_START, 0x00
|
||||
},
|
||||
{ /* 0x19 */
|
||||
TVP5150_VERT_BLANKING_STOP,0x00
|
||||
TVP5150_VERT_BLANKING_STOP, 0x00
|
||||
},
|
||||
{ /* 0x1a */
|
||||
TVP5150_CHROMA_PROC_CTL_1,0x0c
|
||||
TVP5150_CHROMA_PROC_CTL_1, 0x0c
|
||||
},
|
||||
{ /* 0x1b */
|
||||
TVP5150_CHROMA_PROC_CTL_2,0x14
|
||||
TVP5150_CHROMA_PROC_CTL_2, 0x14
|
||||
},
|
||||
{ /* 0x1c */
|
||||
TVP5150_INT_RESET_REG_B,0x00
|
||||
TVP5150_INT_RESET_REG_B, 0x00
|
||||
},
|
||||
{ /* 0x1d */
|
||||
TVP5150_INT_ENABLE_REG_B,0x00
|
||||
TVP5150_INT_ENABLE_REG_B, 0x00
|
||||
},
|
||||
{ /* 0x1e */
|
||||
TVP5150_INTT_CONFIG_REG_B,0x00
|
||||
TVP5150_INTT_CONFIG_REG_B, 0x00
|
||||
},
|
||||
{ /* 0x28 */
|
||||
TVP5150_VIDEO_STD,0x00
|
||||
TVP5150_VIDEO_STD, 0x00
|
||||
},
|
||||
{ /* 0x2e */
|
||||
TVP5150_MACROVISION_ON_CTR,0x0f
|
||||
TVP5150_MACROVISION_ON_CTR, 0x0f
|
||||
},
|
||||
{ /* 0x2f */
|
||||
TVP5150_MACROVISION_OFF_CTR,0x01
|
||||
TVP5150_MACROVISION_OFF_CTR, 0x01
|
||||
},
|
||||
{ /* 0xbb */
|
||||
TVP5150_TELETEXT_FIL_ENA,0x00
|
||||
TVP5150_TELETEXT_FIL_ENA, 0x00
|
||||
},
|
||||
{ /* 0xc0 */
|
||||
TVP5150_INT_STATUS_REG_A,0x00
|
||||
TVP5150_INT_STATUS_REG_A, 0x00
|
||||
},
|
||||
{ /* 0xc1 */
|
||||
TVP5150_INT_ENABLE_REG_A,0x00
|
||||
TVP5150_INT_ENABLE_REG_A, 0x00
|
||||
},
|
||||
{ /* 0xc2 */
|
||||
TVP5150_INT_CONF,0x04
|
||||
TVP5150_INT_CONF, 0x04
|
||||
},
|
||||
{ /* 0xc8 */
|
||||
TVP5150_FIFO_INT_THRESHOLD,0x80
|
||||
TVP5150_FIFO_INT_THRESHOLD, 0x80
|
||||
},
|
||||
{ /* 0xc9 */
|
||||
TVP5150_FIFO_RESET,0x00
|
||||
TVP5150_FIFO_RESET, 0x00
|
||||
},
|
||||
{ /* 0xca */
|
||||
TVP5150_LINE_NUMBER_INT,0x00
|
||||
TVP5150_LINE_NUMBER_INT, 0x00
|
||||
},
|
||||
{ /* 0xcb */
|
||||
TVP5150_PIX_ALIGN_REG_LOW,0x4e
|
||||
TVP5150_PIX_ALIGN_REG_LOW, 0x4e
|
||||
},
|
||||
{ /* 0xcc */
|
||||
TVP5150_PIX_ALIGN_REG_HIGH,0x00
|
||||
TVP5150_PIX_ALIGN_REG_HIGH, 0x00
|
||||
},
|
||||
{ /* 0xcd */
|
||||
TVP5150_FIFO_OUT_CTRL,0x01
|
||||
TVP5150_FIFO_OUT_CTRL, 0x01
|
||||
},
|
||||
{ /* 0xcf */
|
||||
TVP5150_FULL_FIELD_ENA,0x00
|
||||
TVP5150_FULL_FIELD_ENA, 0x00
|
||||
},
|
||||
{ /* 0xd0 */
|
||||
TVP5150_LINE_MODE_INI,0x00
|
||||
TVP5150_LINE_MODE_INI, 0x00
|
||||
},
|
||||
{ /* 0xfc */
|
||||
TVP5150_FULL_FIELD_MODE_REG,0x7f
|
||||
TVP5150_FULL_FIELD_MODE_REG, 0x7f
|
||||
},
|
||||
{ /* end of data */
|
||||
0xff,0xff
|
||||
0xff, 0xff
|
||||
}
|
||||
};
|
||||
|
||||
@@ -456,27 +456,27 @@ static const struct i2c_reg_value tvp5150_init_default[] = {
|
||||
static const struct i2c_reg_value tvp5150_init_enable[] = {
|
||||
{
|
||||
TVP5150_CONF_SHARED_PIN, 2
|
||||
},{ /* Automatic offset and AGC enabled */
|
||||
}, { /* Automatic offset and AGC enabled */
|
||||
TVP5150_ANAL_CHL_CTL, 0x15
|
||||
},{ /* Activate YCrCb output 0x9 or 0xd ? */
|
||||
}, { /* Activate YCrCb output 0x9 or 0xd ? */
|
||||
TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
|
||||
TVP5150_MISC_CTL_INTREQ_OE |
|
||||
TVP5150_MISC_CTL_YCBCR_OE |
|
||||
TVP5150_MISC_CTL_SYNC_OE |
|
||||
TVP5150_MISC_CTL_VBLANK |
|
||||
TVP5150_MISC_CTL_CLOCK_OE,
|
||||
},{ /* Activates video std autodetection for all standards */
|
||||
}, { /* Activates video std autodetection for all standards */
|
||||
TVP5150_AUTOSW_MSK, 0x0
|
||||
},{ /* Default format: 0x47. For 4:2:2: 0x40 */
|
||||
}, { /* Default format: 0x47. For 4:2:2: 0x40 */
|
||||
TVP5150_DATA_RATE_SEL, 0x47
|
||||
},{
|
||||
}, {
|
||||
TVP5150_CHROMA_PROC_CTL_1, 0x0c
|
||||
},{
|
||||
}, {
|
||||
TVP5150_CHROMA_PROC_CTL_2, 0x54
|
||||
},{ /* Non documented, but initialized on WinTV USB2 */
|
||||
}, { /* Non documented, but initialized on WinTV USB2 */
|
||||
0x27, 0x20
|
||||
},{
|
||||
0xff,0xff
|
||||
}, {
|
||||
0xff, 0xff
|
||||
}
|
||||
};
|
||||
|
||||
@@ -500,78 +500,80 @@ struct i2c_vbi_ram_value {
|
||||
* and so on. There are 16 possible locations from 0 to 15.
|
||||
*/
|
||||
|
||||
static struct i2c_vbi_ram_value vbi_ram_default[] =
|
||||
{
|
||||
/* FIXME: Current api doesn't handle all VBI types, those not
|
||||
yet supported are placed under #if 0 */
|
||||
static struct i2c_vbi_ram_value vbi_ram_default[] = {
|
||||
|
||||
/*
|
||||
* FIXME: Current api doesn't handle all VBI types, those not
|
||||
* yet supported are placed under #if 0
|
||||
*/
|
||||
#if 0
|
||||
[0] = {0x010, /* Teletext, SECAM, WST System A */
|
||||
{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
|
||||
{V4L2_SLICED_TELETEXT_SECAM, 6, 23, 1},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
|
||||
0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
||||
},
|
||||
#endif
|
||||
[1] = {0x030, /* Teletext, PAL, WST System B */
|
||||
{V4L2_SLICED_TELETEXT_B,6,22,1},
|
||||
{V4L2_SLICED_TELETEXT_B, 6, 22, 1},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
|
||||
0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
||||
},
|
||||
#if 0
|
||||
[2] = {0x050, /* Teletext, PAL, WST System C */
|
||||
{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
|
||||
{V4L2_SLICED_TELETEXT_PAL_C, 6, 22, 1},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
|
||||
0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
||||
},
|
||||
[3] = {0x070, /* Teletext, NTSC, WST System B */
|
||||
{V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
|
||||
{V4L2_SLICED_TELETEXT_NTSC_B, 10, 21, 1},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
|
||||
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
||||
},
|
||||
[4] = {0x090, /* Tetetext, NTSC NABTS System C */
|
||||
{V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
|
||||
{V4L2_SLICED_TELETEXT_NTSC_C, 10, 21, 1},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
|
||||
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
|
||||
},
|
||||
[5] = {0x0b0, /* Teletext, NTSC-J, NABTS System D */
|
||||
{V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
|
||||
{V4L2_SLICED_TELETEXT_NTSC_D, 10, 21, 1},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
|
||||
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
||||
},
|
||||
[6] = {0x0d0, /* Closed Caption, PAL/SECAM */
|
||||
{V4L2_SLICED_CAPTION_625,22,22,1},
|
||||
{V4L2_SLICED_CAPTION_625, 22, 22, 1},
|
||||
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
|
||||
0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
|
||||
},
|
||||
#endif
|
||||
[7] = {0x0f0, /* Closed Caption, NTSC */
|
||||
{V4L2_SLICED_CAPTION_525,21,21,1},
|
||||
{V4L2_SLICED_CAPTION_525, 21, 21, 1},
|
||||
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
|
||||
0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
|
||||
},
|
||||
[8] = {0x110, /* Wide Screen Signal, PAL/SECAM */
|
||||
{V4L2_SLICED_WSS_625,23,23,1},
|
||||
{V4L2_SLICED_WSS_625, 23, 23, 1},
|
||||
{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
|
||||
0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
|
||||
},
|
||||
#if 0
|
||||
[9] = {0x130, /* Wide Screen Signal, NTSC C */
|
||||
{V4L2_SLICED_WSS_525,20,20,1},
|
||||
{V4L2_SLICED_WSS_525, 20, 20, 1},
|
||||
{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
|
||||
0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
|
||||
},
|
||||
[10] = {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
|
||||
{V4l2_SLICED_VITC_625,6,22,0},
|
||||
{V4l2_SLICED_VITC_625, 6, 22, 0},
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
|
||||
0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
|
||||
},
|
||||
[11] = {0x170, /* Vertical Interval Timecode (VITC), NTSC */
|
||||
{V4l2_SLICED_VITC_525,10,20,0},
|
||||
{V4l2_SLICED_VITC_525, 10, 20, 0},
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
|
||||
0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
|
||||
},
|
||||
#endif
|
||||
[12] = {0x190, /* Video Program System (VPS), PAL */
|
||||
{V4L2_SLICED_VPS,16,16,0},
|
||||
{V4L2_SLICED_VPS, 16, 16, 0},
|
||||
{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
|
||||
0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
|
||||
},
|
||||
@@ -623,7 +625,7 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
|
||||
int line, i;
|
||||
|
||||
dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n");
|
||||
memset(cap, 0, sizeof *cap);
|
||||
memset(cap, 0, sizeof(*cap));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
|
||||
const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
|
||||
@@ -655,7 +657,7 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
|
||||
* MSB = field2
|
||||
*/
|
||||
static int tvp5150_set_vbi(struct v4l2_subdev *sd,
|
||||
unsigned int type,u8 flags, int line,
|
||||
unsigned int type, u8 flags, int line,
|
||||
const int fields)
|
||||
{
|
||||
struct tvp5150 *decoder = to_tvp5150(sd);
|
||||
@@ -1101,11 +1103,14 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd,
|
||||
|
||||
static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
|
||||
{
|
||||
/* this is for capturing 36 raw vbi lines
|
||||
if there's a way to cut off the beginning 2 vbi lines
|
||||
with the tvp5150 then the vbi line count could be lowered
|
||||
to 17 lines/field again, although I couldn't find a register
|
||||
which could do that cropping */
|
||||
/*
|
||||
* this is for capturing 36 raw vbi lines
|
||||
* if there's a way to cut off the beginning 2 vbi lines
|
||||
* with the tvp5150 then the vbi line count could be lowered
|
||||
* to 17 lines/field again, although I couldn't find a register
|
||||
* which could do that cropping
|
||||
*/
|
||||
|
||||
if (fmt->sample_format == V4L2_PIX_FMT_GREY)
|
||||
tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70);
|
||||
if (fmt->count[0] == 18 && fmt->count[1] == 18) {
|
||||
|
564
drivers/media/i2c/video-i2c.c
Normal file
564
drivers/media/i2c/video-i2c.c
Normal file
@@ -0,0 +1,564 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* video-i2c.c - Support for I2C transport video devices
|
||||
*
|
||||
* Copyright (C) 2018 Matt Ranostay <matt.ranostay@konsulko.com>
|
||||
*
|
||||
* Supported:
|
||||
* - Panasonic AMG88xx Grid-Eye Sensors
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fh.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include <media/videobuf2-vmalloc.h>
|
||||
|
||||
#define VIDEO_I2C_DRIVER "video-i2c"
|
||||
|
||||
struct video_i2c_chip;
|
||||
|
||||
struct video_i2c_buffer {
|
||||
struct vb2_v4l2_buffer vb;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct video_i2c_data {
|
||||
struct i2c_client *client;
|
||||
const struct video_i2c_chip *chip;
|
||||
struct mutex lock;
|
||||
spinlock_t slock;
|
||||
unsigned int sequence;
|
||||
struct mutex queue_lock;
|
||||
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct video_device vdev;
|
||||
struct vb2_queue vb_vidq;
|
||||
|
||||
struct task_struct *kthread_vid_cap;
|
||||
struct list_head vid_cap_active;
|
||||
};
|
||||
|
||||
static const struct v4l2_fmtdesc amg88xx_format = {
|
||||
.pixelformat = V4L2_PIX_FMT_Y12,
|
||||
};
|
||||
|
||||
static const struct v4l2_frmsize_discrete amg88xx_size = {
|
||||
.width = 8,
|
||||
.height = 8,
|
||||
};
|
||||
|
||||
struct video_i2c_chip {
|
||||
/* video dimensions */
|
||||
const struct v4l2_fmtdesc *format;
|
||||
const struct v4l2_frmsize_discrete *size;
|
||||
|
||||
/* max frames per second */
|
||||
unsigned int max_fps;
|
||||
|
||||
/* pixel buffer size */
|
||||
unsigned int buffer_size;
|
||||
|
||||
/* pixel size in bits */
|
||||
unsigned int bpp;
|
||||
|
||||
/* xfer function */
|
||||
int (*xfer)(struct video_i2c_data *data, char *buf);
|
||||
};
|
||||
|
||||
static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
|
||||
{
|
||||
struct i2c_client *client = data->client;
|
||||
struct i2c_msg msg[2];
|
||||
u8 reg = 0x80;
|
||||
int ret;
|
||||
|
||||
msg[0].addr = client->addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 1;
|
||||
msg[0].buf = (char *)®
|
||||
|
||||
msg[1].addr = client->addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
msg[1].len = data->chip->buffer_size;
|
||||
msg[1].buf = (char *)buf;
|
||||
|
||||
ret = i2c_transfer(client->adapter, msg, 2);
|
||||
|
||||
return (ret == 2) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
#define AMG88XX 0
|
||||
|
||||
static const struct video_i2c_chip video_i2c_chip[] = {
|
||||
[AMG88XX] = {
|
||||
.size = &amg88xx_size,
|
||||
.format = &amg88xx_format,
|
||||
.max_fps = 10,
|
||||
.buffer_size = 128,
|
||||
.bpp = 16,
|
||||
.xfer = &amg88xx_xfer,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct v4l2_file_operations video_i2c_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = v4l2_fh_open,
|
||||
.release = vb2_fop_release,
|
||||
.poll = vb2_fop_poll,
|
||||
.read = vb2_fop_read,
|
||||
.mmap = vb2_fop_mmap,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
};
|
||||
|
||||
static int queue_setup(struct vb2_queue *vq,
|
||||
unsigned int *nbuffers, unsigned int *nplanes,
|
||||
unsigned int sizes[], struct device *alloc_devs[])
|
||||
{
|
||||
struct video_i2c_data *data = vb2_get_drv_priv(vq);
|
||||
unsigned int size = data->chip->buffer_size;
|
||||
|
||||
if (vq->num_buffers + *nbuffers < 2)
|
||||
*nbuffers = 2;
|
||||
|
||||
if (*nplanes)
|
||||
return sizes[0] < size ? -EINVAL : 0;
|
||||
|
||||
*nplanes = 1;
|
||||
sizes[0] = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buffer_prepare(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct video_i2c_data *data = vb2_get_drv_priv(vb->vb2_queue);
|
||||
unsigned int size = data->chip->buffer_size;
|
||||
|
||||
if (vb2_plane_size(vb, 0) < size)
|
||||
return -EINVAL;
|
||||
|
||||
vbuf->field = V4L2_FIELD_NONE;
|
||||
vb2_set_plane_payload(vb, 0, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void buffer_queue(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct video_i2c_data *data = vb2_get_drv_priv(vb->vb2_queue);
|
||||
struct video_i2c_buffer *buf =
|
||||
container_of(vbuf, struct video_i2c_buffer, vb);
|
||||
|
||||
spin_lock(&data->slock);
|
||||
list_add_tail(&buf->list, &data->vid_cap_active);
|
||||
spin_unlock(&data->slock);
|
||||
}
|
||||
|
||||
static int video_i2c_thread_vid_cap(void *priv)
|
||||
{
|
||||
struct video_i2c_data *data = priv;
|
||||
unsigned int delay = msecs_to_jiffies(1000 / data->chip->max_fps);
|
||||
|
||||
set_freezable();
|
||||
|
||||
do {
|
||||
unsigned long start_jiffies = jiffies;
|
||||
struct video_i2c_buffer *vid_cap_buf = NULL;
|
||||
int schedule_delay;
|
||||
|
||||
try_to_freeze();
|
||||
|
||||
spin_lock(&data->slock);
|
||||
|
||||
if (!list_empty(&data->vid_cap_active)) {
|
||||
vid_cap_buf = list_last_entry(&data->vid_cap_active,
|
||||
struct video_i2c_buffer, list);
|
||||
list_del(&vid_cap_buf->list);
|
||||
}
|
||||
|
||||
spin_unlock(&data->slock);
|
||||
|
||||
if (vid_cap_buf) {
|
||||
struct vb2_buffer *vb2_buf = &vid_cap_buf->vb.vb2_buf;
|
||||
void *vbuf = vb2_plane_vaddr(vb2_buf, 0);
|
||||
int ret;
|
||||
|
||||
ret = data->chip->xfer(data, vbuf);
|
||||
vb2_buf->timestamp = ktime_get_ns();
|
||||
vid_cap_buf->vb.sequence = data->sequence++;
|
||||
vb2_buffer_done(vb2_buf, ret ?
|
||||
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
|
||||
}
|
||||
|
||||
schedule_delay = delay - (jiffies - start_jiffies);
|
||||
|
||||
if (time_after(jiffies, start_jiffies + delay))
|
||||
schedule_delay = delay;
|
||||
|
||||
schedule_timeout_interruptible(schedule_delay);
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void video_i2c_del_list(struct vb2_queue *vq, enum vb2_buffer_state state)
|
||||
{
|
||||
struct video_i2c_data *data = vb2_get_drv_priv(vq);
|
||||
struct video_i2c_buffer *buf, *tmp;
|
||||
|
||||
spin_lock(&data->slock);
|
||||
|
||||
list_for_each_entry_safe(buf, tmp, &data->vid_cap_active, list) {
|
||||
list_del(&buf->list);
|
||||
vb2_buffer_done(&buf->vb.vb2_buf, state);
|
||||
}
|
||||
|
||||
spin_unlock(&data->slock);
|
||||
}
|
||||
|
||||
static int start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
{
|
||||
struct video_i2c_data *data = vb2_get_drv_priv(vq);
|
||||
|
||||
if (data->kthread_vid_cap)
|
||||
return 0;
|
||||
|
||||
data->sequence = 0;
|
||||
data->kthread_vid_cap = kthread_run(video_i2c_thread_vid_cap, data,
|
||||
"%s-vid-cap", data->v4l2_dev.name);
|
||||
if (!IS_ERR(data->kthread_vid_cap))
|
||||
return 0;
|
||||
|
||||
video_i2c_del_list(vq, VB2_BUF_STATE_QUEUED);
|
||||
|
||||
return PTR_ERR(data->kthread_vid_cap);
|
||||
}
|
||||
|
||||
static void stop_streaming(struct vb2_queue *vq)
|
||||
{
|
||||
struct video_i2c_data *data = vb2_get_drv_priv(vq);
|
||||
|
||||
if (data->kthread_vid_cap == NULL)
|
||||
return;
|
||||
|
||||
kthread_stop(data->kthread_vid_cap);
|
||||
data->kthread_vid_cap = NULL;
|
||||
|
||||
video_i2c_del_list(vq, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
|
||||
static struct vb2_ops video_i2c_video_qops = {
|
||||
.queue_setup = queue_setup,
|
||||
.buf_prepare = buffer_prepare,
|
||||
.buf_queue = buffer_queue,
|
||||
.start_streaming = start_streaming,
|
||||
.stop_streaming = stop_streaming,
|
||||
.wait_prepare = vb2_ops_wait_prepare,
|
||||
.wait_finish = vb2_ops_wait_finish,
|
||||
};
|
||||
|
||||
static int video_i2c_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *vcap)
|
||||
{
|
||||
struct video_i2c_data *data = video_drvdata(file);
|
||||
struct i2c_client *client = data->client;
|
||||
|
||||
strlcpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver));
|
||||
strlcpy(vcap->card, data->vdev.name, sizeof(vcap->card));
|
||||
|
||||
sprintf(vcap->bus_info, "I2C:%d-%d", client->adapter->nr, client->addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_g_input(struct file *file, void *fh, unsigned int *inp)
|
||||
{
|
||||
*inp = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_s_input(struct file *file, void *fh, unsigned int inp)
|
||||
{
|
||||
return (inp > 0) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int video_i2c_enum_input(struct file *file, void *fh,
|
||||
struct v4l2_input *vin)
|
||||
{
|
||||
if (vin->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
strlcpy(vin->name, "Camera", sizeof(vin->name));
|
||||
|
||||
vin->type = V4L2_INPUT_TYPE_CAMERA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_enum_fmt_vid_cap(struct file *file, void *fh,
|
||||
struct v4l2_fmtdesc *fmt)
|
||||
{
|
||||
struct video_i2c_data *data = video_drvdata(file);
|
||||
enum v4l2_buf_type type = fmt->type;
|
||||
|
||||
if (fmt->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
*fmt = *data->chip->format;
|
||||
fmt->type = type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_enum_framesizes(struct file *file, void *fh,
|
||||
struct v4l2_frmsizeenum *fsize)
|
||||
{
|
||||
const struct video_i2c_data *data = video_drvdata(file);
|
||||
const struct v4l2_frmsize_discrete *size = data->chip->size;
|
||||
|
||||
/* currently only one frame size is allowed */
|
||||
if (fsize->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (fsize->pixel_format != data->chip->format->pixelformat)
|
||||
return -EINVAL;
|
||||
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
||||
fsize->discrete.width = size->width;
|
||||
fsize->discrete.height = size->height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_enum_frameintervals(struct file *file, void *priv,
|
||||
struct v4l2_frmivalenum *fe)
|
||||
{
|
||||
const struct video_i2c_data *data = video_drvdata(file);
|
||||
const struct v4l2_frmsize_discrete *size = data->chip->size;
|
||||
|
||||
if (fe->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (fe->width != size->width || fe->height != size->height)
|
||||
return -EINVAL;
|
||||
|
||||
fe->type = V4L2_FRMIVAL_TYPE_DISCRETE;
|
||||
fe->discrete.numerator = 1;
|
||||
fe->discrete.denominator = data->chip->max_fps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_try_fmt_vid_cap(struct file *file, void *fh,
|
||||
struct v4l2_format *fmt)
|
||||
{
|
||||
const struct video_i2c_data *data = video_drvdata(file);
|
||||
const struct v4l2_frmsize_discrete *size = data->chip->size;
|
||||
struct v4l2_pix_format *pix = &fmt->fmt.pix;
|
||||
unsigned int bpp = data->chip->bpp / 8;
|
||||
|
||||
pix->width = size->width;
|
||||
pix->height = size->height;
|
||||
pix->pixelformat = data->chip->format->pixelformat;
|
||||
pix->field = V4L2_FIELD_NONE;
|
||||
pix->bytesperline = pix->width * bpp;
|
||||
pix->sizeimage = pix->bytesperline * pix->height;
|
||||
pix->colorspace = V4L2_COLORSPACE_RAW;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int video_i2c_s_fmt_vid_cap(struct file *file, void *fh,
|
||||
struct v4l2_format *fmt)
|
||||
{
|
||||
struct video_i2c_data *data = video_drvdata(file);
|
||||
|
||||
if (vb2_is_busy(&data->vb_vidq))
|
||||
return -EBUSY;
|
||||
|
||||
return video_i2c_try_fmt_vid_cap(file, fh, fmt);
|
||||
}
|
||||
|
||||
static int video_i2c_g_parm(struct file *filp, void *priv,
|
||||
struct v4l2_streamparm *parm)
|
||||
{
|
||||
struct video_i2c_data *data = video_drvdata(filp);
|
||||
|
||||
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
|
||||
parm->parm.capture.readbuffers = 1;
|
||||
parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
|
||||
parm->parm.capture.timeperframe.numerator = 1;
|
||||
parm->parm.capture.timeperframe.denominator = data->chip->max_fps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_ioctl_ops video_i2c_ioctl_ops = {
|
||||
.vidioc_querycap = video_i2c_querycap,
|
||||
.vidioc_g_input = video_i2c_g_input,
|
||||
.vidioc_s_input = video_i2c_s_input,
|
||||
.vidioc_enum_input = video_i2c_enum_input,
|
||||
.vidioc_enum_fmt_vid_cap = video_i2c_enum_fmt_vid_cap,
|
||||
.vidioc_enum_framesizes = video_i2c_enum_framesizes,
|
||||
.vidioc_enum_frameintervals = video_i2c_enum_frameintervals,
|
||||
.vidioc_g_fmt_vid_cap = video_i2c_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = video_i2c_s_fmt_vid_cap,
|
||||
.vidioc_g_parm = video_i2c_g_parm,
|
||||
.vidioc_s_parm = video_i2c_g_parm,
|
||||
.vidioc_try_fmt_vid_cap = video_i2c_try_fmt_vid_cap,
|
||||
.vidioc_reqbufs = vb2_ioctl_reqbufs,
|
||||
.vidioc_create_bufs = vb2_ioctl_create_bufs,
|
||||
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
|
||||
.vidioc_querybuf = vb2_ioctl_querybuf,
|
||||
.vidioc_qbuf = vb2_ioctl_qbuf,
|
||||
.vidioc_dqbuf = vb2_ioctl_dqbuf,
|
||||
.vidioc_streamon = vb2_ioctl_streamon,
|
||||
.vidioc_streamoff = vb2_ioctl_streamoff,
|
||||
};
|
||||
|
||||
static void video_i2c_release(struct video_device *vdev)
|
||||
{
|
||||
kfree(video_get_drvdata(vdev));
|
||||
}
|
||||
|
||||
static int video_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct video_i2c_data *data;
|
||||
struct v4l2_device *v4l2_dev;
|
||||
struct vb2_queue *queue;
|
||||
int ret = -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (dev_fwnode(&client->dev))
|
||||
data->chip = device_get_match_data(&client->dev);
|
||||
else if (id)
|
||||
data->chip = &video_i2c_chip[id->driver_data];
|
||||
else
|
||||
goto error_free_device;
|
||||
|
||||
data->client = client;
|
||||
v4l2_dev = &data->v4l2_dev;
|
||||
strlcpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name));
|
||||
|
||||
ret = v4l2_device_register(&client->dev, v4l2_dev);
|
||||
if (ret < 0)
|
||||
goto error_free_device;
|
||||
|
||||
mutex_init(&data->lock);
|
||||
mutex_init(&data->queue_lock);
|
||||
|
||||
queue = &data->vb_vidq;
|
||||
queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
queue->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR | VB2_READ;
|
||||
queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
|
||||
queue->drv_priv = data;
|
||||
queue->buf_struct_size = sizeof(struct video_i2c_buffer);
|
||||
queue->min_buffers_needed = 1;
|
||||
queue->ops = &video_i2c_video_qops;
|
||||
queue->mem_ops = &vb2_vmalloc_memops;
|
||||
|
||||
ret = vb2_queue_init(queue);
|
||||
if (ret < 0)
|
||||
goto error_unregister_device;
|
||||
|
||||
data->vdev.queue = queue;
|
||||
data->vdev.queue->lock = &data->queue_lock;
|
||||
|
||||
snprintf(data->vdev.name, sizeof(data->vdev.name),
|
||||
"I2C %d-%d Transport Video",
|
||||
client->adapter->nr, client->addr);
|
||||
|
||||
data->vdev.v4l2_dev = v4l2_dev;
|
||||
data->vdev.fops = &video_i2c_fops;
|
||||
data->vdev.lock = &data->lock;
|
||||
data->vdev.ioctl_ops = &video_i2c_ioctl_ops;
|
||||
data->vdev.release = video_i2c_release;
|
||||
data->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE |
|
||||
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
|
||||
|
||||
spin_lock_init(&data->slock);
|
||||
INIT_LIST_HEAD(&data->vid_cap_active);
|
||||
|
||||
video_set_drvdata(&data->vdev, data);
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
ret = video_register_device(&data->vdev, VFL_TYPE_GRABBER, -1);
|
||||
if (ret < 0)
|
||||
goto error_unregister_device;
|
||||
|
||||
return 0;
|
||||
|
||||
error_unregister_device:
|
||||
v4l2_device_unregister(v4l2_dev);
|
||||
mutex_destroy(&data->lock);
|
||||
mutex_destroy(&data->queue_lock);
|
||||
|
||||
error_free_device:
|
||||
kfree(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int video_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct video_i2c_data *data = i2c_get_clientdata(client);
|
||||
|
||||
video_unregister_device(&data->vdev);
|
||||
v4l2_device_unregister(&data->v4l2_dev);
|
||||
|
||||
mutex_destroy(&data->lock);
|
||||
mutex_destroy(&data->queue_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id video_i2c_id_table[] = {
|
||||
{ "amg88xx", AMG88XX },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, video_i2c_id_table);
|
||||
|
||||
static const struct of_device_id video_i2c_of_match[] = {
|
||||
{ .compatible = "panasonic,amg88xx", .data = &video_i2c_chip[AMG88XX] },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, video_i2c_of_match);
|
||||
|
||||
static struct i2c_driver video_i2c_driver = {
|
||||
.driver = {
|
||||
.name = VIDEO_I2C_DRIVER,
|
||||
.of_match_table = video_i2c_of_match,
|
||||
},
|
||||
.probe = video_i2c_probe,
|
||||
.remove = video_i2c_remove,
|
||||
.id_table = video_i2c_id_table,
|
||||
};
|
||||
|
||||
module_i2c_driver(video_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
|
||||
MODULE_DESCRIPTION("I2C transport video support");
|
||||
MODULE_LICENSE("GPL v2");
|
Reference in New Issue
Block a user