Commit e23739b4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 2844a487 86163adb
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32
{
	u32 m_div, clk_sel;

	dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
			intp->quartz);

	if (intp == NULL)
		return STV0900_INVALID_HANDLE;

	if (intp->errs)
		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);
	m_div = ((clk_sel * mclk) / intp->quartz) - 1;
	stv0900_write_bits(intp, F0900_M_DIV, m_div);
+272 −105
Original line number Diff line number Diff line
@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL");
/* ADV7604 system clock frequency */
#define ADV7604_fsc (28636360)

#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
			(state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)

/*
 **********************************************************************
@@ -68,7 +67,7 @@ struct adv7604_state {
	struct v4l2_subdev sd;
	struct media_pad pad;
	struct v4l2_ctrl_handler hdl;
	enum adv7604_prim_mode prim_mode;
	enum adv7604_mode mode;
	struct v4l2_dv_timings timings;
	u8 edid[256];
	unsigned edid_blocks;
@@ -77,6 +76,7 @@ struct adv7604_state {
	struct workqueue_struct *work_queues;
	struct delayed_work delayed_work_enable_hotplug;
	bool connector_hdmi;
	bool restart_stdi_once;

	/* i2c clients */
	struct i2c_client *i2c_avlink;
@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
	V4L2_DV_BT_CEA_720X576P50,
	V4L2_DV_BT_CEA_1280X720P24,
	V4L2_DV_BT_CEA_1280X720P25,
	V4L2_DV_BT_CEA_1280X720P30,
	V4L2_DV_BT_CEA_1280X720P50,
	V4L2_DV_BT_CEA_1280X720P60,
	V4L2_DV_BT_CEA_1920X1080P24,
@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
	V4L2_DV_BT_CEA_1920X1080P50,
	V4L2_DV_BT_CEA_1920X1080P60,

	/* sorted by DMT ID */
	V4L2_DV_BT_DMT_640X350P85,
	V4L2_DV_BT_DMT_640X400P85,
	V4L2_DV_BT_DMT_720X400P85,
@@ -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)
@@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
				((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 i2c_client *client = v4l2_get_subdevdata(sd);
	u32 width = htotal(timings);
	u32 height = vtotal(timings);
	u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
		((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
	struct adv7604_state *state = to_state(sd);
	int i;

	v4l2_dbg(2, debug, sd, "%s\n", __func__);
	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;

	cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);	/* CH1_FR_LL */
	cp_write(sd, 0x90, ch1_fr_ll & 0xff);		/* CH1_FR_LL */
	cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
	cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
	/* TODO support interlaced */
	cp_write(sd, 0x91, 0x10);	/* INTERLACED */
	v4l2_dbg(1, debug, sd, "%s", __func__);

	/* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
	if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
		u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
	/* 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);
	u32 width = htotal(bt);
	u32 height = vtotal(bt);
	u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
	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)
		0xc0 | ((width >> 8) & 0x1f),
		width & 0xff
	};

	v4l2_dbg(2, debug, sd, "%s\n", __func__);

	switch (state->mode) {
	case ADV7604_MODE_COMP:
	case ADV7604_MODE_GR:
		/* auto graphics */
		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);

		/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
		/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
		/* IO-map reg. 0x16 and 0x17 should be written in sequence */
		if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
			v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
			return;
			break;
		}

		/* 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, 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);

		/* 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, 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);
	} else {
		/* reset to default values */
		io_write(sd, 0x16, 0x43);
		io_write(sd, 0x17, 0x5a);
		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);
	}
		break;
	case ADV7604_MODE_HDMI:
		/* set default prim_mode/vid_std for HDMI
		   accoring to [REF_03, c. 4.2] */
		io_write(sd, 0x00, 0x02); /* video std */
		io_write(sd, 0x01, 0x06); /* prim mode */
		break;
	default:
		v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
				__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)
{
@@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
	switch (state->rgb_quantization_range) {
	case V4L2_DV_RGB_RANGE_AUTO:
		/* automatic */
		if ((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 {
		if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
			/* receiving DVI-D signal */

			/* ADV7604 selects RGB limited range regardless of
@@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
				/* RGB full range (0-255) */
				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;
	case V4L2_DV_RGB_RANGE_LIMITED:
@@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
			state->aspect_ratio, timings))
		return 0;

	v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
			__func__, stdi->lcf, stdi->bl);
	v4l2_dbg(2, debug, sd,
		"%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;
}

@@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
		adv7604_fill_optional_dv_timings_fields(sd, timings);
	} else {
		/* 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.
		 */
		if (!stdi2dv_timings(sd, &stdi, timings))
@@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
		stdi.lcvs -= 2;
		v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
		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__);
			return -ERANGE;
		}
		state->restart_stdi_once = true;
	}
found:

@@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
{
	struct adv7604_state *state = to_state(sd);
	struct v4l2_bt_timings *bt;
	int err;

	if (!timings)
		return -EINVAL;
@@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
				__func__, (u32)bt->pixelclock);
		return -ERANGE;
	}

	adv7604_fill_optional_dv_timings_fields(sd, timings);

	state->timings = *timings;

	/* freerun */
	configure_free_run(sd, bt);
	cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);

	/* 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);

@@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
	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) {
	case ADV7604_PRIM_MODE_COMP:
	case ADV7604_PRIM_MODE_RGB:
	struct adv7604_state *state = to_state(sd);

	switch (state->mode) {
	case ADV7604_MODE_COMP:
	case ADV7604_MODE_GR:
		/* enable */
		io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
		break;
	case ADV7604_PRIM_MODE_HDMI_COMP:
	case ADV7604_PRIM_MODE_HDMI_GR:
	case ADV7604_MODE_HDMI:
		/* enable */
		hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
		hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
		io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
		break;
	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;
	}
}
@@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd)
	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) {
	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);
	struct adv7604_state *state = to_state(sd);

	switch (state->mode) {
	case ADV7604_MODE_COMP:
	case ADV7604_MODE_GR:
		/* reset ADI recommended settings for HDMI: */
		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
		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
		cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
		break;

	case ADV7604_PRIM_MODE_HDMI_COMP:
	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);

	case ADV7604_MODE_HDMI:
		/* set ADI recommended settings for HDMI: */
		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
		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

		break;
	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;
	}
}
@@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,

	v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);

	switch (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;
	}
	state->mode = input;

	disable_input(sd);

	select_input(sd, state->prim_mode);
	select_input(sd);

	enable_input(sd, state->prim_mode);
	enable_input(sd);

	return 0;
}
@@ -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 free run: %s\n",
			(!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
	v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
			io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
	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) & 0x70) >> 4);

	v4l2_info(sd, "-----Video Timings-----\n");
	if (read_stdi(sd, &stdi))
@@ -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, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
	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 -
				      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
				     for digital formats */

@@ -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 */
	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 */
	io_write(sd, 0x40, 0xc2); /* Configure INT1 */
	io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
@@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client,
		v4l2_err(sd, "failed to create all i2c clients\n");
		goto err_i2c;
	}
	state->restart_stdi_once = true;

	/* work queues */
	state->work_queues = create_singlethread_workqueue(client->name);
+8 −3
Original line number Diff line number Diff line
@@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
		if (ret & 1) /* Autoexposure */
			ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
					rect.height + mt9v022->y_skip_top + 43);
		else
			ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
					rect.height + mt9v022->y_skip_top + 43);
		/*
		 * If autoexposure is off, there is no need to set
		 * 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 */
	if (!ret)
+4 −2
Original line number Diff line number Diff line
@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = {
MODULE_DEVICE_TABLE(platform, gsc_driver_ids);

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);
+2 −2
Original line number Diff line number Diff line
@@ -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,
				const struct v4l2_event_subscription *sub)
				struct v4l2_event_subscription *sub)
{
	if (sub->type != V4L2_EVENT_FRAME_SYNC)
		return -EINVAL;
@@ -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,
				  const struct v4l2_event_subscription *sub)
				  struct v4l2_event_subscription *sub)
{
	return v4l2_event_unsubscribe(fh, sub);
}
Loading