diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-20 10:30:00 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-20 10:31:51 -0400 |
commit | 9554d57ebbc78db6d66057bfc12552247a7567da (patch) | |
tree | 2411d1ea00be7836bc4260d3f3ea8c2a482e8e5b | |
parent | 973848978be863607282391868efd77ace64278d (diff) |
Revert "[media] staging: media: go7007: Adlink MPG24 board issues"
This patch were applied by mistake, as it were rejected by Don, who
requested it to be broken into per-change patches.
This reverts commit 0982db20aba5fd124bb5942d679d8732478e992a.
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Volokh Konstantin <volokh84@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/staging/media/go7007/README | 18 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-driver.c | 27 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-priv.h | 2 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-usb.c | 5 | ||||
-rw-r--r-- | drivers/staging/media/go7007/go7007-v4l2.c | 7 | ||||
-rw-r--r-- | drivers/staging/media/go7007/wis-tw2804.c | 512 |
6 files changed, 164 insertions, 407 deletions
diff --git a/drivers/staging/media/go7007/README b/drivers/staging/media/go7007/README index 082a6818c64e..48f447637817 100644 --- a/drivers/staging/media/go7007/README +++ b/drivers/staging/media/go7007/README | |||
@@ -5,24 +5,6 @@ Todo: | |||
5 | and added to the build. | 5 | and added to the build. |
6 | - testing? | 6 | - testing? |
7 | - handle churn in v4l layer. | 7 | - handle churn in v4l layer. |
8 | - Some features for wis-tw2804 subdev control (comb filter,motion detector sensitive & mask,more over...) | ||
9 | - go7007-v4l2.c need rewrite with new v4l2 style without nonstandart IO controls (set detector & bitrate) | ||
10 | |||
11 | 05/05/2012 3.4.0-rc+: | ||
12 | Changes: | ||
13 | - When go7007 reset device, i2c was not worked (need rewrite GPIO5) | ||
14 | - As wis2804 has i2c_addr=0x00/*really*/, so Need set I2C_CLIENT_TEN flag for validity | ||
15 | - Some main nonzero initialization, rewrites with kzalloc instead kmalloc | ||
16 | - STATUS_SHUTDOWN was placed in incorrect place, so if firmware wasn`t loaded, we | ||
17 | failed v4l2_device_unregister with kernel panic (OOPS) | ||
18 | - Some new v4l2 style features as call_all(...s_stream...) for using subdev calls | ||
19 | - wis-tw2804.ko module code was incompatible with 3.4.x branch in initialization v4l2_subdev parts. | ||
20 | now i2c_get_clientdata(...) contains v4l2_subdev struct instead non standart wis_tw2804 struct | ||
21 | |||
22 | Adds: | ||
23 | - Additional chipset wis2804 controls with: gain,auto gain,inputs[0,1],color kill,chroma gain,gain balances, | ||
24 | for all 4 channels (from tw2804.pdf) | ||
25 | - Power control for each 4 ADC up when s_stream(...,1), down otherwise in wis-tw2804 module | ||
26 | 8 | ||
27 | Please send patchs to Greg Kroah-Hartman <greg@kroah.com> and Cc: Ross | 9 | Please send patchs to Greg Kroah-Hartman <greg@kroah.com> and Cc: Ross |
28 | Cohen <rcohen@snurgle.org> as well. | 10 | Cohen <rcohen@snurgle.org> as well. |
diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c index 2dff9b5906b9..ece2dd146487 100644 --- a/drivers/staging/media/go7007/go7007-driver.c +++ b/drivers/staging/media/go7007/go7007-driver.c | |||
@@ -173,11 +173,6 @@ static int go7007_init_encoder(struct go7007 *go) | |||
173 | go7007_write_addr(go, 0x3c82, 0x0001); | 173 | go7007_write_addr(go, 0x3c82, 0x0001); |
174 | go7007_write_addr(go, 0x3c80, 0x00fe); | 174 | go7007_write_addr(go, 0x3c80, 0x00fe); |
175 | } | 175 | } |
176 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { | ||
177 | /* set GPIO5 to be an output, currently low */ | ||
178 | go7007_write_addr(go, 0x3c82, 0x0000); | ||
179 | go7007_write_addr(go, 0x3c80, 0x00df); | ||
180 | } | ||
181 | return 0; | 176 | return 0; |
182 | } | 177 | } |
183 | 178 | ||
@@ -197,23 +192,17 @@ int go7007_reset_encoder(struct go7007 *go) | |||
197 | /* | 192 | /* |
198 | * Attempt to instantiate an I2C client by ID, probably loading a module. | 193 | * Attempt to instantiate an I2C client by ID, probably loading a module. |
199 | */ | 194 | */ |
200 | static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c) | 195 | static int init_i2c_module(struct i2c_adapter *adapter, const char *type, |
196 | int addr) | ||
201 | { | 197 | { |
202 | struct go7007 *go = i2c_get_adapdata(adapter); | 198 | struct go7007 *go = i2c_get_adapdata(adapter); |
203 | struct v4l2_device *v4l2_dev = &go->v4l2_dev; | 199 | struct v4l2_device *v4l2_dev = &go->v4l2_dev; |
204 | struct i2c_board_info info; | ||
205 | |||
206 | memset(&info, 0, sizeof(info)); | ||
207 | strlcpy(info.type, i2c->type, sizeof(info.type)); | ||
208 | info.addr = i2c->addr; | ||
209 | 200 | ||
210 | if (i2c->id == I2C_DRIVERID_WIS_TW2804) | 201 | if (v4l2_i2c_new_subdev(v4l2_dev, adapter, type, addr, NULL)) |
211 | info.flags |= I2C_CLIENT_TEN; | ||
212 | if (v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL)) | ||
213 | return 0; | 202 | return 0; |
214 | 203 | ||
215 | printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type); | 204 | printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", type); |
216 | return -EINVAL; | 205 | return -1; |
217 | } | 206 | } |
218 | 207 | ||
219 | /* | 208 | /* |
@@ -249,7 +238,9 @@ int go7007_register_encoder(struct go7007 *go) | |||
249 | } | 238 | } |
250 | if (go->i2c_adapter_online) { | 239 | if (go->i2c_adapter_online) { |
251 | for (i = 0; i < go->board_info->num_i2c_devs; ++i) | 240 | for (i = 0; i < go->board_info->num_i2c_devs; ++i) |
252 | init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]); | 241 | init_i2c_module(&go->i2c_adapter, |
242 | go->board_info->i2c_devs[i].type, | ||
243 | go->board_info->i2c_devs[i].addr); | ||
253 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) | 244 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) |
254 | i2c_clients_command(&go->i2c_adapter, | 245 | i2c_clients_command(&go->i2c_adapter, |
255 | DECODER_SET_CHANNEL, &go->channel_number); | 246 | DECODER_SET_CHANNEL, &go->channel_number); |
@@ -580,7 +571,7 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) | |||
580 | struct go7007 *go; | 571 | struct go7007 *go; |
581 | int i; | 572 | int i; |
582 | 573 | ||
583 | go = kzalloc(sizeof(struct go7007), GFP_KERNEL); | 574 | go = kmalloc(sizeof(struct go7007), GFP_KERNEL); |
584 | if (go == NULL) | 575 | if (go == NULL) |
585 | return NULL; | 576 | return NULL; |
586 | go->dev = dev; | 577 | go->dev = dev; |
diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h index b7b939a1967e..b58c394c6555 100644 --- a/drivers/staging/media/go7007/go7007-priv.h +++ b/drivers/staging/media/go7007/go7007-priv.h | |||
@@ -88,7 +88,7 @@ struct go7007_board_info { | |||
88 | int audio_bclk_div; | 88 | int audio_bclk_div; |
89 | int audio_main_div; | 89 | int audio_main_div; |
90 | int num_i2c_devs; | 90 | int num_i2c_devs; |
91 | struct go_i2c { | 91 | struct { |
92 | const char *type; | 92 | const char *type; |
93 | int id; | 93 | int id; |
94 | int addr; | 94 | int addr; |
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 9dbf5ecd05a2..5443e25086e9 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c | |||
@@ -1110,6 +1110,9 @@ static int go7007_usb_probe(struct usb_interface *intf, | |||
1110 | } else { | 1110 | } else { |
1111 | u16 channel; | 1111 | u16 channel; |
1112 | 1112 | ||
1113 | /* set GPIO5 to be an output, currently low */ | ||
1114 | go7007_write_addr(go, 0x3c82, 0x0000); | ||
1115 | go7007_write_addr(go, 0x3c80, 0x00df); | ||
1113 | /* read channel number from GPIO[1:0] */ | 1116 | /* read channel number from GPIO[1:0] */ |
1114 | go7007_read_addr(go, 0x3c81, &channel); | 1117 | go7007_read_addr(go, 0x3c81, &channel); |
1115 | channel &= 0x3; | 1118 | channel &= 0x3; |
@@ -1242,6 +1245,7 @@ static void go7007_usb_disconnect(struct usb_interface *intf) | |||
1242 | struct urb *vurb, *aurb; | 1245 | struct urb *vurb, *aurb; |
1243 | int i; | 1246 | int i; |
1244 | 1247 | ||
1248 | go->status = STATUS_SHUTDOWN; | ||
1245 | usb_kill_urb(usb->intr_urb); | 1249 | usb_kill_urb(usb->intr_urb); |
1246 | 1250 | ||
1247 | /* Free USB-related structs */ | 1251 | /* Free USB-related structs */ |
@@ -1265,7 +1269,6 @@ static void go7007_usb_disconnect(struct usb_interface *intf) | |||
1265 | kfree(go->hpi_context); | 1269 | kfree(go->hpi_context); |
1266 | 1270 | ||
1267 | go7007_remove(go); | 1271 | go7007_remove(go); |
1268 | go->status = STATUS_SHUTDOWN; | ||
1269 | } | 1272 | } |
1270 | 1273 | ||
1271 | static struct usb_driver go7007_usb_driver = { | 1274 | static struct usb_driver go7007_usb_driver = { |
diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c index b8f2eb6bc3ef..c184ad30fbd8 100644 --- a/drivers/staging/media/go7007/go7007-v4l2.c +++ b/drivers/staging/media/go7007/go7007-v4l2.c | |||
@@ -98,7 +98,7 @@ static int go7007_open(struct file *file) | |||
98 | 98 | ||
99 | if (go->status != STATUS_ONLINE) | 99 | if (go->status != STATUS_ONLINE) |
100 | return -EBUSY; | 100 | return -EBUSY; |
101 | gofh = kzalloc(sizeof(struct go7007_file), GFP_KERNEL); | 101 | gofh = kmalloc(sizeof(struct go7007_file), GFP_KERNEL); |
102 | if (gofh == NULL) | 102 | if (gofh == NULL) |
103 | return -ENOMEM; | 103 | return -ENOMEM; |
104 | ++go->ref_count; | 104 | ++go->ref_count; |
@@ -953,7 +953,6 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
953 | } | 953 | } |
954 | mutex_unlock(&go->hw_lock); | 954 | mutex_unlock(&go->hw_lock); |
955 | mutex_unlock(&gofh->lock); | 955 | mutex_unlock(&gofh->lock); |
956 | call_all(&go->v4l2_dev, video, s_stream, 1); | ||
957 | 956 | ||
958 | return retval; | 957 | return retval; |
959 | } | 958 | } |
@@ -969,7 +968,6 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
969 | mutex_lock(&gofh->lock); | 968 | mutex_lock(&gofh->lock); |
970 | go7007_streamoff(go); | 969 | go7007_streamoff(go); |
971 | mutex_unlock(&gofh->lock); | 970 | mutex_unlock(&gofh->lock); |
972 | call_all(&go->v4l2_dev, video, s_stream, 0); | ||
973 | 971 | ||
974 | return 0; | 972 | return 0; |
975 | } | 973 | } |
@@ -1834,6 +1832,5 @@ void go7007_v4l2_remove(struct go7007 *go) | |||
1834 | mutex_unlock(&go->hw_lock); | 1832 | mutex_unlock(&go->hw_lock); |
1835 | if (go->video_dev) | 1833 | if (go->video_dev) |
1836 | video_unregister_device(go->video_dev); | 1834 | video_unregister_device(go->video_dev); |
1837 | if (go->status != STATUS_SHUTDOWN) | 1835 | v4l2_device_unregister(&go->v4l2_dev); |
1838 | v4l2_device_unregister(&go->v4l2_dev); | ||
1839 | } | 1836 | } |
diff --git a/drivers/staging/media/go7007/wis-tw2804.c b/drivers/staging/media/go7007/wis-tw2804.c index 9afc5df5902e..9134f03e3cf0 100644 --- a/drivers/staging/media/go7007/wis-tw2804.c +++ b/drivers/staging/media/go7007/wis-tw2804.c | |||
@@ -21,27 +21,16 @@ | |||
21 | #include <linux/videodev2.h> | 21 | #include <linux/videodev2.h> |
22 | #include <linux/ioctl.h> | 22 | #include <linux/ioctl.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <media/v4l2-subdev.h> | ||
25 | #include <media/v4l2-device.h> | ||
26 | 24 | ||
27 | #include "wis-i2c.h" | 25 | #include "wis-i2c.h" |
28 | 26 | ||
29 | struct wis_tw2804 { | 27 | struct wis_tw2804 { |
30 | struct v4l2_subdev sd; | 28 | int channel; |
31 | u8 channel:2; | ||
32 | u8 input:1; | ||
33 | u8 update:1; | ||
34 | u8 auto_gain:1; | ||
35 | u8 ckil:1; | ||
36 | int norm; | 29 | int norm; |
37 | u8 brightness; | 30 | int brightness; |
38 | u8 contrast; | 31 | int contrast; |
39 | u8 saturation; | 32 | int saturation; |
40 | u8 hue; | 33 | int hue; |
41 | u8 gain; | ||
42 | u8 cr_gain; | ||
43 | u8 r_balance; | ||
44 | u8 b_balance; | ||
45 | }; | 34 | }; |
46 | 35 | ||
47 | static u8 global_registers[] = { | 36 | static u8 global_registers[] = { |
@@ -52,7 +41,6 @@ static u8 global_registers[] = { | |||
52 | 0x3d, 0x80, | 41 | 0x3d, 0x80, |
53 | 0x3e, 0x82, | 42 | 0x3e, 0x82, |
54 | 0x3f, 0x82, | 43 | 0x3f, 0x82, |
55 | 0x78, 0x0f, | ||
56 | 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ | 44 | 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ |
57 | }; | 45 | }; |
58 | 46 | ||
@@ -115,358 +103,29 @@ static u8 channel_registers[] = { | |||
115 | 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ | 103 | 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ |
116 | }; | 104 | }; |
117 | 105 | ||
118 | static s32 write_reg(struct i2c_client *client, u8 reg, u8 value, u8 channel) | 106 | static int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel) |
119 | { | 107 | { |
120 | return i2c_smbus_write_byte_data(client, reg | (channel << 6), value); | 108 | return i2c_smbus_write_byte_data(client, reg | (channel << 6), value); |
121 | } | 109 | } |
122 | 110 | ||
123 | static int write_regs(struct i2c_client *client, u8 *regs, u8 channel) | 111 | static int write_regs(struct i2c_client *client, u8 *regs, int channel) |
124 | { | 112 | { |
125 | int i; | 113 | int i; |
126 | 114 | ||
127 | for (i = 0; regs[i] != 0xff; i += 2) | 115 | for (i = 0; regs[i] != 0xff; i += 2) |
128 | if (i2c_smbus_write_byte_data(client, | 116 | if (i2c_smbus_write_byte_data(client, |
129 | regs[i] | (channel << 6), regs[i + 1]) < 0) | 117 | regs[i] | (channel << 6), regs[i + 1]) < 0) |
130 | return -EINVAL; | 118 | return -1; |
131 | return 0; | 119 | return 0; |
132 | } | 120 | } |
133 | 121 | ||
134 | static s32 read_reg(struct i2c_client *client, u8 reg, u8 channel) | ||
135 | { | ||
136 | return i2c_smbus_read_byte_data(client, (reg) | (channel << 6)); | ||
137 | } | ||
138 | |||
139 | static inline struct wis_tw2804 *to_state(struct v4l2_subdev *sd) | ||
140 | { | ||
141 | return container_of(sd, struct wis_tw2804, sd); | ||
142 | } | ||
143 | |||
144 | static int tw2804_log_status(struct v4l2_subdev *sd) | ||
145 | { | ||
146 | struct wis_tw2804 *state = to_state(sd); | ||
147 | v4l2_info(sd, "Standard: %s\n", state->norm == V4L2_STD_NTSC ? "NTSC" : | ||
148 | state->norm == V4L2_STD_PAL ? "PAL" : "unknown"); | ||
149 | v4l2_info(sd, "Channel: %d\n", state->channel); | ||
150 | v4l2_info(sd, "Input: %d\n", state->input); | ||
151 | v4l2_info(sd, "Brightness: %d\n", state->brightness); | ||
152 | v4l2_info(sd, "Contrast: %d\n", state->contrast); | ||
153 | v4l2_info(sd, "Saturation: %d\n", state->saturation); | ||
154 | v4l2_info(sd, "Hue: %d\n", state->hue); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int tw2804_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *query) | ||
159 | { | ||
160 | static const u32 user_ctrls[] = { | ||
161 | V4L2_CID_USER_CLASS, | ||
162 | V4L2_CID_BRIGHTNESS, | ||
163 | V4L2_CID_CONTRAST, | ||
164 | V4L2_CID_SATURATION, | ||
165 | V4L2_CID_HUE, | ||
166 | V4L2_CID_AUTOGAIN, | ||
167 | V4L2_CID_COLOR_KILLER, | ||
168 | V4L2_CID_GAIN, | ||
169 | V4L2_CID_CHROMA_GAIN, | ||
170 | V4L2_CID_BLUE_BALANCE, | ||
171 | V4L2_CID_RED_BALANCE, | ||
172 | 0 | ||
173 | }; | ||
174 | |||
175 | static const u32 *ctrl_classes[] = { | ||
176 | user_ctrls, | ||
177 | NULL | ||
178 | }; | ||
179 | |||
180 | query->id = v4l2_ctrl_next(ctrl_classes, query->id); | ||
181 | |||
182 | switch (query->id) { | ||
183 | case V4L2_CID_USER_CLASS: | ||
184 | return v4l2_ctrl_query_fill(query, 0, 0, 0, 0); | ||
185 | case V4L2_CID_BRIGHTNESS: | ||
186 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 128); | ||
187 | case V4L2_CID_CONTRAST: | ||
188 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 128); | ||
189 | case V4L2_CID_SATURATION: | ||
190 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 128); | ||
191 | case V4L2_CID_HUE: | ||
192 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 128); | ||
193 | case V4L2_CID_AUTOGAIN: | ||
194 | return v4l2_ctrl_query_fill(query, 0, 1, 1, 0); | ||
195 | case V4L2_CID_COLOR_KILLER: | ||
196 | return v4l2_ctrl_query_fill(query, 0, 1, 1, 0); | ||
197 | case V4L2_CID_GAIN: | ||
198 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 128); | ||
199 | case V4L2_CID_CHROMA_GAIN: | ||
200 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 128); | ||
201 | case V4L2_CID_BLUE_BALANCE: | ||
202 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 122); | ||
203 | case V4L2_CID_RED_BALANCE: | ||
204 | return v4l2_ctrl_query_fill(query, 0, 255, 1, 122); | ||
205 | default: | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | s32 get_ctrl_addr(int ctrl) | ||
211 | { | ||
212 | switch (ctrl) { | ||
213 | case V4L2_CID_BRIGHTNESS: | ||
214 | return 0x12; | ||
215 | case V4L2_CID_CONTRAST: | ||
216 | return 0x11; | ||
217 | case V4L2_CID_SATURATION: | ||
218 | return 0x10; | ||
219 | case V4L2_CID_HUE: | ||
220 | return 0x0f; | ||
221 | case V4L2_CID_AUTOGAIN: | ||
222 | return 0x02; | ||
223 | case V4L2_CID_COLOR_KILLER: | ||
224 | return 0x14; | ||
225 | case V4L2_CID_GAIN: | ||
226 | return 0x3c; | ||
227 | case V4L2_CID_CHROMA_GAIN: | ||
228 | return 0x3d; | ||
229 | case V4L2_CID_RED_BALANCE: | ||
230 | return 0x3f; | ||
231 | case V4L2_CID_BLUE_BALANCE: | ||
232 | return 0x3e; | ||
233 | default: | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | static int tw2804_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
239 | { | ||
240 | struct wis_tw2804 *state = to_state(sd); | ||
241 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
242 | s32 addr = get_ctrl_addr(ctrl->id); | ||
243 | s32 val = 0; | ||
244 | |||
245 | if (addr == -EINVAL) | ||
246 | return -EINVAL; | ||
247 | |||
248 | if (state->update) { | ||
249 | val = read_reg(client, addr, ctrl->id == V4L2_CID_GAIN || | ||
250 | ctrl->id == V4L2_CID_CHROMA_GAIN || | ||
251 | ctrl->id == V4L2_CID_RED_BALANCE || | ||
252 | ctrl->id == V4L2_CID_BLUE_BALANCE ? 0 : state->channel); | ||
253 | if (val < 0) | ||
254 | return val; | ||
255 | } | ||
256 | |||
257 | switch (ctrl->id) { | ||
258 | case V4L2_CID_BRIGHTNESS: | ||
259 | if (state->update) | ||
260 | state->brightness = val; | ||
261 | ctrl->value = state->brightness; | ||
262 | break; | ||
263 | case V4L2_CID_CONTRAST: | ||
264 | if (state->update) | ||
265 | state->contrast = val; | ||
266 | ctrl->value = state->contrast; | ||
267 | break; | ||
268 | case V4L2_CID_SATURATION: | ||
269 | if (state->update) | ||
270 | state->saturation = val; | ||
271 | ctrl->value = state->saturation; | ||
272 | break; | ||
273 | case V4L2_CID_HUE: | ||
274 | if (state->update) | ||
275 | state->hue = val; | ||
276 | ctrl->value = state->hue; | ||
277 | break; | ||
278 | case V4L2_CID_AUTOGAIN: | ||
279 | if (state->update) | ||
280 | state->auto_gain = val & (1<<7) ? 1 : 0; | ||
281 | ctrl->value = state->auto_gain; | ||
282 | break; | ||
283 | case V4L2_CID_COLOR_KILLER: | ||
284 | if (state->update) | ||
285 | state->ckil = (val & 0x03) == 0x03 ? 1 : 0; | ||
286 | ctrl->value = state->ckil; | ||
287 | break; | ||
288 | case V4L2_CID_GAIN: | ||
289 | if (state->update) | ||
290 | state->gain = val; | ||
291 | ctrl->value = state->gain; | ||
292 | break; | ||
293 | case V4L2_CID_CHROMA_GAIN: | ||
294 | if (state->update) | ||
295 | state->cr_gain = val; | ||
296 | ctrl->value = state->cr_gain; | ||
297 | break; | ||
298 | case V4L2_CID_RED_BALANCE: | ||
299 | if (state->update) | ||
300 | state->r_balance = val; | ||
301 | ctrl->value = state->r_balance; | ||
302 | break; | ||
303 | case V4L2_CID_BLUE_BALANCE: | ||
304 | if (state->update) | ||
305 | state->b_balance = val; | ||
306 | ctrl->value = state->b_balance; | ||
307 | break; | ||
308 | default: | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | |||
312 | state->update = 0; | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static int tw2804_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
317 | { | ||
318 | struct wis_tw2804 *dec = to_state(sd); | ||
319 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
320 | s32 reg = 0; | ||
321 | s32 addr = get_ctrl_addr(ctrl->id); | ||
322 | |||
323 | if (addr == -EINVAL) | ||
324 | return -EINVAL; | ||
325 | |||
326 | switch (ctrl->id) { | ||
327 | case V4L2_CID_AUTOGAIN: | ||
328 | reg = read_reg(client, addr, dec->channel); | ||
329 | if (reg > 0) { | ||
330 | if (ctrl->value == 0) | ||
331 | ctrl->value = reg & ~(1<<7); | ||
332 | else | ||
333 | ctrl->value = reg | 1<<7; | ||
334 | } else | ||
335 | return reg; | ||
336 | break; | ||
337 | case V4L2_CID_COLOR_KILLER: | ||
338 | reg = read_reg(client, addr, dec->channel); | ||
339 | if (reg > 0) | ||
340 | ctrl->value = (reg & ~(0x03)) | (ctrl->value == 0 ? 0x02 : 0x03); | ||
341 | else | ||
342 | return reg; | ||
343 | break; | ||
344 | default: | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | ctrl->value = ctrl->value > 255 ? 255 : (ctrl->value < 0 ? 0 : ctrl->value); | ||
349 | reg = write_reg(client, addr, (u8)ctrl->value, ctrl->id == V4L2_CID_GAIN || | ||
350 | ctrl->id == V4L2_CID_CHROMA_GAIN || | ||
351 | ctrl->id == V4L2_CID_RED_BALANCE || | ||
352 | ctrl->id == V4L2_CID_BLUE_BALANCE ? 0 : dec->channel); | ||
353 | |||
354 | if (reg < 0) { | ||
355 | v4l2_err(&dec->sd, "Can`t set_ctrl value:id=%d;value=%d\n", ctrl->id, ctrl->value); | ||
356 | return reg; | ||
357 | } | ||
358 | |||
359 | dec->update = 1; | ||
360 | return tw2804_g_ctrl(sd, ctrl); | ||
361 | } | ||
362 | |||
363 | static int tw2804_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) | ||
364 | { | ||
365 | struct wis_tw2804 *dec = to_state(sd); | ||
366 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
367 | |||
368 | u8 regs[] = { | ||
369 | 0x01, norm&V4L2_STD_NTSC ? 0xc4 : 0x84, | ||
370 | 0x09, norm&V4L2_STD_NTSC ? 0x07 : 0x04, | ||
371 | 0x0a, norm&V4L2_STD_NTSC ? 0xf0 : 0x20, | ||
372 | 0x0b, norm&V4L2_STD_NTSC ? 0x07 : 0x04, | ||
373 | 0x0c, norm&V4L2_STD_NTSC ? 0xf0 : 0x20, | ||
374 | 0x0d, norm&V4L2_STD_NTSC ? 0x40 : 0x4a, | ||
375 | 0x16, norm&V4L2_STD_NTSC ? 0x00 : 0x40, | ||
376 | 0x17, norm&V4L2_STD_NTSC ? 0x00 : 0x40, | ||
377 | 0x20, norm&V4L2_STD_NTSC ? 0x07 : 0x0f, | ||
378 | 0x21, norm&V4L2_STD_NTSC ? 0x07 : 0x0f, | ||
379 | 0xff, 0xff, | ||
380 | }; | ||
381 | write_regs(client, regs, dec->channel); | ||
382 | dec->norm = norm; | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static const struct v4l2_subdev_core_ops tw2804_core_ops = { | ||
387 | .log_status = tw2804_log_status, | ||
388 | .g_ctrl = tw2804_g_ctrl, | ||
389 | .s_ctrl = tw2804_s_ctrl, | ||
390 | .queryctrl = tw2804_queryctrl, | ||
391 | .s_std = tw2804_s_std, | ||
392 | }; | ||
393 | |||
394 | static int tw2804_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output, | ||
395 | u32 config) | ||
396 | { | ||
397 | struct wis_tw2804 *dec = to_state(sd); | ||
398 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
399 | s32 reg = 0; | ||
400 | |||
401 | if (0 > input || input > 1) | ||
402 | return -EINVAL; | ||
403 | |||
404 | if (input == dec->input && !dec->update) | ||
405 | return 0; | ||
406 | |||
407 | reg = read_reg(client, 0x22, dec->channel); | ||
408 | |||
409 | if (reg >= 0) { | ||
410 | if (input == 0) | ||
411 | reg &= ~(1<<2); | ||
412 | else | ||
413 | reg |= 1<<2; | ||
414 | reg = write_reg(client, 0x22, (u8)reg, dec->channel); | ||
415 | } | ||
416 | |||
417 | if (reg >= 0) { | ||
418 | dec->input = input; | ||
419 | dec->update = 0; | ||
420 | } else | ||
421 | return reg; | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int tw2804_s_mbus_fmt(struct v4l2_subdev *sd, | ||
426 | struct v4l2_mbus_framefmt *fmt) | ||
427 | { | ||
428 | /*TODO need select between 3fmt: | ||
429 | * bt_656, | ||
430 | * bt_601_8bit, | ||
431 | * bt_656_dual, | ||
432 | */ | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | int tw2804_s_stream(struct v4l2_subdev *sd, int enable) | ||
437 | { | ||
438 | struct wis_tw2804 *dec = to_state(sd); | ||
439 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
440 | u32 reg = read_reg(client, 0x78, 0); | ||
441 | |||
442 | if (enable == 1) | ||
443 | write_reg(client, 0x78, reg & ~(1<<dec->channel), 0); | ||
444 | else | ||
445 | write_reg(client, 0x78, reg | (1<<dec->channel), 0); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static const struct v4l2_subdev_video_ops tw2804_video_ops = { | ||
451 | .s_routing = tw2804_s_video_routing, | ||
452 | .s_mbus_fmt = tw2804_s_mbus_fmt, | ||
453 | .s_stream = tw2804_s_stream, | ||
454 | }; | ||
455 | |||
456 | static const struct v4l2_subdev_ops tw2804_ops = { | ||
457 | .core = &tw2804_core_ops, | ||
458 | .video = &tw2804_video_ops, | ||
459 | }; | ||
460 | |||
461 | static int wis_tw2804_command(struct i2c_client *client, | 122 | static int wis_tw2804_command(struct i2c_client *client, |
462 | unsigned int cmd, void *arg) | 123 | unsigned int cmd, void *arg) |
463 | { | 124 | { |
464 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 125 | struct wis_tw2804 *dec = i2c_get_clientdata(client); |
465 | struct wis_tw2804 *dec = to_state(sd); | ||
466 | int *input; | ||
467 | 126 | ||
468 | if (cmd == DECODER_SET_CHANNEL) { | 127 | if (cmd == DECODER_SET_CHANNEL) { |
469 | input = arg; | 128 | int *input = arg; |
470 | 129 | ||
471 | if (*input < 0 || *input > 3) { | 130 | if (*input < 0 || *input > 3) { |
472 | printk(KERN_ERR "wis-tw2804: channel %d is not " | 131 | printk(KERN_ERR "wis-tw2804: channel %d is not " |
@@ -495,6 +154,139 @@ static int wis_tw2804_command(struct i2c_client *client, | |||
495 | "channel number is set\n", cmd); | 154 | "channel number is set\n", cmd); |
496 | return 0; | 155 | return 0; |
497 | } | 156 | } |
157 | |||
158 | switch (cmd) { | ||
159 | case VIDIOC_S_STD: | ||
160 | { | ||
161 | v4l2_std_id *input = arg; | ||
162 | u8 regs[] = { | ||
163 | 0x01, *input & V4L2_STD_NTSC ? 0xc4 : 0x84, | ||
164 | 0x09, *input & V4L2_STD_NTSC ? 0x07 : 0x04, | ||
165 | 0x0a, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, | ||
166 | 0x0b, *input & V4L2_STD_NTSC ? 0x07 : 0x04, | ||
167 | 0x0c, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, | ||
168 | 0x0d, *input & V4L2_STD_NTSC ? 0x40 : 0x4a, | ||
169 | 0x16, *input & V4L2_STD_NTSC ? 0x00 : 0x40, | ||
170 | 0x17, *input & V4L2_STD_NTSC ? 0x00 : 0x40, | ||
171 | 0x20, *input & V4L2_STD_NTSC ? 0x07 : 0x0f, | ||
172 | 0x21, *input & V4L2_STD_NTSC ? 0x07 : 0x0f, | ||
173 | 0xff, 0xff, | ||
174 | }; | ||
175 | write_regs(client, regs, dec->channel); | ||
176 | dec->norm = *input; | ||
177 | break; | ||
178 | } | ||
179 | case VIDIOC_QUERYCTRL: | ||
180 | { | ||
181 | struct v4l2_queryctrl *ctrl = arg; | ||
182 | |||
183 | switch (ctrl->id) { | ||
184 | case V4L2_CID_BRIGHTNESS: | ||
185 | ctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
186 | strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); | ||
187 | ctrl->minimum = 0; | ||
188 | ctrl->maximum = 255; | ||
189 | ctrl->step = 1; | ||
190 | ctrl->default_value = 128; | ||
191 | ctrl->flags = 0; | ||
192 | break; | ||
193 | case V4L2_CID_CONTRAST: | ||
194 | ctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
195 | strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); | ||
196 | ctrl->minimum = 0; | ||
197 | ctrl->maximum = 255; | ||
198 | ctrl->step = 1; | ||
199 | ctrl->default_value = 128; | ||
200 | ctrl->flags = 0; | ||
201 | break; | ||
202 | case V4L2_CID_SATURATION: | ||
203 | ctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
204 | strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); | ||
205 | ctrl->minimum = 0; | ||
206 | ctrl->maximum = 255; | ||
207 | ctrl->step = 1; | ||
208 | ctrl->default_value = 128; | ||
209 | ctrl->flags = 0; | ||
210 | break; | ||
211 | case V4L2_CID_HUE: | ||
212 | ctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
213 | strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); | ||
214 | ctrl->minimum = 0; | ||
215 | ctrl->maximum = 255; | ||
216 | ctrl->step = 1; | ||
217 | ctrl->default_value = 128; | ||
218 | ctrl->flags = 0; | ||
219 | break; | ||
220 | } | ||
221 | break; | ||
222 | } | ||
223 | case VIDIOC_S_CTRL: | ||
224 | { | ||
225 | struct v4l2_control *ctrl = arg; | ||
226 | |||
227 | switch (ctrl->id) { | ||
228 | case V4L2_CID_BRIGHTNESS: | ||
229 | if (ctrl->value > 255) | ||
230 | dec->brightness = 255; | ||
231 | else if (ctrl->value < 0) | ||
232 | dec->brightness = 0; | ||
233 | else | ||
234 | dec->brightness = ctrl->value; | ||
235 | write_reg(client, 0x12, dec->brightness, dec->channel); | ||
236 | break; | ||
237 | case V4L2_CID_CONTRAST: | ||
238 | if (ctrl->value > 255) | ||
239 | dec->contrast = 255; | ||
240 | else if (ctrl->value < 0) | ||
241 | dec->contrast = 0; | ||
242 | else | ||
243 | dec->contrast = ctrl->value; | ||
244 | write_reg(client, 0x11, dec->contrast, dec->channel); | ||
245 | break; | ||
246 | case V4L2_CID_SATURATION: | ||
247 | if (ctrl->value > 255) | ||
248 | dec->saturation = 255; | ||
249 | else if (ctrl->value < 0) | ||
250 | dec->saturation = 0; | ||
251 | else | ||
252 | dec->saturation = ctrl->value; | ||
253 | write_reg(client, 0x10, dec->saturation, dec->channel); | ||
254 | break; | ||
255 | case V4L2_CID_HUE: | ||
256 | if (ctrl->value > 255) | ||
257 | dec->hue = 255; | ||
258 | else if (ctrl->value < 0) | ||
259 | dec->hue = 0; | ||
260 | else | ||
261 | dec->hue = ctrl->value; | ||
262 | write_reg(client, 0x0f, dec->hue, dec->channel); | ||
263 | break; | ||
264 | } | ||
265 | break; | ||
266 | } | ||
267 | case VIDIOC_G_CTRL: | ||
268 | { | ||
269 | struct v4l2_control *ctrl = arg; | ||
270 | |||
271 | switch (ctrl->id) { | ||
272 | case V4L2_CID_BRIGHTNESS: | ||
273 | ctrl->value = dec->brightness; | ||
274 | break; | ||
275 | case V4L2_CID_CONTRAST: | ||
276 | ctrl->value = dec->contrast; | ||
277 | break; | ||
278 | case V4L2_CID_SATURATION: | ||
279 | ctrl->value = dec->saturation; | ||
280 | break; | ||
281 | case V4L2_CID_HUE: | ||
282 | ctrl->value = dec->hue; | ||
283 | break; | ||
284 | } | ||
285 | break; | ||
286 | } | ||
287 | default: | ||
288 | break; | ||
289 | } | ||
498 | return 0; | 290 | return 0; |
499 | } | 291 | } |
500 | 292 | ||
@@ -503,28 +295,21 @@ static int wis_tw2804_probe(struct i2c_client *client, | |||
503 | { | 295 | { |
504 | struct i2c_adapter *adapter = client->adapter; | 296 | struct i2c_adapter *adapter = client->adapter; |
505 | struct wis_tw2804 *dec; | 297 | struct wis_tw2804 *dec; |
506 | struct v4l2_subdev *sd; | ||
507 | 298 | ||
508 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 299 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
509 | return -ENODEV; | 300 | return -ENODEV; |
510 | 301 | ||
511 | dec = kzalloc(sizeof(struct wis_tw2804), GFP_KERNEL); | 302 | dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL); |
512 | |||
513 | if (dec == NULL) | 303 | if (dec == NULL) |
514 | return -ENOMEM; | 304 | return -ENOMEM; |
515 | sd = &dec->sd; | 305 | |
516 | dec->update = 1; | ||
517 | dec->channel = -1; | 306 | dec->channel = -1; |
518 | dec->norm = V4L2_STD_NTSC; | 307 | dec->norm = V4L2_STD_NTSC; |
519 | dec->brightness = 128; | 308 | dec->brightness = 128; |
520 | dec->contrast = 128; | 309 | dec->contrast = 128; |
521 | dec->saturation = 128; | 310 | dec->saturation = 128; |
522 | dec->hue = 128; | 311 | dec->hue = 128; |
523 | dec->gain = 128; | 312 | i2c_set_clientdata(client, dec); |
524 | dec->cr_gain = 128; | ||
525 | dec->b_balance = 122; | ||
526 | dec->r_balance = 122; | ||
527 | v4l2_i2c_subdev_init(sd, client, &tw2804_ops); | ||
528 | 313 | ||
529 | printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n", | 314 | printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n", |
530 | client->addr, adapter->name); | 315 | client->addr, adapter->name); |
@@ -534,10 +319,9 @@ static int wis_tw2804_probe(struct i2c_client *client, | |||
534 | 319 | ||
535 | static int wis_tw2804_remove(struct i2c_client *client) | 320 | static int wis_tw2804_remove(struct i2c_client *client) |
536 | { | 321 | { |
537 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 322 | struct wis_tw2804 *dec = i2c_get_clientdata(client); |
538 | 323 | ||
539 | v4l2_device_unregister_subdev(sd); | 324 | kfree(dec); |
540 | kfree(to_state(sd)); | ||
541 | return 0; | 325 | return 0; |
542 | } | 326 | } |
543 | 327 | ||