The patch number 9823 was added via Hans Verkuil <hverk...@xs4all.nl>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        v4l-dvb-maintai...@linuxtv.org

------

From: Hans Verkuil  <hverk...@xs4all.nl>
cx25840: convert to v4l2_subdev.


Priority: normal

Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>


---

 linux/drivers/media/video/cx25840/cx25840-audio.c    |   14 
 linux/drivers/media/video/cx25840/cx25840-core.c     |  537 ++++++-----
 linux/drivers/media/video/cx25840/cx25840-core.h     |    7 
 linux/drivers/media/video/cx25840/cx25840-firmware.c |    2 
 linux/drivers/media/video/cx25840/cx25840-vbi.c      |    2 
 5 files changed, 324 insertions(+), 238 deletions(-)

diff -r c0a6e07deaf5 -r 3513f8d73839 
linux/drivers/media/video/cx25840/cx25840-audio.c
--- a/linux/drivers/media/video/cx25840/cx25840-audio.c Sat Nov 29 16:45:59 
2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-audio.c Sat Nov 29 16:50:06 
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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_state *state = to_state(i2c_get_clientdata(client));
        struct v4l2_control *ctrl = arg;
        int retval;
 
diff -r c0a6e07deaf5 -r 3513f8d73839 
linux/drivers/media/video/cx25840/cx25840-core.c
--- a/linux/drivers/media/video/cx25840/cx25840-core.c  Sat Nov 29 16:45:59 
2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-core.c  Sat Nov 29 16:50:06 
2008 +0100
@@ -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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct cx25840_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 cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct cx25840_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 cx25840_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 cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       struct cx25840_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 cx25840_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 cx25840_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 cx25840_init(struct v4l2_subdev *sd, u32 val)
+{
+       struct cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_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 cx25840_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct cx25840_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 cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+       struct cx25840_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 cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+       struct cx25840_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 cx25840_s_radio(struct v4l2_subdev *sd)
+{
+       struct cx25840_state *state = to_state(sd);
+
+       state->radio = 1;
+       return 0;
+}
+
+static int cx25840_s_video_routing(struct v4l2_subdev *sd, const struct 
v4l2_routing *route)
+{
+       struct cx25840_state *state = to_state(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return set_input(client, route->input, state->aud_input);
+}
+
+static int cx25840_s_audio_routing(struct v4l2_subdev *sd, const struct 
v4l2_routing *route)
+{
+       struct cx25840_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 cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency 
*freq)
+{
+       struct cx25840_state *state = to_state(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!state->is_cx25836)
+               input_change(client);
+       return 0;
+}
+
+static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       struct cx25840_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 cx25840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       struct cx25840_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,34 +1362,92 @@ 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 cx25840_reset(struct v4l2_subdev *sd, u32 val)
+{
+       struct cx25840_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 cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident 
*chip)
+{
+       struct cx25840_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 cx25840_log_status(struct v4l2_subdev *sd)
+{
+       struct cx25840_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 cx25840_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+       return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops cx25840_core_ops = {
+       .log_status = cx25840_log_status,
+       .g_chip_ident = cx25840_g_chip_ident,
+       .g_ctrl = cx25840_g_ctrl,
+       .s_ctrl = cx25840_s_ctrl,
+       .queryctrl = cx25840_queryctrl,
+       .reset = cx25840_reset,
+       .init = cx25840_init,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = cx25840_g_register,
+       .s_register = cx25840_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
+       .s_frequency = cx25840_s_frequency,
+       .s_std = cx25840_s_std,
+       .s_radio = cx25840_s_radio,
+       .g_tuner = cx25840_g_tuner,
+       .s_tuner = cx25840_s_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
+       .s_clock_freq = cx25840_s_clock_freq,
+       .s_routing = cx25840_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops cx25840_video_ops = {
+       .s_routing = cx25840_s_video_routing,
+       .g_fmt = cx25840_g_fmt,
+       .s_fmt = cx25840_s_fmt,
+       .decode_vbi_line = cx25840_decode_vbi_line,
+       .s_stream = cx25840_s_stream,
+};
+
+static const struct v4l2_subdev_ops cx25840_ops = {
+       .core = &cx25840_core_ops,
+       .tuner = &cx25840_tuner_ops,
+       .audio = &cx25840_audio_ops,
+       .video = &cx25840_video_ops,
+};
 
 /* ----------------------------------------------------------------------- */
 
@@ -1380,6 +1455,7 @@ static int cx25840_probe(struct i2c_clie
                         const struct i2c_device_id *did)
 {
        struct cx25840_state *state;
+       struct v4l2_subdev *sd;
        u32 id;
        u16 device_id;
 
@@ -1411,10 +1487,11 @@ static int cx25840_probe(struct i2c_clie
        }
 
        state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
-       if (state == NULL) {
+       if (state == NULL)
                return -ENOMEM;
-       }
-
+
+       sd = &state->sd;
+       v4l2_i2c_subdev_init(sd, client, &cx25840_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);
@@ -1449,7 +1525,10 @@ static int cx25840_probe(struct i2c_clie
 
 static int cx25840_remove(struct i2c_client *client)
 {
-       kfree(i2c_get_clientdata(client));
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+       v4l2_device_unregister_subdev(sd);
+       kfree(to_state(sd));
        return 0;
 }
 
diff -r c0a6e07deaf5 -r 3513f8d73839 
linux/drivers/media/video/cx25840/cx25840-core.h
--- a/linux/drivers/media/video/cx25840/cx25840-core.h  Sat Nov 29 16:45:59 
2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-core.h  Sat Nov 29 16:50:06 
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
@@ -35,6 +36,7 @@
 
 struct cx25840_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 cx25840_state *to_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct cx25840_state, sd);
+}
 
 /* ----------------------------------------------------------------------- */
 /* cx25850-core.c                                                         */
diff -r c0a6e07deaf5 -r 3513f8d73839 
linux/drivers/media/video/cx25840/cx25840-firmware.c
--- a/linux/drivers/media/video/cx25840/cx25840-firmware.c      Sat Nov 29 
16:45:59 2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c      Sat Nov 29 
16:50:06 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 cx25840_state *state = to_state(i2c_get_clientdata(client));
        const struct firmware *fw = NULL;
        u8 buffer[FWSEND];
        const u8 *ptr;
diff -r c0a6e07deaf5 -r 3513f8d73839 
linux/drivers/media/video/cx25840/cx25840-vbi.c
--- a/linux/drivers/media/video/cx25840/cx25840-vbi.c   Sat Nov 29 16:45:59 
2008 +0100
+++ b/linux/drivers/media/video/cx25840/cx25840-vbi.c   Sat Nov 29 16:50:06 
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 cx25840_state *state = to_state(i2c_get_clientdata(client));
        struct v4l2_format *fmt;
        struct v4l2_sliced_vbi_format *svbi;
 


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/3513f8d73839ec4ba0513eb775753fb537ab7ff7

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to