提交 e23739b4 编写于 作者: L Linus Torvalds

Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:
 "For some media fixes:
   - dvb_usb_v2: some fixes at the core
   - Some fixes on some embedded drivers: soc_camera, adv7604, omap3isp,
     exynos/s5p
   - Several Exynos4/5 camera fixes
   - a fix at stv0900 driver
   - a few USB ID additions to detect more variants of rtl28xxu-based
     sticks"

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (25 commits)
  [media] rtl28xxu: 0ccd:00d7 TerraTec Cinergy T Stick+
  [media] rtl28xxu: 1d19:1102 Dexatek DK mini DVB-T Dongle
  [media] mt9v022: fix the V4L2_CID_EXPOSURE control
  [media] mx2_camera: fix missing unlock on error in mx2_start_streaming()
  [media] media: omap1_camera: fix const cropping related warnings
  [media] media: mx1_camera: use the default .set_crop() implementation
  [media] media: mx2_camera: fix const cropping related warnings
  [media] media: mx3_camera: fix const cropping related warnings
  [media] media: pxa_camera: fix const cropping related warnings
  [media] media: sh_mobile_ceu_camera: fix const cropping related warnings
  [media] media: sh_vou: fix const cropping related warnings
  [media] adv7604: restart STDI once if format is not found
  [media] adv7604: use presets where possible
  [media] adv7604: Replace prim_mode by mode
  [media] adv7604: cleanup references
  [media] dvb_usb_v2: switch interruptible mutex to normal
  [media] dvb_usb_v2: fix pid_filter callback error logging
  [media] exynos-gsc: change driver compatible string
  [media] omap3isp: Fix warning caused by bad subdev events operations prototypes
  [media] omap3isp: video: Fix warning caused by bad vidioc_s_crop prototype
  ...
...@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 ...@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32
{ {
u32 m_div, clk_sel; u32 m_div, clk_sel;
dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
intp->quartz);
if (intp == NULL) if (intp == NULL)
return STV0900_INVALID_HANDLE; return STV0900_INVALID_HANDLE;
if (intp->errs) if (intp->errs)
return STV0900_I2C_ERROR; return STV0900_I2C_ERROR;
dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
intp->quartz);
clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6); clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
m_div = ((clk_sel * mclk) / intp->quartz) - 1; m_div = ((clk_sel * mclk) / intp->quartz) - 1;
stv0900_write_bits(intp, F0900_M_DIV, m_div); stv0900_write_bits(intp, F0900_M_DIV, m_div);
......
...@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL"); ...@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL");
/* ADV7604 system clock frequency */ /* ADV7604 system clock frequency */
#define ADV7604_fsc (28636360) #define ADV7604_fsc (28636360)
#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \ #define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)
(state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
/* /*
********************************************************************** **********************************************************************
...@@ -68,7 +67,7 @@ struct adv7604_state { ...@@ -68,7 +67,7 @@ struct adv7604_state {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct media_pad pad; struct media_pad pad;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
enum adv7604_prim_mode prim_mode; enum adv7604_mode mode;
struct v4l2_dv_timings timings; struct v4l2_dv_timings timings;
u8 edid[256]; u8 edid[256];
unsigned edid_blocks; unsigned edid_blocks;
...@@ -77,6 +76,7 @@ struct adv7604_state { ...@@ -77,6 +76,7 @@ struct adv7604_state {
struct workqueue_struct *work_queues; struct workqueue_struct *work_queues;
struct delayed_work delayed_work_enable_hotplug; struct delayed_work delayed_work_enable_hotplug;
bool connector_hdmi; bool connector_hdmi;
bool restart_stdi_once;
/* i2c clients */ /* i2c clients */
struct i2c_client *i2c_avlink; struct i2c_client *i2c_avlink;
...@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = { ...@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
V4L2_DV_BT_CEA_720X576P50, V4L2_DV_BT_CEA_720X576P50,
V4L2_DV_BT_CEA_1280X720P24, V4L2_DV_BT_CEA_1280X720P24,
V4L2_DV_BT_CEA_1280X720P25, V4L2_DV_BT_CEA_1280X720P25,
V4L2_DV_BT_CEA_1280X720P30,
V4L2_DV_BT_CEA_1280X720P50, V4L2_DV_BT_CEA_1280X720P50,
V4L2_DV_BT_CEA_1280X720P60, V4L2_DV_BT_CEA_1280X720P60,
V4L2_DV_BT_CEA_1920X1080P24, V4L2_DV_BT_CEA_1920X1080P24,
...@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = { ...@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
V4L2_DV_BT_CEA_1920X1080P50, V4L2_DV_BT_CEA_1920X1080P50,
V4L2_DV_BT_CEA_1920X1080P60, V4L2_DV_BT_CEA_1920X1080P60,
/* sorted by DMT ID */
V4L2_DV_BT_DMT_640X350P85, V4L2_DV_BT_DMT_640X350P85,
V4L2_DV_BT_DMT_640X400P85, V4L2_DV_BT_DMT_640X400P85,
V4L2_DV_BT_DMT_720X400P85, V4L2_DV_BT_DMT_720X400P85,
...@@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = { ...@@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
{ }, { },
}; };
struct adv7604_video_standards {
struct v4l2_dv_timings timings;
u8 vid_std;
u8 v_freq;
};
/* sorted by number of lines */
static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
/* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
{ V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
{ V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
{ V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
{ V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
{ V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
{ V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
{ V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
{ V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
/* TODO add 1920x1080P60_RB (CVT timing) */
{ },
};
/* sorted by number of lines */
static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
{ V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
{ V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
{ V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
{ V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
{ V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
{ V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
{ V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
{ V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
{ V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
{ V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
{ V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
{ V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
{ V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
{ V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
{ V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
{ V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
/* TODO add 1600X1200P60_RB (not a DMT timing) */
{ V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
{ V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
{ },
};
/* sorted by number of lines */
static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
{ V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
{ V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
{ V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
{ V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
{ V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
{ V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
{ V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
{ V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
{ V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
{ },
};
/* sorted by number of lines */
static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
{ V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
{ V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
{ V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
{ V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
{ V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
{ V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
{ V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
{ V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
{ V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
{ V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
{ V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
{ V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
{ },
};
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static inline struct adv7604_state *to_state(struct v4l2_subdev *sd) static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
...@@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) ...@@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
((io_read(sd, 0x6f) & 0x10) >> 4)); ((io_read(sd, 0x6f) & 0x10) >> 4));
} }
static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings) static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
u8 prim_mode,
const struct adv7604_video_standards *predef_vid_timings,
const struct v4l2_dv_timings *timings)
{
struct adv7604_state *state = to_state(sd);
int i;
for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings,
DIGITAL_INPUT ? 250000 : 1000000))
continue;
io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
prim_mode); /* v_freq and prim mode */
return 0;
}
return -1;
}
static int configure_predefined_video_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{ {
struct adv7604_state *state = to_state(sd);
int err;
v4l2_dbg(1, debug, sd, "%s", __func__);
/* reset to default values */
io_write(sd, 0x16, 0x43);
io_write(sd, 0x17, 0x5a);
/* disable embedded syncs for auto graphics mode */
cp_write_and_or(sd, 0x81, 0xef, 0x00);
cp_write(sd, 0x8f, 0x00);
cp_write(sd, 0x90, 0x00);
cp_write(sd, 0xa2, 0x00);
cp_write(sd, 0xa3, 0x00);
cp_write(sd, 0xa4, 0x00);
cp_write(sd, 0xa5, 0x00);
cp_write(sd, 0xa6, 0x00);
cp_write(sd, 0xa7, 0x00);
cp_write(sd, 0xab, 0x00);
cp_write(sd, 0xac, 0x00);
switch (state->mode) {
case ADV7604_MODE_COMP:
case ADV7604_MODE_GR:
err = find_and_set_predefined_video_timings(sd,
0x01, adv7604_prim_mode_comp, timings);
if (err)
err = find_and_set_predefined_video_timings(sd,
0x02, adv7604_prim_mode_gr, timings);
break;
case ADV7604_MODE_HDMI:
err = find_and_set_predefined_video_timings(sd,
0x05, adv7604_prim_mode_hdmi_comp, timings);
if (err)
err = find_and_set_predefined_video_timings(sd,
0x06, adv7604_prim_mode_hdmi_gr, timings);
break;
default:
v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
__func__, state->mode);
err = -1;
break;
}
return err;
}
static void configure_custom_video_timings(struct v4l2_subdev *sd,
const struct v4l2_bt_timings *bt)
{
struct adv7604_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
u32 width = htotal(timings); u32 width = htotal(bt);
u32 height = vtotal(timings); u32 height = vtotal(bt);
u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ? u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0; u16 cp_start_eav = width - bt->hfrontporch;
u16 cp_start_vbi = height - bt->vfrontporch;
u16 cp_end_vbi = bt->vsync + bt->vbackporch;
u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0;
const u8 pll[2] = {
0xc0 | ((width >> 8) & 0x1f),
width & 0xff
};
v4l2_dbg(2, debug, sd, "%s\n", __func__); v4l2_dbg(2, debug, sd, "%s\n", __func__);
cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); /* CH1_FR_LL */ switch (state->mode) {
cp_write(sd, 0x90, ch1_fr_ll & 0xff); /* CH1_FR_LL */ case ADV7604_MODE_COMP:
cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */ case ADV7604_MODE_GR:
cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */ /* auto graphics */
/* TODO support interlaced */ io_write(sd, 0x00, 0x07); /* video std */
cp_write(sd, 0x91, 0x10); /* INTERLACED */ io_write(sd, 0x01, 0x02); /* prim mode */
/* enable embedded syncs for auto graphics mode */
/* Should only be set in auto-graphics mode [REF_02 p. 91-92] */ cp_write_and_or(sd, 0x81, 0xef, 0x10);
if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
const u8 pll[2] = {
(0xc0 | ((width >> 8) & 0x1f)),
(width & 0xff)
};
/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */ /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
/* IO-map reg. 0x16 and 0x17 should be written in sequence */ /* IO-map reg. 0x16 and 0x17 should be written in sequence */
if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) { if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n"); v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
return; break;
} }
/* active video - horizontal timing */ /* active video - horizontal timing */
cp_start_sav = timings->hsync + timings->hbackporch - 4;
cp_start_eav = width - timings->hfrontporch;
cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff); cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f)); cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
((cp_start_eav >> 8) & 0x0f));
cp_write(sd, 0xa4, cp_start_eav & 0xff); cp_write(sd, 0xa4, cp_start_eav & 0xff);
/* active video - vertical timing */ /* active video - vertical timing */
cp_start_vbi = height - timings->vfrontporch;
cp_end_vbi = timings->vsync + timings->vbackporch;
cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff); cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf)); cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
((cp_end_vbi >> 8) & 0xf));
cp_write(sd, 0xa7, cp_end_vbi & 0xff); cp_write(sd, 0xa7, cp_end_vbi & 0xff);
} else { break;
/* reset to default values */ case ADV7604_MODE_HDMI:
io_write(sd, 0x16, 0x43); /* set default prim_mode/vid_std for HDMI
io_write(sd, 0x17, 0x5a); accoring to [REF_03, c. 4.2] */
cp_write(sd, 0xa2, 0x00); io_write(sd, 0x00, 0x02); /* video std */
cp_write(sd, 0xa3, 0x00); io_write(sd, 0x01, 0x06); /* prim mode */
cp_write(sd, 0xa4, 0x00); break;
cp_write(sd, 0xa5, 0x00); default:
cp_write(sd, 0xa6, 0x00); v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
cp_write(sd, 0xa7, 0x00); __func__, state->mode);
break;
} }
}
cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
cp_write(sd, 0x90, ch1_fr_ll & 0xff);
cp_write(sd, 0xab, (height >> 4) & 0xff);
cp_write(sd, 0xac, (height & 0x0f) << 4);
}
static void set_rgb_quantization_range(struct v4l2_subdev *sd) static void set_rgb_quantization_range(struct v4l2_subdev *sd)
{ {
...@@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) ...@@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
switch (state->rgb_quantization_range) { switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO: case V4L2_DV_RGB_RANGE_AUTO:
/* automatic */ /* automatic */
if ((hdmi_read(sd, 0x05) & 0x80) || if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
(state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
(state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
/* receiving HDMI or analog signal */
io_write_and_or(sd, 0x02, 0x0f, 0xf0);
} else {
/* receiving DVI-D signal */ /* receiving DVI-D signal */
/* ADV7604 selects RGB limited range regardless of /* ADV7604 selects RGB limited range regardless of
...@@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) ...@@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
/* RGB full range (0-255) */ /* RGB full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x10); io_write_and_or(sd, 0x02, 0x0f, 0x10);
} }
} else {
/* receiving HDMI or analog signal, set automode */
io_write_and_or(sd, 0x02, 0x0f, 0xf0);
} }
break; break;
case V4L2_DV_RGB_RANGE_LIMITED: case V4L2_DV_RGB_RANGE_LIMITED:
...@@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd, ...@@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
state->aspect_ratio, timings)) state->aspect_ratio, timings))
return 0; return 0;
v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n", v4l2_dbg(2, debug, sd,
__func__, stdi->lcf, stdi->bl); "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n",
__func__, stdi->lcvs, stdi->lcf, stdi->bl,
stdi->hs_pol, stdi->vs_pol);
return -1; return -1;
} }
...@@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, ...@@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
adv7604_fill_optional_dv_timings_fields(sd, timings); adv7604_fill_optional_dv_timings_fields(sd, timings);
} else { } else {
/* find format /* find format
* Since LCVS values are inaccurate (REF_03, page 275-276), * Since LCVS values are inaccurate [REF_03, p. 275-276],
* stdi2dv_timings() is called with lcvs +-1 if the first attempt fails. * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
*/ */
if (!stdi2dv_timings(sd, &stdi, timings)) if (!stdi2dv_timings(sd, &stdi, timings))
...@@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, ...@@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
stdi.lcvs -= 2; stdi.lcvs -= 2;
v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs); v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
if (stdi2dv_timings(sd, &stdi, timings)) { if (stdi2dv_timings(sd, &stdi, timings)) {
/*
* The STDI block may measure wrong values, especially
* for lcvs and lcf. If the driver can not find any
* valid timing, the STDI block is restarted to measure
* the video timings again. The function will return an
* error, but the restart of STDI will generate a new
* STDI interrupt and the format detection process will
* restart.
*/
if (state->restart_stdi_once) {
v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
/* TODO restart STDI for Sync Channel 2 */
/* enter one-shot mode */
cp_write_and_or(sd, 0x86, 0xf9, 0x00);
/* trigger STDI restart */
cp_write_and_or(sd, 0x86, 0xf9, 0x04);
/* reset to continuous mode */
cp_write_and_or(sd, 0x86, 0xf9, 0x02);
state->restart_stdi_once = false;
return -ENOLINK;
}
v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
return -ERANGE; return -ERANGE;
} }
state->restart_stdi_once = true;
} }
found: found:
...@@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, ...@@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
{ {
struct adv7604_state *state = to_state(sd); struct adv7604_state *state = to_state(sd);
struct v4l2_bt_timings *bt; struct v4l2_bt_timings *bt;
int err;
if (!timings) if (!timings)
return -EINVAL; return -EINVAL;
...@@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, ...@@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
__func__, (u32)bt->pixelclock); __func__, (u32)bt->pixelclock);
return -ERANGE; return -ERANGE;
} }
adv7604_fill_optional_dv_timings_fields(sd, timings); adv7604_fill_optional_dv_timings_fields(sd, timings);
state->timings = *timings; state->timings = *timings;
/* freerun */ cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
configure_free_run(sd, bt);
/* Use prim_mode and vid_std when available */
err = configure_predefined_video_timings(sd, timings);
if (err) {
/* custom settings when the video format
does not have prim_mode/vid_std */
configure_custom_video_timings(sd, bt);
}
set_rgb_quantization_range(sd); set_rgb_quantization_range(sd);
...@@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd, ...@@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
return 0; return 0;
} }
static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode) static void enable_input(struct v4l2_subdev *sd)
{ {
switch (prim_mode) { struct adv7604_state *state = to_state(sd);
case ADV7604_PRIM_MODE_COMP:
case ADV7604_PRIM_MODE_RGB: switch (state->mode) {
case ADV7604_MODE_COMP:
case ADV7604_MODE_GR:
/* enable */ /* enable */
io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */
break; break;
case ADV7604_PRIM_MODE_HDMI_COMP: case ADV7604_MODE_HDMI:
case ADV7604_PRIM_MODE_HDMI_GR:
/* enable */ /* enable */
hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */ hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */ hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */
break; break;
default: default:
v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
__func__, prim_mode); __func__, state->mode);
break; break;
} }
} }
...@@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd) ...@@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd)
hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */ hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
} }
static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode) static void select_input(struct v4l2_subdev *sd)
{ {
switch (prim_mode) { struct adv7604_state *state = to_state(sd);
case ADV7604_PRIM_MODE_COMP:
case ADV7604_PRIM_MODE_RGB:
/* set mode and select free run resolution */
io_write(sd, 0x00, 0x07); /* video std */
io_write(sd, 0x01, 0x02); /* prim mode */
/* enable embedded syncs for auto graphics mode */
cp_write_and_or(sd, 0x81, 0xef, 0x10);
switch (state->mode) {
case ADV7604_MODE_COMP:
case ADV7604_MODE_GR:
/* reset ADI recommended settings for HDMI: */ /* reset ADI recommended settings for HDMI: */
/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */ hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
...@@ -1271,16 +1462,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod ...@@ -1271,16 +1462,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */ cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
break; break;
case ADV7604_PRIM_MODE_HDMI_COMP: case ADV7604_MODE_HDMI:
case ADV7604_PRIM_MODE_HDMI_GR:
/* set mode and select free run resolution */
/* video std */
io_write(sd, 0x00,
(prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
io_write(sd, 0x01, prim_mode); /* prim mode */
/* disable embedded syncs for auto graphics mode */
cp_write_and_or(sd, 0x81, 0xef, 0x00);
/* set ADI recommended settings for HDMI: */ /* set ADI recommended settings for HDMI: */
/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */ hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
...@@ -1309,7 +1491,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod ...@@ -1309,7 +1491,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
break; break;
default: default:
v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode); v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
__func__, state->mode);
break; break;
} }
} }
...@@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd, ...@@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input); v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
switch (input) { state->mode = input;
case 0:
/* TODO select HDMI_COMP or HDMI_GR */
state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
break;
case 1:
state->prim_mode = ADV7604_PRIM_MODE_RGB;
break;
case 2:
state->prim_mode = ADV7604_PRIM_MODE_COMP;
break;
default:
return -EINVAL;
}
disable_input(sd); disable_input(sd);
select_input(sd, state->prim_mode); select_input(sd);
enable_input(sd, state->prim_mode); enable_input(sd);
return 0; return 0;
} }
...@@ -1549,8 +1719,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd) ...@@ -1549,8 +1719,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true"); v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
v4l2_info(sd, "CP free run: %s\n", v4l2_info(sd, "CP free run: %s\n",
(!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off")); (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n", v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f); io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
(io_read(sd, 0x01) & 0x70) >> 4);
v4l2_info(sd, "-----Video Timings-----\n"); v4l2_info(sd, "-----Video Timings-----\n");
if (read_stdi(sd, &stdi)) if (read_stdi(sd, &stdi))
...@@ -1712,9 +1883,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd) ...@@ -1712,9 +1883,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */ cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */ cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold - cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold -
ADI recommended setting [REF_01 c. 2.3.3] */ ADI recommended setting [REF_01, c. 2.3.3] */
cp_write(sd, 0x45, 0x23); /* STDI ch. 2 - LCVS change threshold - cp_write(sd, 0x45, 0x23); /* STDI ch. 2 - LCVS change threshold -
ADI recommended setting [REF_01 c. 2.3.3] */ ADI recommended setting [REF_01, c. 2.3.3] */
cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
for digital formats */ for digital formats */
...@@ -1724,11 +1895,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd) ...@@ -1724,11 +1895,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
state->prim_mode = pdata->prim_mode;
select_input(sd, pdata->prim_mode);
enable_input(sd, pdata->prim_mode);
/* interrupts */ /* interrupts */
io_write(sd, 0x40, 0xc2); /* Configure INT1 */ io_write(sd, 0x40, 0xc2); /* Configure INT1 */
io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */ io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
...@@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client, ...@@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client,
v4l2_err(sd, "failed to create all i2c clients\n"); v4l2_err(sd, "failed to create all i2c clients\n");
goto err_i2c; goto err_i2c;
} }
state->restart_stdi_once = true;
/* work queues */ /* work queues */
state->work_queues = create_singlethread_workqueue(client->name); state->work_queues = create_singlethread_workqueue(client->name);
......
...@@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) ...@@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
if (ret & 1) /* Autoexposure */ if (ret & 1) /* Autoexposure */
ret = reg_write(client, mt9v022->reg->max_total_shutter_width, ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
rect.height + mt9v022->y_skip_top + 43); rect.height + mt9v022->y_skip_top + 43);
else /*
ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, * If autoexposure is off, there is no need to set
rect.height + mt9v022->y_skip_top + 43); * MT9V022_TOTAL_SHUTTER_WIDTH here. Autoexposure can be off
* only if the user has set exposure manually, using the
* V4L2_CID_EXPOSURE_AUTO with the value V4L2_EXPOSURE_MANUAL.
* In this case the register MT9V022_TOTAL_SHUTTER_WIDTH
* already contains the correct value.
*/
} }
/* Setup frame format: defaults apart from width and height */ /* Setup frame format: defaults apart from width and height */
if (!ret) if (!ret)
......
...@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = { ...@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = {
MODULE_DEVICE_TABLE(platform, gsc_driver_ids); MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
static const struct of_device_id exynos_gsc_match[] = { static const struct of_device_id exynos_gsc_match[] = {
{ .compatible = "samsung,exynos5250-gsc", {
.data = &gsc_v_100_drvdata, }, .compatible = "samsung,exynos5-gsc",
.data = &gsc_v_100_drvdata,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, exynos_gsc_match); MODULE_DEVICE_TABLE(of, exynos_gsc_match);
......
...@@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) ...@@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
} }
static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub) struct v4l2_event_subscription *sub)
{ {
if (sub->type != V4L2_EVENT_FRAME_SYNC) if (sub->type != V4L2_EVENT_FRAME_SYNC)
return -EINVAL; return -EINVAL;
...@@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, ...@@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
} }
static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub) struct v4l2_event_subscription *sub)
{ {
return v4l2_event_unsubscribe(fh, sub); return v4l2_event_unsubscribe(fh, sub);
} }
......
...@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat) ...@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh, struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub) struct v4l2_event_subscription *sub)
{ {
struct ispstat *stat = v4l2_get_subdevdata(subdev); struct ispstat *stat = v4l2_get_subdevdata(subdev);
...@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, ...@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh, struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub) struct v4l2_event_subscription *sub)
{ {
return v4l2_event_unsubscribe(fh, sub); return v4l2_event_unsubscribe(fh, sub);
} }
......
...@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name, ...@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name,
void omap3isp_stat_cleanup(struct ispstat *stat); void omap3isp_stat_cleanup(struct ispstat *stat);
int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh, struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub); struct v4l2_event_subscription *sub);
int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh, struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub); struct v4l2_event_subscription *sub);
int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable); int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
int omap3isp_stat_busy(struct ispstat *stat); int omap3isp_stat_busy(struct ispstat *stat);
......
...@@ -792,7 +792,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) ...@@ -792,7 +792,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
} }
static int static int
isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop) isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
{ {
struct isp_video *video = video_drvdata(file); struct isp_video *video = video_drvdata(file);
struct v4l2_subdev *subdev; struct v4l2_subdev *subdev;
......
...@@ -24,6 +24,7 @@ config VIDEO_S5P_FIMC ...@@ -24,6 +24,7 @@ config VIDEO_S5P_FIMC
config VIDEO_S5P_MIPI_CSIS config VIDEO_S5P_MIPI_CSIS
tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver" tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
depends on REGULATOR depends on REGULATOR
select S5P_SETUP_MIPIPHY
help help
This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
receiver (MIPI-CSIS) devices. receiver (MIPI-CSIS) devices.
......
...@@ -1736,7 +1736,9 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ...@@ -1736,7 +1736,9 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
q->mem_ops = &vb2_dma_contig_memops; q->mem_ops = &vb2_dma_contig_memops;
q->buf_struct_size = sizeof(struct fimc_vid_buffer); q->buf_struct_size = sizeof(struct fimc_vid_buffer);
vb2_queue_init(q); ret = vb2_queue_init(q);
if (ret)
goto err_ent;
vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
......
...@@ -1253,7 +1253,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) ...@@ -1253,7 +1253,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
q->buf_struct_size = sizeof(struct flite_buffer); q->buf_struct_size = sizeof(struct flite_buffer);
q->drv_priv = fimc; q->drv_priv = fimc;
vb2_queue_init(q); ret = vb2_queue_init(q);
if (ret < 0)
return ret;
fimc->vd_pad.flags = MEDIA_PAD_FL_SINK; fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0); ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
......
...@@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) ...@@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
static int fimc_register_callback(struct device *dev, void *p) static int fimc_register_callback(struct device *dev, void *p)
{ {
struct fimc_dev *fimc = dev_get_drvdata(dev); struct fimc_dev *fimc = dev_get_drvdata(dev);
struct v4l2_subdev *sd = &fimc->vid_cap.subdev; struct v4l2_subdev *sd;
struct fimc_md *fmd = p; struct fimc_md *fmd = p;
int ret = 0; int ret;
if (!fimc || !fimc->pdev)
return 0;
if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS) if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS)
return 0; return 0;
fimc->pipeline_ops = &fimc_pipeline_ops; sd = &fimc->vid_cap.subdev;
fmd->fimc[fimc->pdev->id] = fimc;
sd->grp_id = FIMC_GROUP_ID; sd->grp_id = FIMC_GROUP_ID;
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
if (ret) { if (ret) {
v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n", v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
fimc->id, ret); fimc->id, ret);
return ret;
} }
return ret; fimc->pipeline_ops = &fimc_pipeline_ops;
fmd->fimc[fimc->id] = fimc;
return 0;
} }
static int fimc_lite_register_callback(struct device *dev, void *p) static int fimc_lite_register_callback(struct device *dev, void *p)
{ {
struct fimc_lite *fimc = dev_get_drvdata(dev); struct fimc_lite *fimc = dev_get_drvdata(dev);
struct v4l2_subdev *sd = &fimc->subdev;
struct fimc_md *fmd = p; struct fimc_md *fmd = p;
int ret; int ret;
if (fimc == NULL) if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
return 0; return 0;
if (fimc->index >= FIMC_LITE_MAX_DEVS) fimc->subdev.grp_id = FLITE_GROUP_ID;
return 0;
fimc->pipeline_ops = &fimc_pipeline_ops; ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
fmd->fimc_lite[fimc->index] = fimc;
sd->grp_id = FLITE_GROUP_ID;
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
if (ret) { if (ret) {
v4l2_err(&fmd->v4l2_dev, v4l2_err(&fmd->v4l2_dev,
"Failed to register FIMC-LITE.%d (%d)\n", "Failed to register FIMC-LITE.%d (%d)\n",
fimc->index, ret); fimc->index, ret);
return ret;
} }
return ret;
fimc->pipeline_ops = &fimc_pipeline_ops;
fmd->fimc_lite[fimc->index] = fimc;
return 0;
} }
static int csis_register_callback(struct device *dev, void *p) static int csis_register_callback(struct device *dev, void *p)
...@@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p) ...@@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p)
v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name); v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
id = pdev->id < 0 ? 0 : pdev->id; id = pdev->id < 0 ? 0 : pdev->id;
fmd->csis[id].sd = sd;
sd->grp_id = CSIS_GROUP_ID; sd->grp_id = CSIS_GROUP_ID;
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
if (ret) if (!ret)
fmd->csis[id].sd = sd;
else
v4l2_err(&fmd->v4l2_dev, v4l2_err(&fmd->v4l2_dev,
"Failed to register CSIS subdevice: %d\n", ret); "Failed to register CSIS subdevice: %d\n", ret);
return ret; return ret;
......
...@@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) ...@@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
/* Assume a dull encoder, do all the work ourselves. */ /* Assume a dull encoder, do all the work ourselves. */
static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a) static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a)
{ {
struct v4l2_crop a_writable = *a;
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
struct sh_vou_device *vou_dev = video_get_drvdata(vdev); struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
struct v4l2_rect *rect = &a->c; struct v4l2_rect *rect = &a_writable.c;
struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
struct v4l2_pix_format *pix = &vou_dev->pix; struct v4l2_pix_format *pix = &vou_dev->pix;
struct sh_vou_geometry geo; struct sh_vou_geometry geo;
......
...@@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) ...@@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
pcdev->icd = NULL; pcdev->icd = NULL;
} }
static int mx1_camera_set_crop(struct soc_camera_device *icd,
struct v4l2_crop *a)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, video, s_crop, a);
}
static int mx1_camera_set_bus_param(struct soc_camera_device *icd) static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
{ {
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
...@@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = { ...@@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
.add = mx1_camera_add_device, .add = mx1_camera_add_device,
.remove = mx1_camera_remove_device, .remove = mx1_camera_remove_device,
.set_bus_param = mx1_camera_set_bus_param, .set_bus_param = mx1_camera_set_bus_param,
.set_crop = mx1_camera_set_crop,
.set_fmt = mx1_camera_set_fmt, .set_fmt = mx1_camera_set_fmt,
.try_fmt = mx1_camera_try_fmt, .try_fmt = mx1_camera_try_fmt,
.init_videobuf = mx1_camera_init_videobuf, .init_videobuf = mx1_camera_init_videobuf,
......
...@@ -864,8 +864,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) ...@@ -864,8 +864,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
bytesperline = soc_mbus_bytes_per_line(icd->user_width, bytesperline = soc_mbus_bytes_per_line(icd->user_width,
icd->current_fmt->host_fmt); icd->current_fmt->host_fmt);
if (bytesperline < 0) if (bytesperline < 0) {
spin_unlock_irqrestore(&pcdev->lock, flags);
return bytesperline; return bytesperline;
}
/* /*
* I didn't manage to properly enable/disable the prp * I didn't manage to properly enable/disable the prp
...@@ -878,8 +880,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) ...@@ -878,8 +880,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
pcdev->discard_size, &pcdev->discard_buffer_dma, pcdev->discard_size, &pcdev->discard_buffer_dma,
GFP_KERNEL); GFP_KERNEL);
if (!pcdev->discard_buffer) if (!pcdev->discard_buffer) {
spin_unlock_irqrestore(&pcdev->lock, flags);
return -ENOMEM; return -ENOMEM;
}
pcdev->buf_discard[0].discard = true; pcdev->buf_discard[0].discard = true;
list_add_tail(&pcdev->buf_discard[0].queue, list_add_tail(&pcdev->buf_discard[0].queue,
...@@ -1099,9 +1103,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) ...@@ -1099,9 +1103,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
} }
static int mx2_camera_set_crop(struct soc_camera_device *icd, static int mx2_camera_set_crop(struct soc_camera_device *icd,
struct v4l2_crop *a) const struct v4l2_crop *a)
{ {
struct v4l2_rect *rect = &a->c; struct v4l2_crop a_writable = *a;
struct v4l2_rect *rect = &a_writable.c;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct v4l2_mbus_framefmt mf; struct v4l2_mbus_framefmt mf;
int ret; int ret;
......
...@@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width) ...@@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width)
* default g_crop and cropcap from soc_camera.c * default g_crop and cropcap from soc_camera.c
*/ */
static int mx3_camera_set_crop(struct soc_camera_device *icd, static int mx3_camera_set_crop(struct soc_camera_device *icd,
struct v4l2_crop *a) const struct v4l2_crop *a)
{ {
struct v4l2_rect *rect = &a->c; struct v4l2_crop a_writable = *a;
struct v4l2_rect *rect = &a_writable.c;
struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv; struct mx3_camera_dev *mx3_cam = ici->priv;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
......
...@@ -1215,9 +1215,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev, ...@@ -1215,9 +1215,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
} }
static int omap1_cam_set_crop(struct soc_camera_device *icd, static int omap1_cam_set_crop(struct soc_camera_device *icd,
struct v4l2_crop *crop) const struct v4l2_crop *crop)
{ {
struct v4l2_rect *rect = &crop->c; const struct v4l2_rect *rect = &crop->c;
const struct soc_camera_format_xlate *xlate = icd->current_fmt; const struct soc_camera_format_xlate *xlate = icd->current_fmt;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent; struct device *dev = icd->parent;
......
...@@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height) ...@@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height)
} }
static int pxa_camera_set_crop(struct soc_camera_device *icd, static int pxa_camera_set_crop(struct soc_camera_device *icd,
struct v4l2_crop *a) const struct v4l2_crop *a)
{ {
struct v4l2_rect *rect = &a->c; const struct v4l2_rect *rect = &a->c;
struct device *dev = icd->parent; struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev); struct soc_camera_host *ici = to_soc_camera_host(dev);
struct pxa_camera_dev *pcdev = ici->priv; struct pxa_camera_dev *pcdev = ici->priv;
......
...@@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) ...@@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
} }
/* Check if any dimension of r1 is smaller than respective one of r2 */ /* Check if any dimension of r1 is smaller than respective one of r2 */
static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2) static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
{ {
return r1->width < r2->width || r1->height < r2->height; return r1->width < r2->width || r1->height < r2->height;
} }
/* Check if r1 fails to cover r2 */ /* Check if r1 fails to cover r2 */
static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
{ {
return r1->left > r2->left || r1->top > r2->top || return r1->left > r2->left || r1->top > r2->top ||
r1->left + r1->width < r2->left + r2->width || r1->left + r1->width < r2->left + r2->width ||
...@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam) ...@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam)
* 3. if (2) failed, try to request the maximum image * 3. if (2) failed, try to request the maximum image
*/ */
static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop,
const struct v4l2_crop *cam_crop) struct v4l2_crop *cam_crop)
{ {
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
...@@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd, ...@@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd,
static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
const struct v4l2_crop *a) const struct v4l2_crop *a)
{ {
struct v4l2_rect *rect = &a->c; struct v4l2_crop a_writable = *a;
const struct v4l2_rect *rect = &a_writable.c;
struct device *dev = icd->parent; struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev); struct soc_camera_host *ici = to_soc_camera_host(dev);
struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_dev *pcdev = ici->priv;
...@@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, ...@@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
* 1. - 2. Apply iterative camera S_CROP for new input window, read back * 1. - 2. Apply iterative camera S_CROP for new input window, read back
* actual camera rectangle. * actual camera rectangle.
*/ */
ret = client_s_crop(icd, a, &cam_crop); ret = client_s_crop(icd, &a_writable, &cam_crop);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, ...@@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
} }
static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd, static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
struct v4l2_crop *a) const struct v4l2_crop *a)
{ {
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
......
...@@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, ...@@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
/* activate the pid on the device pid filter */ /* activate the pid on the device pid filter */
if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
adap->pid_filtering && adap->pid_filtering && adap->props->pid_filter) {
adap->props->pid_filter)
ret = adap->props->pid_filter(adap, dvbdmxfeed->index, ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
dvbdmxfeed->pid, (count == 1) ? 1 : 0); dvbdmxfeed->pid, (count == 1) ? 1 : 0);
if (ret < 0) if (ret < 0)
dev_err(&d->udev->dev, "%s: pid_filter() " \ dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
"failed=%d\n", KBUILD_MODNAME, KBUILD_MODNAME, ret);
ret); }
/* start feeding if it is first pid */ /* start feeding if it is first pid */
if (adap->feed_count == 1 && count == 1) { if (adap->feed_count == 1 && count == 1) {
......
...@@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, ...@@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
return -EINVAL; return -EINVAL;
} }
ret = mutex_lock_interruptible(&d->usb_mutex); mutex_lock(&d->usb_mutex);
if (ret < 0)
return ret;
dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf); dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
......
...@@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = { ...@@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
&rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) }, &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3, { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
&rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
{ DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
&rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) },
{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
&rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) },
{ } { }
}; };
MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
......
...@@ -40,14 +40,6 @@ enum adv7604_op_ch_sel { ...@@ -40,14 +40,6 @@ enum adv7604_op_ch_sel {
ADV7604_OP_CH_SEL_RBG = 5, ADV7604_OP_CH_SEL_RBG = 5,
}; };
/* Primary mode (IO register 0x01, [3:0]) */
enum adv7604_prim_mode {
ADV7604_PRIM_MODE_COMP = 1,
ADV7604_PRIM_MODE_RGB = 2,
ADV7604_PRIM_MODE_HDMI_COMP = 5,
ADV7604_PRIM_MODE_HDMI_GR = 6,
};
/* Input Color Space (IO register 0x02, [7:4]) */ /* Input Color Space (IO register 0x02, [7:4]) */
enum adv7604_inp_color_space { enum adv7604_inp_color_space {
ADV7604_INP_COLOR_SPACE_LIM_RGB = 0, ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
...@@ -103,9 +95,6 @@ struct adv7604_platform_data { ...@@ -103,9 +95,6 @@ struct adv7604_platform_data {
/* Bus rotation and reordering */ /* Bus rotation and reordering */
enum adv7604_op_ch_sel op_ch_sel; enum adv7604_op_ch_sel op_ch_sel;
/* Primary mode */
enum adv7604_prim_mode prim_mode;
/* Select output format */ /* Select output format */
enum adv7604_op_format_sel op_format_sel; enum adv7604_op_format_sel op_format_sel;
...@@ -142,6 +131,16 @@ struct adv7604_platform_data { ...@@ -142,6 +131,16 @@ struct adv7604_platform_data {
u8 i2c_vdp; u8 i2c_vdp;
}; };
/*
* Mode of operation.
* This is used as the input argument of the s_routing video op.
*/
enum adv7604_mode {
ADV7604_MODE_COMP,
ADV7604_MODE_GR,
ADV7604_MODE_HDMI,
};
#define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE (V4L2_CID_DV_CLASS_BASE + 0x1000) #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE (V4L2_CID_DV_CLASS_BASE + 0x1000)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL (V4L2_CID_DV_CLASS_BASE + 0x1001) #define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL (V4L2_CID_DV_CLASS_BASE + 0x1001)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR (V4L2_CID_DV_CLASS_BASE + 0x1002) #define V4L2_CID_ADV_RX_FREE_RUN_COLOR (V4L2_CID_DV_CLASS_BASE + 0x1002)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册