GNU Linux-libre 4.14.324-gnu1
[releases.git] / drivers / media / i2c / tw2804.c
1 /*
2  * Copyright (C) 2005-2006 Micronas USA Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License (Version 2) as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <linux/videodev2.h>
18 #include <linux/ioctl.h>
19 #include <linux/slab.h>
20 #include <media/v4l2-subdev.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-ctrls.h>
23
24 #define TW2804_REG_AUTOGAIN             0x02
25 #define TW2804_REG_HUE                  0x0f
26 #define TW2804_REG_SATURATION           0x10
27 #define TW2804_REG_CONTRAST             0x11
28 #define TW2804_REG_BRIGHTNESS           0x12
29 #define TW2804_REG_COLOR_KILLER         0x14
30 #define TW2804_REG_GAIN                 0x3c
31 #define TW2804_REG_CHROMA_GAIN          0x3d
32 #define TW2804_REG_BLUE_BALANCE         0x3e
33 #define TW2804_REG_RED_BALANCE          0x3f
34
35 struct tw2804 {
36         struct v4l2_subdev sd;
37         struct v4l2_ctrl_handler hdl;
38         u8 channel:2;
39         u8 input:1;
40         int norm;
41 };
42
43 static const u8 global_registers[] = {
44         0x39, 0x00,
45         0x3a, 0xff,
46         0x3b, 0x84,
47         0x3c, 0x80,
48         0x3d, 0x80,
49         0x3e, 0x82,
50         0x3f, 0x82,
51         0x78, 0x00,
52         0xff, 0xff, /* Terminator (reg 0xff does not exist) */
53 };
54
55 static const u8 channel_registers[] = {
56         0x01, 0xc4,
57         0x02, 0xa5,
58         0x03, 0x20,
59         0x04, 0xd0,
60         0x05, 0x20,
61         0x06, 0xd0,
62         0x07, 0x88,
63         0x08, 0x20,
64         0x09, 0x07,
65         0x0a, 0xf0,
66         0x0b, 0x07,
67         0x0c, 0xf0,
68         0x0d, 0x40,
69         0x0e, 0xd2,
70         0x0f, 0x80,
71         0x10, 0x80,
72         0x11, 0x80,
73         0x12, 0x80,
74         0x13, 0x1f,
75         0x14, 0x00,
76         0x15, 0x00,
77         0x16, 0x00,
78         0x17, 0x00,
79         0x18, 0xff,
80         0x19, 0xff,
81         0x1a, 0xff,
82         0x1b, 0xff,
83         0x1c, 0xff,
84         0x1d, 0xff,
85         0x1e, 0xff,
86         0x1f, 0xff,
87         0x20, 0x07,
88         0x21, 0x07,
89         0x22, 0x00,
90         0x23, 0x91,
91         0x24, 0x51,
92         0x25, 0x03,
93         0x26, 0x00,
94         0x27, 0x00,
95         0x28, 0x00,
96         0x29, 0x00,
97         0x2a, 0x00,
98         0x2b, 0x00,
99         0x2c, 0x00,
100         0x2d, 0x00,
101         0x2e, 0x00,
102         0x2f, 0x00,
103         0x30, 0x00,
104         0x31, 0x00,
105         0x32, 0x00,
106         0x33, 0x00,
107         0x34, 0x00,
108         0x35, 0x00,
109         0x36, 0x00,
110         0x37, 0x00,
111         0xff, 0xff, /* Terminator (reg 0xff does not exist) */
112 };
113
114 static int write_reg(struct i2c_client *client, u8 reg, u8 value, u8 channel)
115 {
116         return i2c_smbus_write_byte_data(client, reg | (channel << 6), value);
117 }
118
119 static int write_regs(struct i2c_client *client, const u8 *regs, u8 channel)
120 {
121         int ret;
122         int i;
123
124         for (i = 0; regs[i] != 0xff; i += 2) {
125                 ret = i2c_smbus_write_byte_data(client,
126                                 regs[i] | (channel << 6), regs[i + 1]);
127                 if (ret < 0)
128                         return ret;
129         }
130         return 0;
131 }
132
133 static int read_reg(struct i2c_client *client, u8 reg, u8 channel)
134 {
135         return i2c_smbus_read_byte_data(client, (reg) | (channel << 6));
136 }
137
138 static inline struct tw2804 *to_state(struct v4l2_subdev *sd)
139 {
140         return container_of(sd, struct tw2804, sd);
141 }
142
143 static inline struct tw2804 *to_state_from_ctrl(struct v4l2_ctrl *ctrl)
144 {
145         return container_of(ctrl->handler, struct tw2804, hdl);
146 }
147
148 static int tw2804_log_status(struct v4l2_subdev *sd)
149 {
150         struct tw2804 *state = to_state(sd);
151
152         v4l2_info(sd, "Standard: %s\n",
153                         state->norm & V4L2_STD_525_60 ? "60 Hz" : "50 Hz");
154         v4l2_info(sd, "Channel: %d\n", state->channel);
155         v4l2_info(sd, "Input: %d\n", state->input);
156         return v4l2_ctrl_subdev_log_status(sd);
157 }
158
159 /*
160  * These volatile controls are needed because all four channels share
161  * these controls. So a change made to them through one channel would
162  * require another channel to be updated.
163  *
164  * Normally this would have been done in a different way, but since the one
165  * board that uses this driver sees this single chip as if it was on four
166  * different i2c adapters (each adapter belonging to a separate instance of
167  * the same USB driver) there is no reliable method that I have found to let
168  * the instances know about each other.
169  *
170  * So implementing these global registers as volatile is the best we can do.
171  */
172 static int tw2804_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
173 {
174         struct tw2804 *state = to_state_from_ctrl(ctrl);
175         struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
176
177         switch (ctrl->id) {
178         case V4L2_CID_GAIN:
179                 ctrl->val = read_reg(client, TW2804_REG_GAIN, 0);
180                 return 0;
181
182         case V4L2_CID_CHROMA_GAIN:
183                 ctrl->val = read_reg(client, TW2804_REG_CHROMA_GAIN, 0);
184                 return 0;
185
186         case V4L2_CID_BLUE_BALANCE:
187                 ctrl->val = read_reg(client, TW2804_REG_BLUE_BALANCE, 0);
188                 return 0;
189
190         case V4L2_CID_RED_BALANCE:
191                 ctrl->val = read_reg(client, TW2804_REG_RED_BALANCE, 0);
192                 return 0;
193         }
194         return 0;
195 }
196
197 static int tw2804_s_ctrl(struct v4l2_ctrl *ctrl)
198 {
199         struct tw2804 *state = to_state_from_ctrl(ctrl);
200         struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
201         int addr;
202         int reg;
203
204         switch (ctrl->id) {
205         case V4L2_CID_AUTOGAIN:
206                 addr = TW2804_REG_AUTOGAIN;
207                 reg = read_reg(client, addr, state->channel);
208                 if (reg < 0)
209                         return reg;
210                 if (ctrl->val == 0)
211                         reg &= ~(1 << 7);
212                 else
213                         reg |= 1 << 7;
214                 return write_reg(client, addr, reg, state->channel);
215
216         case V4L2_CID_COLOR_KILLER:
217                 addr = TW2804_REG_COLOR_KILLER;
218                 reg = read_reg(client, addr, state->channel);
219                 if (reg < 0)
220                         return reg;
221                 reg = (reg & ~(0x03)) | (ctrl->val == 0 ? 0x02 : 0x03);
222                 return write_reg(client, addr, reg, state->channel);
223
224         case V4L2_CID_GAIN:
225                 return write_reg(client, TW2804_REG_GAIN, ctrl->val, 0);
226
227         case V4L2_CID_CHROMA_GAIN:
228                 return write_reg(client, TW2804_REG_CHROMA_GAIN, ctrl->val, 0);
229
230         case V4L2_CID_BLUE_BALANCE:
231                 return write_reg(client, TW2804_REG_BLUE_BALANCE, ctrl->val, 0);
232
233         case V4L2_CID_RED_BALANCE:
234                 return write_reg(client, TW2804_REG_RED_BALANCE, ctrl->val, 0);
235
236         case V4L2_CID_BRIGHTNESS:
237                 return write_reg(client, TW2804_REG_BRIGHTNESS,
238                                 ctrl->val, state->channel);
239
240         case V4L2_CID_CONTRAST:
241                 return write_reg(client, TW2804_REG_CONTRAST,
242                                 ctrl->val, state->channel);
243
244         case V4L2_CID_SATURATION:
245                 return write_reg(client, TW2804_REG_SATURATION,
246                                 ctrl->val, state->channel);
247
248         case V4L2_CID_HUE:
249                 return write_reg(client, TW2804_REG_HUE,
250                                 ctrl->val, state->channel);
251
252         default:
253                 break;
254         }
255         return -EINVAL;
256 }
257
258 static int tw2804_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
259 {
260         struct tw2804 *dec = to_state(sd);
261         struct i2c_client *client = v4l2_get_subdevdata(sd);
262         bool is_60hz = norm & V4L2_STD_525_60;
263         u8 regs[] = {
264                 0x01, is_60hz ? 0xc4 : 0x84,
265                 0x09, is_60hz ? 0x07 : 0x04,
266                 0x0a, is_60hz ? 0xf0 : 0x20,
267                 0x0b, is_60hz ? 0x07 : 0x04,
268                 0x0c, is_60hz ? 0xf0 : 0x20,
269                 0x0d, is_60hz ? 0x40 : 0x4a,
270                 0x16, is_60hz ? 0x00 : 0x40,
271                 0x17, is_60hz ? 0x00 : 0x40,
272                 0x20, is_60hz ? 0x07 : 0x0f,
273                 0x21, is_60hz ? 0x07 : 0x0f,
274                 0xff, 0xff,
275         };
276
277         write_regs(client, regs, dec->channel);
278         dec->norm = norm;
279         return 0;
280 }
281
282 static int tw2804_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output,
283         u32 config)
284 {
285         struct tw2804 *dec = to_state(sd);
286         struct i2c_client *client = v4l2_get_subdevdata(sd);
287         int reg;
288
289         if (config && config - 1 != dec->channel) {
290                 if (config > 4) {
291                         dev_err(&client->dev,
292                                 "channel %d is not between 1 and 4!\n", config);
293                         return -EINVAL;
294                 }
295                 dec->channel = config - 1;
296                 dev_dbg(&client->dev, "initializing TW2804 channel %d\n",
297                         dec->channel);
298                 if (dec->channel == 0 &&
299                                 write_regs(client, global_registers, 0) < 0) {
300                         dev_err(&client->dev,
301                                 "error initializing TW2804 global registers\n");
302                         return -EIO;
303                 }
304                 if (write_regs(client, channel_registers, dec->channel) < 0) {
305                         dev_err(&client->dev,
306                                 "error initializing TW2804 channel %d\n",
307                                 dec->channel);
308                         return -EIO;
309                 }
310         }
311
312         if (input > 1)
313                 return -EINVAL;
314
315         if (input == dec->input)
316                 return 0;
317
318         reg = read_reg(client, 0x22, dec->channel);
319
320         if (reg >= 0) {
321                 if (input == 0)
322                         reg &= ~(1 << 2);
323                 else
324                         reg |= 1 << 2;
325                 reg = write_reg(client, 0x22, reg, dec->channel);
326         }
327
328         if (reg >= 0)
329                 dec->input = input;
330         else
331                 return reg;
332         return 0;
333 }
334
335 static const struct v4l2_ctrl_ops tw2804_ctrl_ops = {
336         .g_volatile_ctrl = tw2804_g_volatile_ctrl,
337         .s_ctrl = tw2804_s_ctrl,
338 };
339
340 static const struct v4l2_subdev_video_ops tw2804_video_ops = {
341         .s_std = tw2804_s_std,
342         .s_routing = tw2804_s_video_routing,
343 };
344
345 static const struct v4l2_subdev_core_ops tw2804_core_ops = {
346         .log_status = tw2804_log_status,
347 };
348
349 static const struct v4l2_subdev_ops tw2804_ops = {
350         .core = &tw2804_core_ops,
351         .video = &tw2804_video_ops,
352 };
353
354 static int tw2804_probe(struct i2c_client *client,
355                             const struct i2c_device_id *id)
356 {
357         struct i2c_adapter *adapter = client->adapter;
358         struct tw2804 *state;
359         struct v4l2_subdev *sd;
360         struct v4l2_ctrl *ctrl;
361         int err;
362
363         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
364                 return -ENODEV;
365
366         state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
367         if (state == NULL)
368                 return -ENOMEM;
369         sd = &state->sd;
370         v4l2_i2c_subdev_init(sd, client, &tw2804_ops);
371         state->channel = -1;
372         state->norm = V4L2_STD_NTSC;
373
374         v4l2_ctrl_handler_init(&state->hdl, 10);
375         v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
376                                 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
377         v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
378                                 V4L2_CID_CONTRAST, 0, 255, 1, 128);
379         v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
380                                 V4L2_CID_SATURATION, 0, 255, 1, 128);
381         v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
382                                 V4L2_CID_HUE, 0, 255, 1, 128);
383         v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
384                                 V4L2_CID_COLOR_KILLER, 0, 1, 1, 0);
385         v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
386                                 V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
387         ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
388                                 V4L2_CID_GAIN, 0, 255, 1, 128);
389         if (ctrl)
390                 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
391         ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
392                                 V4L2_CID_CHROMA_GAIN, 0, 255, 1, 128);
393         if (ctrl)
394                 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
395         ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
396                                 V4L2_CID_BLUE_BALANCE, 0, 255, 1, 122);
397         if (ctrl)
398                 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
399         ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops,
400                                 V4L2_CID_RED_BALANCE, 0, 255, 1, 122);
401         if (ctrl)
402                 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
403         sd->ctrl_handler = &state->hdl;
404         err = state->hdl.error;
405         if (err) {
406                 v4l2_ctrl_handler_free(&state->hdl);
407                 return err;
408         }
409
410         v4l_info(client, "chip found @ 0x%02x (%s)\n",
411                         client->addr << 1, client->adapter->name);
412
413         return 0;
414 }
415
416 static int tw2804_remove(struct i2c_client *client)
417 {
418         struct v4l2_subdev *sd = i2c_get_clientdata(client);
419         struct tw2804 *state = to_state(sd);
420
421         v4l2_device_unregister_subdev(sd);
422         v4l2_ctrl_handler_free(&state->hdl);
423         return 0;
424 }
425
426 static const struct i2c_device_id tw2804_id[] = {
427         { "tw2804", 0 },
428         { }
429 };
430 MODULE_DEVICE_TABLE(i2c, tw2804_id);
431
432 static struct i2c_driver tw2804_driver = {
433         .driver = {
434                 .name   = "tw2804",
435         },
436         .probe          = tw2804_probe,
437         .remove         = tw2804_remove,
438         .id_table       = tw2804_id,
439 };
440
441 module_i2c_driver(tw2804_driver);
442
443 MODULE_LICENSE("GPL v2");
444 MODULE_DESCRIPTION("TW2804/TW2802 V4L2 i2c driver");
445 MODULE_AUTHOR("Micronas USA Inc");