diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-audio.c | 14 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.c | 447 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.h | 7 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-firmware.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840-vbi.c | 2 |
5 files changed, 279 insertions, 193 deletions
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index d6421e1e8f6a..d199d80ea0a3 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | static int set_audclk_freq(struct i2c_client *client, u32 freq) | 26 | static int set_audclk_freq(struct i2c_client *client, u32 freq) |
27 | { | 27 | { |
28 | struct cx25840_state *state = i2c_get_clientdata(client); | 28 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
29 | 29 | ||
30 | if (freq != 32000 && freq != 44100 && freq != 48000) | 30 | if (freq != 32000 && freq != 44100 && freq != 48000) |
31 | return -EINVAL; | 31 | return -EINVAL; |
@@ -193,7 +193,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) | |||
193 | 193 | ||
194 | void cx25840_audio_set_path(struct i2c_client *client) | 194 | void cx25840_audio_set_path(struct i2c_client *client) |
195 | { | 195 | { |
196 | struct cx25840_state *state = i2c_get_clientdata(client); | 196 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
197 | 197 | ||
198 | /* assert soft reset */ | 198 | /* assert soft reset */ |
199 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | 199 | cx25840_and_or(client, 0x810, ~0x1, 0x01); |
@@ -235,7 +235,7 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
235 | 235 | ||
236 | static int get_volume(struct i2c_client *client) | 236 | static int get_volume(struct i2c_client *client) |
237 | { | 237 | { |
238 | struct cx25840_state *state = i2c_get_clientdata(client); | 238 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
239 | int vol; | 239 | int vol; |
240 | 240 | ||
241 | if (state->unmute_volume >= 0) | 241 | if (state->unmute_volume >= 0) |
@@ -252,7 +252,7 @@ static int get_volume(struct i2c_client *client) | |||
252 | 252 | ||
253 | static void set_volume(struct i2c_client *client, int volume) | 253 | static void set_volume(struct i2c_client *client, int volume) |
254 | { | 254 | { |
255 | struct cx25840_state *state = i2c_get_clientdata(client); | 255 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
256 | int vol; | 256 | int vol; |
257 | 257 | ||
258 | if (state->unmute_volume >= 0) { | 258 | if (state->unmute_volume >= 0) { |
@@ -340,14 +340,14 @@ static void set_balance(struct i2c_client *client, int balance) | |||
340 | 340 | ||
341 | static int get_mute(struct i2c_client *client) | 341 | static int get_mute(struct i2c_client *client) |
342 | { | 342 | { |
343 | struct cx25840_state *state = i2c_get_clientdata(client); | 343 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
344 | 344 | ||
345 | return state->unmute_volume >= 0; | 345 | return state->unmute_volume >= 0; |
346 | } | 346 | } |
347 | 347 | ||
348 | static void set_mute(struct i2c_client *client, int mute) | 348 | static void set_mute(struct i2c_client *client, int mute) |
349 | { | 349 | { |
350 | struct cx25840_state *state = i2c_get_clientdata(client); | 350 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
351 | 351 | ||
352 | if (mute && state->unmute_volume == -1) { | 352 | if (mute && state->unmute_volume == -1) { |
353 | int vol = get_volume(client); | 353 | int vol = get_volume(client); |
@@ -365,7 +365,7 @@ static void set_mute(struct i2c_client *client, int mute) | |||
365 | 365 | ||
366 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) | 366 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) |
367 | { | 367 | { |
368 | struct cx25840_state *state = i2c_get_clientdata(client); | 368 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
369 | struct v4l2_control *ctrl = arg; | 369 | struct v4l2_control *ctrl = arg; |
370 | int retval; | 370 | int retval; |
371 | 371 | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 4da8cd74f00e..2ad277189da8 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -191,7 +191,7 @@ static void cx25840_work_handler(struct work_struct *work) | |||
191 | static void cx25840_initialize(struct i2c_client *client) | 191 | static void cx25840_initialize(struct i2c_client *client) |
192 | { | 192 | { |
193 | DEFINE_WAIT(wait); | 193 | DEFINE_WAIT(wait); |
194 | struct cx25840_state *state = i2c_get_clientdata(client); | 194 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
195 | struct workqueue_struct *q; | 195 | struct workqueue_struct *q; |
196 | 196 | ||
197 | /* datasheet startup in numbered steps, refer to page 3-77 */ | 197 | /* datasheet startup in numbered steps, refer to page 3-77 */ |
@@ -259,7 +259,7 @@ static void cx25840_initialize(struct i2c_client *client) | |||
259 | static void cx23885_initialize(struct i2c_client *client) | 259 | static void cx23885_initialize(struct i2c_client *client) |
260 | { | 260 | { |
261 | DEFINE_WAIT(wait); | 261 | DEFINE_WAIT(wait); |
262 | struct cx25840_state *state = i2c_get_clientdata(client); | 262 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
263 | struct workqueue_struct *q; | 263 | struct workqueue_struct *q; |
264 | 264 | ||
265 | /* Internal Reset */ | 265 | /* Internal Reset */ |
@@ -350,7 +350,7 @@ static void cx23885_initialize(struct i2c_client *client) | |||
350 | 350 | ||
351 | void cx25840_std_setup(struct i2c_client *client) | 351 | void cx25840_std_setup(struct i2c_client *client) |
352 | { | 352 | { |
353 | struct cx25840_state *state = i2c_get_clientdata(client); | 353 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
354 | v4l2_std_id std = state->std; | 354 | v4l2_std_id std = state->std; |
355 | int hblank, hactive, burst, vblank, vactive, sc; | 355 | int hblank, hactive, burst, vblank, vactive, sc; |
356 | int vblank656, src_decimation; | 356 | int vblank656, src_decimation; |
@@ -497,7 +497,7 @@ void cx25840_std_setup(struct i2c_client *client) | |||
497 | 497 | ||
498 | static void input_change(struct i2c_client *client) | 498 | static void input_change(struct i2c_client *client) |
499 | { | 499 | { |
500 | struct cx25840_state *state = i2c_get_clientdata(client); | 500 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
501 | v4l2_std_id std = state->std; | 501 | v4l2_std_id std = state->std; |
502 | 502 | ||
503 | /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ | 503 | /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ |
@@ -551,7 +551,7 @@ static void input_change(struct i2c_client *client) | |||
551 | static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, | 551 | static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, |
552 | enum cx25840_audio_input aud_input) | 552 | enum cx25840_audio_input aud_input) |
553 | { | 553 | { |
554 | struct cx25840_state *state = i2c_get_clientdata(client); | 554 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
555 | u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && | 555 | u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && |
556 | vid_input <= CX25840_COMPOSITE8); | 556 | vid_input <= CX25840_COMPOSITE8); |
557 | u8 reg; | 557 | u8 reg; |
@@ -671,7 +671,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
671 | 671 | ||
672 | static int set_v4lstd(struct i2c_client *client) | 672 | static int set_v4lstd(struct i2c_client *client) |
673 | { | 673 | { |
674 | struct cx25840_state *state = i2c_get_clientdata(client); | 674 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
675 | u8 fmt = 0; /* zero is autodetect */ | 675 | u8 fmt = 0; /* zero is autodetect */ |
676 | u8 pal_m = 0; | 676 | u8 pal_m = 0; |
677 | 677 | ||
@@ -720,9 +720,10 @@ static int set_v4lstd(struct i2c_client *client) | |||
720 | 720 | ||
721 | /* ----------------------------------------------------------------------- */ | 721 | /* ----------------------------------------------------------------------- */ |
722 | 722 | ||
723 | static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 723 | static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
724 | { | 724 | { |
725 | struct cx25840_state *state = i2c_get_clientdata(client); | 725 | struct cx25840_state *state = to_state(sd); |
726 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
726 | 727 | ||
727 | switch (ctrl->id) { | 728 | switch (ctrl->id) { |
728 | case CX25840_CID_ENABLE_PVR150_WORKAROUND: | 729 | case CX25840_CID_ENABLE_PVR150_WORKAROUND: |
@@ -786,9 +787,10 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | |||
786 | return 0; | 787 | return 0; |
787 | } | 788 | } |
788 | 789 | ||
789 | static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 790 | static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
790 | { | 791 | { |
791 | struct cx25840_state *state = i2c_get_clientdata(client); | 792 | struct cx25840_state *state = to_state(sd); |
793 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
792 | 794 | ||
793 | switch (ctrl->id) { | 795 | switch (ctrl->id) { |
794 | case CX25840_CID_ENABLE_PVR150_WORKAROUND: | 796 | case CX25840_CID_ENABLE_PVR150_WORKAROUND: |
@@ -823,21 +825,23 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | |||
823 | 825 | ||
824 | /* ----------------------------------------------------------------------- */ | 826 | /* ----------------------------------------------------------------------- */ |
825 | 827 | ||
826 | static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | 828 | static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
827 | { | 829 | { |
830 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
831 | |||
828 | switch (fmt->type) { | 832 | switch (fmt->type) { |
829 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | 833 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: |
830 | return cx25840_vbi(client, VIDIOC_G_FMT, fmt); | 834 | return cx25840_vbi(client, VIDIOC_G_FMT, fmt); |
831 | default: | 835 | default: |
832 | return -EINVAL; | 836 | return -EINVAL; |
833 | } | 837 | } |
834 | |||
835 | return 0; | 838 | return 0; |
836 | } | 839 | } |
837 | 840 | ||
838 | static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | 841 | static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) |
839 | { | 842 | { |
840 | struct cx25840_state *state = i2c_get_clientdata(client); | 843 | struct cx25840_state *state = to_state(sd); |
844 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
841 | struct v4l2_pix_format *pix; | 845 | struct v4l2_pix_format *pix; |
842 | int HSC, VSC, Vsrc, Hsrc, filter, Vlines; | 846 | int HSC, VSC, Vsrc, Hsrc, filter, Vlines; |
843 | int is_50Hz = !(state->std & V4L2_STD_525_60); | 847 | int is_50Hz = !(state->std & V4L2_STD_525_60); |
@@ -914,7 +918,7 @@ static void log_video_status(struct i2c_client *client) | |||
914 | "0xD", "0xE", "0xF" | 918 | "0xD", "0xE", "0xF" |
915 | }; | 919 | }; |
916 | 920 | ||
917 | struct cx25840_state *state = i2c_get_clientdata(client); | 921 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
918 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; | 922 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; |
919 | u8 gen_stat1 = cx25840_read(client, 0x40d); | 923 | u8 gen_stat1 = cx25840_read(client, 0x40d); |
920 | u8 gen_stat2 = cx25840_read(client, 0x40e); | 924 | u8 gen_stat2 = cx25840_read(client, 0x40e); |
@@ -944,7 +948,7 @@ static void log_video_status(struct i2c_client *client) | |||
944 | 948 | ||
945 | static void log_audio_status(struct i2c_client *client) | 949 | static void log_audio_status(struct i2c_client *client) |
946 | { | 950 | { |
947 | struct cx25840_state *state = i2c_get_clientdata(client); | 951 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
948 | u8 download_ctl = cx25840_read(client, 0x803); | 952 | u8 download_ctl = cx25840_read(client, 0x803); |
949 | u8 mod_det_stat0 = cx25840_read(client, 0x804); | 953 | u8 mod_det_stat0 = cx25840_read(client, 0x804); |
950 | u8 mod_det_stat1 = cx25840_read(client, 0x805); | 954 | u8 mod_det_stat1 = cx25840_read(client, 0x805); |
@@ -1097,21 +1101,12 @@ static void log_audio_status(struct i2c_client *client) | |||
1097 | 1101 | ||
1098 | /* ----------------------------------------------------------------------- */ | 1102 | /* ----------------------------------------------------------------------- */ |
1099 | 1103 | ||
1100 | static int cx25840_command(struct i2c_client *client, unsigned int cmd, | 1104 | static int cx25840_init(struct v4l2_subdev *sd, u32 val) |
1101 | void *arg) | ||
1102 | { | 1105 | { |
1103 | struct cx25840_state *state = i2c_get_clientdata(client); | 1106 | struct cx25840_state *state = to_state(sd); |
1104 | struct v4l2_tuner *vt = arg; | 1107 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1105 | struct v4l2_routing *route = arg; | ||
1106 | |||
1107 | /* ignore these commands */ | ||
1108 | switch (cmd) { | ||
1109 | case TUNER_SET_TYPE_ADDR: | ||
1110 | return 0; | ||
1111 | } | ||
1112 | 1108 | ||
1113 | if (!state->is_initialized) { | 1109 | if (!state->is_initialized) { |
1114 | v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd); | ||
1115 | /* initialize on first use */ | 1110 | /* initialize on first use */ |
1116 | state->is_initialized = 1; | 1111 | state->is_initialized = 1; |
1117 | if (state->is_cx25836) | 1112 | if (state->is_cx25836) |
@@ -1121,50 +1116,69 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
1121 | else | 1116 | else |
1122 | cx25840_initialize(client); | 1117 | cx25840_initialize(client); |
1123 | } | 1118 | } |
1119 | return 0; | ||
1120 | } | ||
1124 | 1121 | ||
1125 | switch (cmd) { | ||
1126 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1122 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1127 | /* ioctls to allow direct access to the | 1123 | static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg) |
1128 | * cx25840 registers for testing */ | 1124 | { |
1129 | case VIDIOC_DBG_G_REGISTER: | 1125 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1130 | case VIDIOC_DBG_S_REGISTER: | ||
1131 | { | ||
1132 | struct v4l2_register *reg = arg; | ||
1133 | |||
1134 | if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) | ||
1135 | return -EINVAL; | ||
1136 | if (!capable(CAP_SYS_ADMIN)) | ||
1137 | return -EPERM; | ||
1138 | 1126 | ||
1139 | if (cmd == VIDIOC_DBG_G_REGISTER) | 1127 | if (!v4l2_chip_match_i2c_client(client, |
1140 | reg->val = cx25840_read(client, reg->reg & 0x0fff); | 1128 | reg->match_type, reg->match_chip)) |
1141 | else | 1129 | return -EINVAL; |
1142 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | 1130 | if (!capable(CAP_SYS_ADMIN)) |
1143 | break; | 1131 | return -EPERM; |
1144 | } | 1132 | reg->val = cx25840_read(client, reg->reg & 0x0fff); |
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1136 | static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg) | ||
1137 | { | ||
1138 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1139 | |||
1140 | if (!v4l2_chip_match_i2c_client(client, | ||
1141 | reg->match_type, reg->match_chip)) | ||
1142 | return -EINVAL; | ||
1143 | if (!capable(CAP_SYS_ADMIN)) | ||
1144 | return -EPERM; | ||
1145 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | ||
1146 | return 0; | ||
1147 | } | ||
1145 | #endif | 1148 | #endif |
1146 | 1149 | ||
1147 | case VIDIOC_INT_DECODE_VBI_LINE: | 1150 | static int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) |
1148 | return cx25840_vbi(client, cmd, arg); | 1151 | { |
1152 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1149 | 1153 | ||
1150 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | 1154 | return cx25840_vbi(client, VIDIOC_INT_DECODE_VBI_LINE, vbi); |
1151 | return cx25840_audio(client, cmd, arg); | 1155 | } |
1156 | |||
1157 | static int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | ||
1158 | { | ||
1159 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1160 | |||
1161 | return cx25840_audio(client, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); | ||
1162 | } | ||
1163 | |||
1164 | static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | ||
1165 | { | ||
1166 | struct cx25840_state *state = to_state(sd); | ||
1167 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1152 | 1168 | ||
1153 | case VIDIOC_STREAMON: | 1169 | v4l_dbg(1, cx25840_debug, client, "%s output\n", |
1154 | v4l_dbg(1, cx25840_debug, client, "enable output\n"); | 1170 | enable ? "enable" : "disable"); |
1171 | if (enable) { | ||
1155 | if (state->is_cx23885) { | 1172 | if (state->is_cx23885) { |
1156 | u8 v = (cx25840_read(client, 0x421) | 0x0b); | 1173 | u8 v = (cx25840_read(client, 0x421) | 0x0b); |
1157 | cx25840_write(client, 0x421, v); | 1174 | cx25840_write(client, 0x421, v); |
1158 | } else { | 1175 | } else { |
1159 | cx25840_write(client, 0x115, | 1176 | cx25840_write(client, 0x115, |
1160 | state->is_cx25836 ? 0x0c : 0x8c); | 1177 | state->is_cx25836 ? 0x0c : 0x8c); |
1161 | cx25840_write(client, 0x116, | 1178 | cx25840_write(client, 0x116, |
1162 | state->is_cx25836 ? 0x04 : 0x07); | 1179 | state->is_cx25836 ? 0x04 : 0x07); |
1163 | } | 1180 | } |
1164 | break; | 1181 | } else { |
1165 | |||
1166 | case VIDIOC_STREAMOFF: | ||
1167 | v4l_dbg(1, cx25840_debug, client, "disable output\n"); | ||
1168 | if (state->is_cx23885) { | 1182 | if (state->is_cx23885) { |
1169 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); | 1183 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); |
1170 | cx25840_write(client, 0x421, v); | 1184 | cx25840_write(client, 0x421, v); |
@@ -1172,133 +1186,136 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
1172 | cx25840_write(client, 0x115, 0x00); | 1186 | cx25840_write(client, 0x115, 0x00); |
1173 | cx25840_write(client, 0x116, 0x00); | 1187 | cx25840_write(client, 0x116, 0x00); |
1174 | } | 1188 | } |
1175 | break; | 1189 | } |
1190 | return 0; | ||
1191 | } | ||
1176 | 1192 | ||
1177 | case VIDIOC_LOG_STATUS: | 1193 | static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) |
1178 | log_video_status(client); | 1194 | { |
1179 | if (!state->is_cx25836) | 1195 | struct cx25840_state *state = to_state(sd); |
1180 | log_audio_status(client); | ||
1181 | break; | ||
1182 | 1196 | ||
1183 | case VIDIOC_G_CTRL: | 1197 | switch (qc->id) { |
1184 | return get_v4lctrl(client, (struct v4l2_control *)arg); | 1198 | case V4L2_CID_BRIGHTNESS: |
1199 | case V4L2_CID_CONTRAST: | ||
1200 | case V4L2_CID_SATURATION: | ||
1201 | case V4L2_CID_HUE: | ||
1202 | return v4l2_ctrl_query_fill_std(qc); | ||
1203 | default: | ||
1204 | break; | ||
1205 | } | ||
1206 | if (state->is_cx25836) | ||
1207 | return -EINVAL; | ||
1185 | 1208 | ||
1186 | case VIDIOC_S_CTRL: | 1209 | switch (qc->id) { |
1187 | return set_v4lctrl(client, (struct v4l2_control *)arg); | 1210 | case V4L2_CID_AUDIO_VOLUME: |
1211 | return v4l2_ctrl_query_fill(qc, 0, 65535, | ||
1212 | 65535 / 100, state->default_volume); | ||
1213 | case V4L2_CID_AUDIO_MUTE: | ||
1214 | case V4L2_CID_AUDIO_BALANCE: | ||
1215 | case V4L2_CID_AUDIO_BASS: | ||
1216 | case V4L2_CID_AUDIO_TREBLE: | ||
1217 | return v4l2_ctrl_query_fill_std(qc); | ||
1218 | default: | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | return -EINVAL; | ||
1222 | } | ||
1188 | 1223 | ||
1189 | case VIDIOC_QUERYCTRL: | 1224 | static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std) |
1190 | { | 1225 | { |
1191 | struct v4l2_queryctrl *qc = arg; | 1226 | struct cx25840_state *state = to_state(sd); |
1227 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1192 | 1228 | ||
1193 | switch (qc->id) { | 1229 | if (state->radio == 0 && state->std == std) |
1194 | case V4L2_CID_BRIGHTNESS: | 1230 | return 0; |
1195 | case V4L2_CID_CONTRAST: | 1231 | state->radio = 0; |
1196 | case V4L2_CID_SATURATION: | 1232 | state->std = std; |
1197 | case V4L2_CID_HUE: | 1233 | return set_v4lstd(client); |
1198 | return v4l2_ctrl_query_fill_std(qc); | 1234 | } |
1199 | default: | ||
1200 | break; | ||
1201 | } | ||
1202 | if (state->is_cx25836) | ||
1203 | return -EINVAL; | ||
1204 | 1235 | ||
1205 | switch (qc->id) { | 1236 | static int cx25840_s_radio(struct v4l2_subdev *sd) |
1206 | case V4L2_CID_AUDIO_VOLUME: | 1237 | { |
1207 | return v4l2_ctrl_query_fill(qc, 0, 65535, | 1238 | struct cx25840_state *state = to_state(sd); |
1208 | 65535 / 100, state->default_volume); | ||
1209 | case V4L2_CID_AUDIO_MUTE: | ||
1210 | case V4L2_CID_AUDIO_BALANCE: | ||
1211 | case V4L2_CID_AUDIO_BASS: | ||
1212 | case V4L2_CID_AUDIO_TREBLE: | ||
1213 | return v4l2_ctrl_query_fill_std(qc); | ||
1214 | default: | ||
1215 | return -EINVAL; | ||
1216 | } | ||
1217 | return -EINVAL; | ||
1218 | } | ||
1219 | 1239 | ||
1220 | case VIDIOC_G_STD: | 1240 | state->radio = 1; |
1221 | *(v4l2_std_id *)arg = state->std; | 1241 | return 0; |
1222 | break; | 1242 | } |
1223 | 1243 | ||
1224 | case VIDIOC_S_STD: | 1244 | static int cx25840_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) |
1225 | if (state->radio == 0 && state->std == *(v4l2_std_id *)arg) | 1245 | { |
1226 | return 0; | 1246 | struct cx25840_state *state = to_state(sd); |
1227 | state->radio = 0; | 1247 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1228 | state->std = *(v4l2_std_id *)arg; | ||
1229 | return set_v4lstd(client); | ||
1230 | 1248 | ||
1231 | case AUDC_SET_RADIO: | 1249 | return set_input(client, route->input, state->aud_input); |
1232 | state->radio = 1; | 1250 | } |
1233 | break; | ||
1234 | 1251 | ||
1235 | case VIDIOC_INT_G_VIDEO_ROUTING: | 1252 | static int cx25840_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) |
1236 | route->input = state->vid_input; | 1253 | { |
1237 | route->output = 0; | 1254 | struct cx25840_state *state = to_state(sd); |
1238 | break; | 1255 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1239 | 1256 | ||
1240 | case VIDIOC_INT_S_VIDEO_ROUTING: | 1257 | if (state->is_cx25836) |
1241 | return set_input(client, route->input, state->aud_input); | 1258 | return -EINVAL; |
1259 | return set_input(client, state->vid_input, route->input); | ||
1260 | } | ||
1242 | 1261 | ||
1243 | case VIDIOC_INT_G_AUDIO_ROUTING: | 1262 | static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) |
1244 | if (state->is_cx25836) | 1263 | { |
1245 | return -EINVAL; | 1264 | struct cx25840_state *state = to_state(sd); |
1246 | route->input = state->aud_input; | 1265 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1247 | route->output = 0; | ||
1248 | break; | ||
1249 | 1266 | ||
1250 | case VIDIOC_INT_S_AUDIO_ROUTING: | 1267 | if (!state->is_cx25836) |
1251 | if (state->is_cx25836) | 1268 | input_change(client); |
1252 | return -EINVAL; | 1269 | return 0; |
1253 | return set_input(client, state->vid_input, route->input); | 1270 | } |
1254 | 1271 | ||
1255 | case VIDIOC_S_FREQUENCY: | 1272 | static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
1256 | if (!state->is_cx25836) { | 1273 | { |
1257 | input_change(client); | 1274 | struct cx25840_state *state = to_state(sd); |
1258 | } | 1275 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1259 | break; | 1276 | u8 vpres = cx25840_read(client, 0x40e) & 0x20; |
1277 | u8 mode; | ||
1278 | int val = 0; | ||
1260 | 1279 | ||
1261 | case VIDIOC_G_TUNER: | 1280 | if (state->radio) |
1262 | { | 1281 | return 0; |
1263 | u8 vpres = cx25840_read(client, 0x40e) & 0x20; | ||
1264 | u8 mode; | ||
1265 | int val = 0; | ||
1266 | 1282 | ||
1267 | if (state->radio) | 1283 | vt->signal = vpres ? 0xffff : 0x0; |
1268 | break; | 1284 | if (state->is_cx25836) |
1285 | return 0; | ||
1269 | 1286 | ||
1270 | vt->signal = vpres ? 0xffff : 0x0; | 1287 | vt->capability |= |
1271 | if (state->is_cx25836) | 1288 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | |
1272 | break; | 1289 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; |
1273 | 1290 | ||
1274 | vt->capability |= | 1291 | mode = cx25840_read(client, 0x804); |
1275 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | | ||
1276 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | ||
1277 | 1292 | ||
1278 | mode = cx25840_read(client, 0x804); | 1293 | /* get rxsubchans and audmode */ |
1294 | if ((mode & 0xf) == 1) | ||
1295 | val |= V4L2_TUNER_SUB_STEREO; | ||
1296 | else | ||
1297 | val |= V4L2_TUNER_SUB_MONO; | ||
1279 | 1298 | ||
1280 | /* get rxsubchans and audmode */ | 1299 | if (mode == 2 || mode == 4) |
1281 | if ((mode & 0xf) == 1) | 1300 | val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
1282 | val |= V4L2_TUNER_SUB_STEREO; | ||
1283 | else | ||
1284 | val |= V4L2_TUNER_SUB_MONO; | ||
1285 | 1301 | ||
1286 | if (mode == 2 || mode == 4) | 1302 | if (mode & 0x10) |
1287 | val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | 1303 | val |= V4L2_TUNER_SUB_SAP; |
1288 | 1304 | ||
1289 | if (mode & 0x10) | 1305 | vt->rxsubchans = val; |
1290 | val |= V4L2_TUNER_SUB_SAP; | 1306 | vt->audmode = state->audmode; |
1307 | return 0; | ||
1308 | } | ||
1291 | 1309 | ||
1292 | vt->rxsubchans = val; | 1310 | static int cx25840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
1293 | vt->audmode = state->audmode; | 1311 | { |
1294 | break; | 1312 | struct cx25840_state *state = to_state(sd); |
1295 | } | 1313 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1296 | 1314 | ||
1297 | case VIDIOC_S_TUNER: | 1315 | if (state->radio || state->is_cx25836) |
1298 | if (state->radio || state->is_cx25836) | 1316 | return 0; |
1299 | break; | ||
1300 | 1317 | ||
1301 | switch (vt->audmode) { | 1318 | switch (vt->audmode) { |
1302 | case V4L2_TUNER_MODE_MONO: | 1319 | case V4L2_TUNER_MODE_MONO: |
1303 | /* mono -> mono | 1320 | /* mono -> mono |
1304 | stereo -> mono | 1321 | stereo -> mono |
@@ -1326,41 +1343,100 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
1326 | break; | 1343 | break; |
1327 | default: | 1344 | default: |
1328 | return -EINVAL; | 1345 | return -EINVAL; |
1329 | } | 1346 | } |
1330 | state->audmode = vt->audmode; | 1347 | state->audmode = vt->audmode; |
1331 | break; | 1348 | return 0; |
1349 | } | ||
1332 | 1350 | ||
1333 | case VIDIOC_G_FMT: | 1351 | static int cx25840_reset(struct v4l2_subdev *sd, u32 val) |
1334 | return get_v4lfmt(client, (struct v4l2_format *)arg); | 1352 | { |
1353 | struct cx25840_state *state = to_state(sd); | ||
1354 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1335 | 1355 | ||
1336 | case VIDIOC_S_FMT: | 1356 | if (state->is_cx25836) |
1337 | return set_v4lfmt(client, (struct v4l2_format *)arg); | 1357 | cx25836_initialize(client); |
1358 | else if (state->is_cx23885) | ||
1359 | cx23885_initialize(client); | ||
1360 | else | ||
1361 | cx25840_initialize(client); | ||
1362 | return 0; | ||
1363 | } | ||
1338 | 1364 | ||
1339 | case VIDIOC_INT_RESET: | 1365 | static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip) |
1340 | if (state->is_cx25836) | 1366 | { |
1341 | cx25836_initialize(client); | 1367 | struct cx25840_state *state = to_state(sd); |
1342 | else if (state->is_cx23885) | 1368 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1343 | cx23885_initialize(client); | ||
1344 | else | ||
1345 | cx25840_initialize(client); | ||
1346 | break; | ||
1347 | 1369 | ||
1348 | case VIDIOC_G_CHIP_IDENT: | 1370 | return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); |
1349 | return v4l2_chip_ident_i2c_client(client, arg, state->id, state->rev); | 1371 | } |
1350 | 1372 | ||
1351 | default: | 1373 | static int cx25840_log_status(struct v4l2_subdev *sd) |
1352 | return -EINVAL; | 1374 | { |
1353 | } | 1375 | struct cx25840_state *state = to_state(sd); |
1376 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1354 | 1377 | ||
1378 | log_video_status(client); | ||
1379 | if (!state->is_cx25836) | ||
1380 | log_audio_status(client); | ||
1355 | return 0; | 1381 | return 0; |
1356 | } | 1382 | } |
1357 | 1383 | ||
1384 | static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) | ||
1385 | { | ||
1386 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); | ||
1387 | } | ||
1388 | |||
1389 | /* ----------------------------------------------------------------------- */ | ||
1390 | |||
1391 | static const struct v4l2_subdev_core_ops cx25840_core_ops = { | ||
1392 | .log_status = cx25840_log_status, | ||
1393 | .g_chip_ident = cx25840_g_chip_ident, | ||
1394 | .g_ctrl = cx25840_g_ctrl, | ||
1395 | .s_ctrl = cx25840_s_ctrl, | ||
1396 | .queryctrl = cx25840_queryctrl, | ||
1397 | .reset = cx25840_reset, | ||
1398 | .init = cx25840_init, | ||
1399 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1400 | .g_register = cx25840_g_register, | ||
1401 | .s_register = cx25840_s_register, | ||
1402 | #endif | ||
1403 | }; | ||
1404 | |||
1405 | static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { | ||
1406 | .s_frequency = cx25840_s_frequency, | ||
1407 | .s_std = cx25840_s_std, | ||
1408 | .s_radio = cx25840_s_radio, | ||
1409 | .g_tuner = cx25840_g_tuner, | ||
1410 | .s_tuner = cx25840_s_tuner, | ||
1411 | }; | ||
1412 | |||
1413 | static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { | ||
1414 | .s_clock_freq = cx25840_s_clock_freq, | ||
1415 | .s_routing = cx25840_s_audio_routing, | ||
1416 | }; | ||
1417 | |||
1418 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { | ||
1419 | .s_routing = cx25840_s_video_routing, | ||
1420 | .g_fmt = cx25840_g_fmt, | ||
1421 | .s_fmt = cx25840_s_fmt, | ||
1422 | .decode_vbi_line = cx25840_decode_vbi_line, | ||
1423 | .s_stream = cx25840_s_stream, | ||
1424 | }; | ||
1425 | |||
1426 | static const struct v4l2_subdev_ops cx25840_ops = { | ||
1427 | .core = &cx25840_core_ops, | ||
1428 | .tuner = &cx25840_tuner_ops, | ||
1429 | .audio = &cx25840_audio_ops, | ||
1430 | .video = &cx25840_video_ops, | ||
1431 | }; | ||
1432 | |||
1358 | /* ----------------------------------------------------------------------- */ | 1433 | /* ----------------------------------------------------------------------- */ |
1359 | 1434 | ||
1360 | static int cx25840_probe(struct i2c_client *client, | 1435 | static int cx25840_probe(struct i2c_client *client, |
1361 | const struct i2c_device_id *did) | 1436 | const struct i2c_device_id *did) |
1362 | { | 1437 | { |
1363 | struct cx25840_state *state; | 1438 | struct cx25840_state *state; |
1439 | struct v4l2_subdev *sd; | ||
1364 | u32 id; | 1440 | u32 id; |
1365 | u16 device_id; | 1441 | u16 device_id; |
1366 | 1442 | ||
@@ -1392,10 +1468,11 @@ static int cx25840_probe(struct i2c_client *client, | |||
1392 | } | 1468 | } |
1393 | 1469 | ||
1394 | state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); | 1470 | state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); |
1395 | if (state == NULL) { | 1471 | if (state == NULL) |
1396 | return -ENOMEM; | 1472 | return -ENOMEM; |
1397 | } | ||
1398 | 1473 | ||
1474 | sd = &state->sd; | ||
1475 | v4l2_i2c_subdev_init(sd, client, &cx25840_ops); | ||
1399 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The | 1476 | /* Note: revision '(device_id & 0x0f) == 2' was never built. The |
1400 | marking skips from 0x1 == 22 to 0x3 == 23. */ | 1477 | marking skips from 0x1 == 22 to 0x3 == 23. */ |
1401 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", | 1478 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", |
@@ -1403,7 +1480,6 @@ static int cx25840_probe(struct i2c_client *client, | |||
1403 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), | 1480 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : (device_id & 0x0f), |
1404 | client->addr << 1, client->adapter->name); | 1481 | client->addr << 1, client->adapter->name); |
1405 | 1482 | ||
1406 | i2c_set_clientdata(client, state); | ||
1407 | state->c = client; | 1483 | state->c = client; |
1408 | state->is_cx25836 = ((device_id & 0xff00) == 0x8300); | 1484 | state->is_cx25836 = ((device_id & 0xff00) == 0x8300); |
1409 | state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); | 1485 | state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); |
@@ -1430,7 +1506,10 @@ static int cx25840_probe(struct i2c_client *client, | |||
1430 | 1506 | ||
1431 | static int cx25840_remove(struct i2c_client *client) | 1507 | static int cx25840_remove(struct i2c_client *client) |
1432 | { | 1508 | { |
1433 | kfree(i2c_get_clientdata(client)); | 1509 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1510 | |||
1511 | v4l2_device_unregister_subdev(sd); | ||
1512 | kfree(to_state(sd)); | ||
1434 | return 0; | 1513 | return 0; |
1435 | } | 1514 | } |
1436 | 1515 | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index b87337e590b4..be0558277ca3 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | 23 | ||
24 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
25 | #include <media/v4l2-device.h> | ||
25 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
26 | 27 | ||
27 | /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is | 28 | /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is |
@@ -34,6 +35,7 @@ | |||
34 | 35 | ||
35 | struct cx25840_state { | 36 | struct cx25840_state { |
36 | struct i2c_client *c; | 37 | struct i2c_client *c; |
38 | struct v4l2_subdev sd; | ||
37 | int pvr150_workaround; | 39 | int pvr150_workaround; |
38 | int radio; | 40 | int radio; |
39 | v4l2_std_id std; | 41 | v4l2_std_id std; |
@@ -53,6 +55,11 @@ struct cx25840_state { | |||
53 | struct work_struct fw_work; /* work entry for fw load */ | 55 | struct work_struct fw_work; /* work entry for fw load */ |
54 | }; | 56 | }; |
55 | 57 | ||
58 | static inline struct cx25840_state *to_state(struct v4l2_subdev *sd) | ||
59 | { | ||
60 | return container_of(sd, struct cx25840_state, sd); | ||
61 | } | ||
62 | |||
56 | /* ----------------------------------------------------------------------- */ | 63 | /* ----------------------------------------------------------------------- */ |
57 | /* cx25850-core.c */ | 64 | /* cx25850-core.c */ |
58 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); | 65 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); |
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 8d489a4b9570..0b2dceb74108 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -91,7 +91,7 @@ static int fw_write(struct i2c_client *client, const u8 *data, int size) | |||
91 | 91 | ||
92 | int cx25840_loadfw(struct i2c_client *client) | 92 | int cx25840_loadfw(struct i2c_client *client) |
93 | { | 93 | { |
94 | struct cx25840_state *state = i2c_get_clientdata(client); | 94 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
95 | const struct firmware *fw = NULL; | 95 | const struct firmware *fw = NULL; |
96 | u8 buffer[FWSEND]; | 96 | u8 buffer[FWSEND]; |
97 | const u8 *ptr; | 97 | const u8 *ptr; |
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 58e6ef1c28a0..03f09b288eb8 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -84,7 +84,7 @@ static int decode_vps(u8 * dst, u8 * p) | |||
84 | 84 | ||
85 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | 85 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) |
86 | { | 86 | { |
87 | struct cx25840_state *state = i2c_get_clientdata(client); | 87 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); |
88 | struct v4l2_format *fmt; | 88 | struct v4l2_format *fmt; |
89 | struct v4l2_sliced_vbi_format *svbi; | 89 | struct v4l2_sliced_vbi_format *svbi; |
90 | 90 | ||