lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <200811251849.10196.hverkuil@xs4all.nl>
Date:	Tue, 25 Nov 2008 18:49:10 +0100
From:	Hans Verkuil <hverkuil@...all.nl>
To:	"Trilok Soni" <soni.trilok@...il.com>
Cc:	v4l <video4linux-list@...hat.com>,
	"linux-omap@...r.kernel.org" <linux-omap@...r.kernel.org>,
	"davinci-linux-open-source@...ux.davincidsp.com" 
	<davinci-linux-open-source@...ux.davincidsp.com>,
	linux-kernel@...r.kernel.org
Subject: Re: v4l2_device/v4l2_subdev: please review (PATCH 3/3)


# HG changeset patch
# User Hans Verkuil <hverkuil@...all.nl>
# Date 1227561257 -3600
# Node ID d5c3c3f0b53c549b53d9596c9a7e827ec7521c57
# Parent 3a957c63323e35f5862259814b728d4c08584963
cx25840: convert to v4l2_subdev.

From: Hans Verkuil <hverkuil@...all.nl>

Priority: normal

Signed-off-by: Hans Verkuil <hverkuil@...all.nl>

--- a/linux/drivers/media/video/cx25840/cx25840-audio.c	Mon Nov 24 
22:12:55 2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-audio.c	Mon Nov 24 
22:14:17 2008 +0100
@@ -26,7 +26,7 @@
 
 static int set_audclk_freq(struct i2c_client *client, u32 freq)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 
 	if (freq != 32000 && freq != 44100 && freq != 48000)
 		return -EINVAL;
@@ -194,7 +194,7 @@ static int set_audclk_freq(struct i2c_cl
 
 void cx25840_audio_set_path(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 
 	/* assert soft reset */
 	cx25840_and_or(client, 0x810, ~0x1, 0x01);
@@ -236,7 +236,7 @@ void cx25840_audio_set_path(struct i2c_c
 
 static int get_volume(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	int vol;
 
 	if (state->unmute_volume >= 0)
@@ -253,7 +253,7 @@ static int get_volume(struct i2c_client 
 
 static void set_volume(struct i2c_client *client, int volume)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	int vol;
 
 	if (state->unmute_volume >= 0) {
@@ -341,14 +341,14 @@ static void set_balance(struct i2c_clien
 
 static int get_mute(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 
 	return state->unmute_volume >= 0;
 }
 
 static void set_mute(struct i2c_client *client, int mute)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 
 	if (mute && state->unmute_volume == -1) {
 		int vol = get_volume(client);
@@ -366,7 +366,7 @@ static void set_mute(struct i2c_client *
 
 int cx25840_audio(struct i2c_client *client, unsigned int cmd, void 
*arg)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	struct v4l2_control *ctrl = arg;
 	int retval;
 
--- a/linux/drivers/media/video/cx25840/cx25840-core.c	Mon Nov 24 
22:12:55 2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-core.c	Mon Nov 24 
22:14:17 2008 +0100
@@ -185,11 +185,11 @@ static void cx25836_initialize(struct i2
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
 static void cx25840_work_handler(struct work_struct *work)
 {
-	struct cx25840_state *state = container_of(work, struct cx25840_state, 
fw_work);
+	struct subdev_state *state = container_of(work, struct subdev_state, 
fw_work);
 #else
 void cx25840_work_handler(void *arg)
 {
-	struct cx25840_state *state = arg;
+	struct subdev_state *state = arg;
 #endif
 	cx25840_loadfw(state->c);
 	wake_up(&state->fw_wait);
@@ -198,7 +198,7 @@ static void cx25840_initialize(struct i2
 static void cx25840_initialize(struct i2c_client *client)
 {
 	DEFINE_WAIT(wait);
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	struct workqueue_struct *q;
 
 	/* datasheet startup in numbered steps, refer to page 3-77 */
@@ -270,7 +270,7 @@ static void cx23885_initialize(struct i2
 static void cx23885_initialize(struct i2c_client *client)
 {
 	DEFINE_WAIT(wait);
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	struct workqueue_struct *q;
 
 	/* Internal Reset */
@@ -369,7 +369,7 @@ static void cx23885_initialize(struct i2
 
 void cx25840_std_setup(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	v4l2_std_id std = state->std;
 	int hblank, hactive, burst, vblank, vactive, sc;
 	int vblank656, src_decimation;
@@ -516,7 +516,7 @@ void cx25840_std_setup(struct i2c_client
 
 static void input_change(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	v4l2_std_id std = state->std;
 
 	/* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
@@ -570,7 +570,7 @@ static int set_input(struct i2c_client *
 static int set_input(struct i2c_client *client, enum 
cx25840_video_input vid_input,
 						enum cx25840_audio_input aud_input)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	u8 is_composite = (vid_input >= CX25840_COMPOSITE1 &&
 			   vid_input <= CX25840_COMPOSITE8);
 	u8 reg;
@@ -690,7 +690,7 @@ static int set_input(struct i2c_client *
 
 static int set_v4lstd(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	u8 fmt = 0; 	/* zero is autodetect */
 	u8 pal_m = 0;
 
@@ -739,9 +739,10 @@ static int set_v4lstd(struct i2c_client 
 
 /* ----------------------------------------------------------------------- 
*/
 
-static int set_v4lctrl(struct i2c_client *client, struct v4l2_control 
*ctrl)
-{
-	struct cx25840_state *state = i2c_get_clientdata(client);
+static int subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control 
*ctrl)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
 	switch (ctrl->id) {
 	case CX25840_CID_ENABLE_PVR150_WORKAROUND:
@@ -805,9 +806,10 @@ static int set_v4lctrl(struct i2c_client
 	return 0;
 }
 
-static int get_v4lctrl(struct i2c_client *client, struct v4l2_control 
*ctrl)
-{
-	struct cx25840_state *state = i2c_get_clientdata(client);
+static int subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control 
*ctrl)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
 	switch (ctrl->id) {
 	case CX25840_CID_ENABLE_PVR150_WORKAROUND:
@@ -842,21 +844,23 @@ static int get_v4lctrl(struct i2c_client
 
 /* ----------------------------------------------------------------------- 
*/
 
-static int get_v4lfmt(struct i2c_client *client, struct v4l2_format 
*fmt)
-{
+static int subdev_g_fmt(struct v4l2_subdev *sd, struct v4l2_format 
*fmt)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	switch (fmt->type) {
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 		return cx25840_vbi(client, VIDIOC_G_FMT, fmt);
 	default:
 		return -EINVAL;
 	}
-
-	return 0;
-}
-
-static int set_v4lfmt(struct i2c_client *client, struct v4l2_format 
*fmt)
-{
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	return 0;
+}
+
+static int subdev_s_fmt(struct v4l2_subdev *sd, struct v4l2_format 
*fmt)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct v4l2_pix_format *pix;
 	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
 	int is_50Hz = !(state->std & V4L2_STD_525_60);
@@ -933,7 +937,7 @@ static void log_video_status(struct i2c_
 		"0xD", "0xE", "0xF"
 	};
 
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
 	u8 gen_stat1 = cx25840_read(client, 0x40d);
 	u8 gen_stat2 = cx25840_read(client, 0x40e);
@@ -963,7 +967,7 @@ static void log_video_status(struct i2c_
 
 static void log_audio_status(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	u8 download_ctl = cx25840_read(client, 0x803);
 	u8 mod_det_stat0 = cx25840_read(client, 0x804);
 	u8 mod_det_stat1 = cx25840_read(client, 0x805);
@@ -1116,21 +1120,12 @@ static void log_audio_status(struct i2c_
 
 /* ----------------------------------------------------------------------- 
*/
 
-static int cx25840_command(struct i2c_client *client, unsigned int cmd,
-			   void *arg)
-{
-	struct cx25840_state *state = i2c_get_clientdata(client);
-	struct v4l2_tuner *vt = arg;
-	struct v4l2_routing *route = arg;
-
-	/* ignore these commands */
-	switch (cmd) {
-		case TUNER_SET_TYPE_ADDR:
-			return 0;
-	}
+static int subdev_init(struct v4l2_subdev *sd, u32 val)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
 	if (!state->is_initialized) {
-		v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", 
cmd);
 		/* initialize on first use */
 		state->is_initialized = 1;
 		if (state->is_cx25836)
@@ -1140,50 +1135,69 @@ static int cx25840_command(struct i2c_cl
 		else
 			cx25840_initialize(client);
 	}
-
-	switch (cmd) {
+	return 0;
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	/* ioctls to allow direct access to the
-	 * cx25840 registers for testing */
-	case VIDIOC_DBG_G_REGISTER:
-	case VIDIOC_DBG_S_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-
-		if (!v4l2_chip_match_i2c_client(client, reg->match_type, 
reg->match_chip))
-			return -EINVAL;
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-
-		if (cmd == VIDIOC_DBG_G_REGISTER)
-			reg->val = cx25840_read(client, reg->reg & 0x0fff);
-		else
-			cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
-		break;
-	}
+static int subdev_g_register(struct v4l2_subdev *sd, struct 
v4l2_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client,
+				reg->match_type, reg->match_chip))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	reg->val = cx25840_read(client, reg->reg & 0x0fff);
+	return 0;
+}
+
+static int subdev_s_register(struct v4l2_subdev *sd, struct 
v4l2_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client,
+				reg->match_type, reg->match_chip))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
+	return 0;
+}
 #endif
 
-	case VIDIOC_INT_DECODE_VBI_LINE:
-		return cx25840_vbi(client, cmd, arg);
-
-	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-		return cx25840_audio(client, cmd, arg);
-
-	case VIDIOC_STREAMON:
-		v4l_dbg(1, cx25840_debug, client, "enable output\n");
+static int subdev_decode_vbi_line(struct v4l2_subdev *sd, struct 
v4l2_decode_vbi_line *vbi)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return cx25840_vbi(client, VIDIOC_INT_DECODE_VBI_LINE, vbi);
+}
+
+static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return cx25840_audio(client, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq);
+}
+
+static int subdev_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	v4l_dbg(1, cx25840_debug, client, "%s output\n",
+			enable ? "enable" : "disable");
+	if (enable) {
 		if (state->is_cx23885) {
 			u8 v = (cx25840_read(client, 0x421) | 0x0b);
 			cx25840_write(client, 0x421, v);
 		} else {
 			cx25840_write(client, 0x115,
-				state->is_cx25836 ? 0x0c : 0x8c);
+					state->is_cx25836 ? 0x0c : 0x8c);
 			cx25840_write(client, 0x116,
-				state->is_cx25836 ? 0x04 : 0x07);
-		}
-		break;
-
-	case VIDIOC_STREAMOFF:
-		v4l_dbg(1, cx25840_debug, client, "disable output\n");
+					state->is_cx25836 ? 0x04 : 0x07);
+		}
+	} else {
 		if (state->is_cx23885) {
 			u8 v = cx25840_read(client, 0x421) & ~(0x0b);
 			cx25840_write(client, 0x421, v);
@@ -1191,133 +1205,136 @@ static int cx25840_command(struct i2c_cl
 			cx25840_write(client, 0x115, 0x00);
 			cx25840_write(client, 0x116, 0x00);
 		}
+	}
+	return 0;
+}
+
+static int subdev_queryctrl(struct v4l2_subdev *sd, struct 
v4l2_queryctrl *qc)
+{
+	struct subdev_state *state = to_state(sd);
+
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill_std(qc);
+	default:
 		break;
-
-	case VIDIOC_LOG_STATUS:
-		log_video_status(client);
-		if (!state->is_cx25836)
-			log_audio_status(client);
-		break;
-
-	case VIDIOC_G_CTRL:
-		return get_v4lctrl(client, (struct v4l2_control *)arg);
-
-	case VIDIOC_S_CTRL:
-		return set_v4lctrl(client, (struct v4l2_control *)arg);
-
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *qc = arg;
-
-		switch (qc->id) {
-			case V4L2_CID_BRIGHTNESS:
-			case V4L2_CID_CONTRAST:
-			case V4L2_CID_SATURATION:
-			case V4L2_CID_HUE:
-				return v4l2_ctrl_query_fill_std(qc);
-			default:
-				break;
-		}
-		if (state->is_cx25836)
-			return -EINVAL;
-
-		switch (qc->id) {
-			case V4L2_CID_AUDIO_VOLUME:
-				return v4l2_ctrl_query_fill(qc, 0, 65535,
-					65535 / 100, state->default_volume);
-			case V4L2_CID_AUDIO_MUTE:
-			case V4L2_CID_AUDIO_BALANCE:
-			case V4L2_CID_AUDIO_BASS:
-			case V4L2_CID_AUDIO_TREBLE:
-				return v4l2_ctrl_query_fill_std(qc);
-			default:
-				return -EINVAL;
-		}
+	}
+	if (state->is_cx25836)
 		return -EINVAL;
-	}
-
-	case VIDIOC_G_STD:
-		*(v4l2_std_id *)arg = state->std;
-		break;
-
-	case VIDIOC_S_STD:
-		if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
-			return 0;
-		state->radio = 0;
-		state->std = *(v4l2_std_id *)arg;
-		return set_v4lstd(client);
-
-	case AUDC_SET_RADIO:
-		state->radio = 1;
-		break;
-
-	case VIDIOC_INT_G_VIDEO_ROUTING:
-		route->input = state->vid_input;
-		route->output = 0;
-		break;
-
-	case VIDIOC_INT_S_VIDEO_ROUTING:
-		return set_input(client, route->input, state->aud_input);
-
-	case VIDIOC_INT_G_AUDIO_ROUTING:
-		if (state->is_cx25836)
-			return -EINVAL;
-		route->input = state->aud_input;
-		route->output = 0;
-		break;
-
-	case VIDIOC_INT_S_AUDIO_ROUTING:
-		if (state->is_cx25836)
-			return -EINVAL;
-		return set_input(client, state->vid_input, route->input);
-
-	case VIDIOC_S_FREQUENCY:
-		if (!state->is_cx25836) {
-			input_change(client);
-		}
-		break;
-
-	case VIDIOC_G_TUNER:
-	{
-		u8 vpres = cx25840_read(client, 0x40e) & 0x20;
-		u8 mode;
-		int val = 0;
-
-		if (state->radio)
-			break;
-
-		vt->signal = vpres ? 0xffff : 0x0;
-		if (state->is_cx25836)
-			break;
-
-		vt->capability |=
-		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
-		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
-
-		mode = cx25840_read(client, 0x804);
-
-		/* get rxsubchans and audmode */
-		if ((mode & 0xf) == 1)
-			val |= V4L2_TUNER_SUB_STEREO;
-		else
-			val |= V4L2_TUNER_SUB_MONO;
-
-		if (mode == 2 || mode == 4)
-			val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-
-		if (mode & 0x10)
-			val |= V4L2_TUNER_SUB_SAP;
-
-		vt->rxsubchans = val;
-		vt->audmode = state->audmode;
-		break;
-	}
-
-	case VIDIOC_S_TUNER:
-		if (state->radio || state->is_cx25836)
-			break;
-
-		switch (vt->audmode) {
+
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535,
+				65535 / 100, state->default_volume);
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		return v4l2_ctrl_query_fill_std(qc);
+	default:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+static int subdev_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->radio == 0 && state->std == std)
+		return 0;
+	state->radio = 0;
+	state->std = std;
+	return set_v4lstd(client);
+}
+
+static int subdev_s_radio(struct v4l2_subdev *sd)
+{
+	struct subdev_state *state = to_state(sd);
+
+	state->radio = 1;
+	return 0;
+}
+
+static int subdev_s_video_routing(struct v4l2_subdev *sd, const struct 
v4l2_routing *route)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return set_input(client, route->input, state->aud_input);
+}
+
+static int subdev_s_audio_routing(struct v4l2_subdev *sd, const struct 
v4l2_routing *route)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->is_cx25836)
+		return -EINVAL;
+	return set_input(client, state->vid_input, route->input);
+}
+
+static int subdev_s_frequency(struct v4l2_subdev *sd, struct 
v4l2_frequency *freq)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!state->is_cx25836)
+		input_change(client);
+	return 0;
+}
+
+static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner 
*vt)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 vpres = cx25840_read(client, 0x40e) & 0x20;
+	u8 mode;
+	int val = 0;
+
+	if (state->radio)
+		return 0;
+
+	vt->signal = vpres ? 0xffff : 0x0;
+	if (state->is_cx25836)
+		return 0;
+
+	vt->capability |=
+		V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+		V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+	mode = cx25840_read(client, 0x804);
+
+	/* get rxsubchans and audmode */
+	if ((mode & 0xf) == 1)
+		val |= V4L2_TUNER_SUB_STEREO;
+	else
+		val |= V4L2_TUNER_SUB_MONO;
+
+	if (mode == 2 || mode == 4)
+		val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+	if (mode & 0x10)
+		val |= V4L2_TUNER_SUB_SAP;
+
+	vt->rxsubchans = val;
+	vt->audmode = state->audmode;
+	return 0;
+}
+
+static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner 
*vt)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->radio || state->is_cx25836)
+		return 0;
+
+	switch (vt->audmode) {
 		case V4L2_TUNER_MODE_MONO:
 			/* mono      -> mono
 			   stereo    -> mono
@@ -1345,41 +1362,100 @@ static int cx25840_command(struct i2c_cl
 			break;
 		default:
 			return -EINVAL;
-		}
-		state->audmode = vt->audmode;
-		break;
-
-	case VIDIOC_G_FMT:
-		return get_v4lfmt(client, (struct v4l2_format *)arg);
-
-	case VIDIOC_S_FMT:
-		return set_v4lfmt(client, (struct v4l2_format *)arg);
-
-	case VIDIOC_INT_RESET:
-		if (state->is_cx25836)
-			cx25836_initialize(client);
-		else if (state->is_cx23885)
-			cx23885_initialize(client);
-		else
-			cx25840_initialize(client);
-		break;
-
-	case VIDIOC_G_CHIP_IDENT:
-		return v4l2_chip_ident_i2c_client(client, arg, state->id, 
state->rev);
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
+	}
+	state->audmode = vt->audmode;
+	return 0;
+}
+
+static int subdev_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->is_cx25836)
+		cx25836_initialize(client);
+	else if (state->is_cx23885)
+		cx23885_initialize(client);
+	else
+		cx25840_initialize(client);
+	return 0;
+}
+
+static int subdev_g_chip_ident(struct v4l2_subdev *sd, struct 
v4l2_chip_ident *chip)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, state->id, 
state->rev);
+}
+
+static int subdev_log_status(struct v4l2_subdev *sd)
+{
+	struct subdev_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	log_video_status(client);
+	if (!state->is_cx25836)
+		log_audio_status(client);
+	return 0;
+}
+
+static int subdev_command(struct i2c_client *client, unsigned cmd, void 
*arg)
+{
+	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
 }
 
 /* ----------------------------------------------------------------------- 
*/
 
-static int cx25840_probe(struct i2c_client *client,
+static const struct v4l2_subdev_core_ops subdev_core_ops = {
+	.log_status = subdev_log_status,
+	.g_chip_ident = subdev_g_chip_ident,
+	.g_ctrl = subdev_g_ctrl,
+	.s_ctrl = subdev_s_ctrl,
+	.queryctrl = subdev_queryctrl,
+	.reset = subdev_reset,
+	.init = subdev_init,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = subdev_g_register,
+	.s_register = subdev_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
+	.s_frequency = subdev_s_frequency,
+	.s_std = subdev_s_std,
+	.s_radio = subdev_s_radio,
+	.g_tuner = subdev_g_tuner,
+	.s_tuner = subdev_s_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
+	.s_clock_freq = subdev_s_clock_freq,
+	.s_routing = subdev_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops subdev_video_ops = {
+	.s_routing = subdev_s_video_routing,
+	.g_fmt = subdev_g_fmt,
+	.s_fmt = subdev_s_fmt,
+	.decode_vbi_line = subdev_decode_vbi_line,
+	.s_stream = subdev_s_stream,
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+	.core = &subdev_core_ops,
+	.tuner = &subdev_tuner_ops,
+	.audio = &subdev_audio_ops,
+	.video = &subdev_video_ops,
+};
+
+/* ----------------------------------------------------------------------- 
*/
+
+static int subdev_probe(struct i2c_client *client,
 			 const struct i2c_device_id *did)
 {
-	struct cx25840_state *state;
+	struct subdev_state *state;
+	struct v4l2_subdev *sd;
 	u32 id;
 	u16 device_id;
 
@@ -1410,11 +1486,12 @@ static int cx25840_probe(struct i2c_clie
 		return -ENODEV;
 	}
 
-	state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
-	if (state == NULL) {
+	state = kzalloc(sizeof(struct subdev_state), GFP_KERNEL);
+	if (state == NULL)
 		return -ENOMEM;
-	}
-
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &subdev_ops);
 	/* Note: revision '(device_id & 0x0f) == 2' was never built. The
 	   marking skips from 0x1 == 22 to 0x3 == 23. */
 	v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
@@ -1422,7 +1499,6 @@ static int cx25840_probe(struct i2c_clie
 		    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 
0x0f),
 		    client->addr << 1, client->adapter->name);
 
-	i2c_set_clientdata(client, state);
 	state->c = client;
 	state->is_cx25836 = ((device_id & 0xff00) == 0x8300);
 	state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313);
@@ -1447,9 +1523,12 @@ static int cx25840_probe(struct i2c_clie
 	return 0;
 }
 
-static int cx25840_remove(struct i2c_client *client)
-{
-	kfree(i2c_get_clientdata(client));
+static int subdev_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
 	return 0;
 }
 
@@ -1464,9 +1543,9 @@ static struct v4l2_i2c_driver_data v4l2_
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "cx25840",
 	.driverid = I2C_DRIVERID_CX25840,
-	.command = cx25840_command,
-	.probe = cx25840_probe,
-	.remove = cx25840_remove,
+	.command = subdev_command,
+	.probe = subdev_probe,
+	.remove = subdev_remove,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
 	.id_table = cx25840_id,
 #endif
--- a/linux/drivers/media/video/cx25840/cx25840-core.h	Mon Nov 24 
22:12:55 2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-core.h	Mon Nov 24 
22:14:17 2008 +0100
@@ -23,6 +23,7 @@
 #include "compat.h"
 
 #include <linux/videodev2.h>
+#include <media/v4l2-device.h>
 #include <linux/i2c.h>
 
 /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug 
that is
@@ -33,8 +34,9 @@
    providing this information. */
 #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
 
-struct cx25840_state {
+struct subdev_state {
 	struct i2c_client *c;
+	struct v4l2_subdev sd;
 	int pvr150_workaround;
 	int radio;
 	v4l2_std_id std;
@@ -53,6 +55,11 @@ struct cx25840_state {
 	wait_queue_head_t fw_wait;    /* wake up when the fw load is finished 
*/
 	struct work_struct fw_work;   /* work entry for fw load */
 };
+
+static inline struct subdev_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct subdev_state, sd);
+}
 
 /* ----------------------------------------------------------------------- 
*/
 /* cx25850-core.c 							   */
--- a/linux/drivers/media/video/cx25840/cx25840-firmware.c	Mon Nov 24 
22:12:55 2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c	Mon Nov 24 
22:14:17 2008 +0100
@@ -92,7 +92,7 @@ static int fw_write(struct i2c_client *c
 
 int cx25840_loadfw(struct i2c_client *client)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	const struct firmware *fw = NULL;
 	u8 buffer[FWSEND];
 	const u8 *ptr;
--- a/linux/drivers/media/video/cx25840/cx25840-vbi.c	Mon Nov 24 
22:12:55 2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-vbi.c	Mon Nov 24 
22:14:17 2008 +0100
@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
 
 int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
 {
-	struct cx25840_state *state = i2c_get_clientdata(client);
+	struct subdev_state *state = to_state(i2c_get_clientdata(client));
 	struct v4l2_format *fmt;
 	struct v4l2_sliced_vbi_format *svbi;
 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ