Linux 4.16.11
[linux/fpc-iii.git] / drivers / media / i2c / ths7303.c
blob8206bf7a5a8fa4b3e6950465ae9b83dc85afe928
1 /*
2 * ths7303/53- THS7303/53 Video Amplifier driver
4 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
5 * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
7 * Author: Chaithrika U S <chaithrika@ti.com>
9 * Contributors:
10 * Hans Verkuil <hans.verkuil@cisco.com>
11 * Lad, Prabhakar <prabhakar.lad@ti.com>
12 * Martin Bugge <marbugge@cisco.com>
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation version 2.
18 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
19 * kind, whether express or implied; without even the implied warranty
20 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
24 #include <linux/i2c.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
28 #include <media/i2c/ths7303.h>
29 #include <media/v4l2-device.h>
31 #define THS7303_CHANNEL_1 1
32 #define THS7303_CHANNEL_2 2
33 #define THS7303_CHANNEL_3 3
35 struct ths7303_state {
36 struct v4l2_subdev sd;
37 const struct ths7303_platform_data *pdata;
38 struct v4l2_bt_timings bt;
39 int std_id;
40 int stream_on;
43 enum ths7303_filter_mode {
44 THS7303_FILTER_MODE_480I_576I,
45 THS7303_FILTER_MODE_480P_576P,
46 THS7303_FILTER_MODE_720P_1080I,
47 THS7303_FILTER_MODE_1080P,
48 THS7303_FILTER_MODE_DISABLE
51 MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
52 MODULE_AUTHOR("Chaithrika U S");
53 MODULE_LICENSE("GPL");
55 static inline struct ths7303_state *to_state(struct v4l2_subdev *sd)
57 return container_of(sd, struct ths7303_state, sd);
60 static int ths7303_read(struct v4l2_subdev *sd, u8 reg)
62 struct i2c_client *client = v4l2_get_subdevdata(sd);
64 return i2c_smbus_read_byte_data(client, reg);
67 static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
69 struct i2c_client *client = v4l2_get_subdevdata(sd);
70 int ret;
71 int i;
73 for (i = 0; i < 3; i++) {
74 ret = i2c_smbus_write_byte_data(client, reg, val);
75 if (ret == 0)
76 return 0;
78 return ret;
81 /* following function is used to set ths7303 */
82 static int ths7303_setval(struct v4l2_subdev *sd,
83 enum ths7303_filter_mode mode)
85 struct i2c_client *client = v4l2_get_subdevdata(sd);
86 struct ths7303_state *state = to_state(sd);
87 const struct ths7303_platform_data *pdata = state->pdata;
88 u8 val, sel = 0;
89 int err, disable = 0;
91 if (!client)
92 return -EINVAL;
94 switch (mode) {
95 case THS7303_FILTER_MODE_1080P:
96 sel = 0x3; /*1080p and SXGA/UXGA */
97 break;
98 case THS7303_FILTER_MODE_720P_1080I:
99 sel = 0x2; /*720p, 1080i and SVGA/XGA */
100 break;
101 case THS7303_FILTER_MODE_480P_576P:
102 sel = 0x1; /* EDTV 480p/576p and VGA */
103 break;
104 case THS7303_FILTER_MODE_480I_576I:
105 sel = 0x0; /* SDTV, S-Video, 480i/576i */
106 break;
107 default:
108 /* disable all channels */
109 disable = 1;
112 val = (sel << 6) | (sel << 3);
113 if (!disable)
114 val |= (pdata->ch_1 & 0x27);
115 err = ths7303_write(sd, THS7303_CHANNEL_1, val);
116 if (err)
117 goto out;
119 val = (sel << 6) | (sel << 3);
120 if (!disable)
121 val |= (pdata->ch_2 & 0x27);
122 err = ths7303_write(sd, THS7303_CHANNEL_2, val);
123 if (err)
124 goto out;
126 val = (sel << 6) | (sel << 3);
127 if (!disable)
128 val |= (pdata->ch_3 & 0x27);
129 err = ths7303_write(sd, THS7303_CHANNEL_3, val);
130 if (err)
131 goto out;
133 return 0;
134 out:
135 pr_info("write byte data failed\n");
136 return err;
139 static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
141 struct ths7303_state *state = to_state(sd);
143 if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
144 state->std_id = 1;
145 state->bt.pixelclock = 0;
146 return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
149 return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
152 static int ths7303_config(struct v4l2_subdev *sd)
154 struct ths7303_state *state = to_state(sd);
155 int res;
157 if (!state->stream_on) {
158 ths7303_write(sd, THS7303_CHANNEL_1,
159 (ths7303_read(sd, THS7303_CHANNEL_1) & 0xf8) |
160 0x00);
161 ths7303_write(sd, THS7303_CHANNEL_2,
162 (ths7303_read(sd, THS7303_CHANNEL_2) & 0xf8) |
163 0x00);
164 ths7303_write(sd, THS7303_CHANNEL_3,
165 (ths7303_read(sd, THS7303_CHANNEL_3) & 0xf8) |
166 0x00);
167 return 0;
170 if (state->bt.pixelclock > 120000000)
171 res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
172 else if (state->bt.pixelclock > 70000000)
173 res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
174 else if (state->bt.pixelclock > 20000000)
175 res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
176 else if (state->std_id)
177 res = ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
178 else
179 /* disable all channels */
180 res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
182 return res;
186 static int ths7303_s_stream(struct v4l2_subdev *sd, int enable)
188 struct ths7303_state *state = to_state(sd);
190 state->stream_on = enable;
192 return ths7303_config(sd);
195 /* for setting filter for HD output */
196 static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
197 struct v4l2_dv_timings *dv_timings)
199 struct ths7303_state *state = to_state(sd);
201 if (!dv_timings || dv_timings->type != V4L2_DV_BT_656_1120)
202 return -EINVAL;
204 state->bt = dv_timings->bt;
205 state->std_id = 0;
207 return ths7303_config(sd);
210 static const struct v4l2_subdev_video_ops ths7303_video_ops = {
211 .s_stream = ths7303_s_stream,
212 .s_std_output = ths7303_s_std_output,
213 .s_dv_timings = ths7303_s_dv_timings,
216 #ifdef CONFIG_VIDEO_ADV_DEBUG
218 static int ths7303_g_register(struct v4l2_subdev *sd,
219 struct v4l2_dbg_register *reg)
221 reg->size = 1;
222 reg->val = ths7303_read(sd, reg->reg);
223 return 0;
226 static int ths7303_s_register(struct v4l2_subdev *sd,
227 const struct v4l2_dbg_register *reg)
229 ths7303_write(sd, reg->reg, reg->val);
230 return 0;
232 #endif
234 static const char * const stc_lpf_sel_txt[4] = {
235 "500-kHz Filter",
236 "2.5-MHz Filter",
237 "5-MHz Filter",
238 "5-MHz Filter",
241 static const char * const in_mux_sel_txt[2] = {
242 "Input A Select",
243 "Input B Select",
246 static const char * const lpf_freq_sel_txt[4] = {
247 "9-MHz LPF",
248 "16-MHz LPF",
249 "35-MHz LPF",
250 "Bypass LPF",
253 static const char * const in_bias_sel_dis_cont_txt[8] = {
254 "Disable Channel",
255 "Mute Function - No Output",
256 "DC Bias Select",
257 "DC Bias + 250 mV Offset Select",
258 "AC Bias Select",
259 "Sync Tip Clamp with low bias",
260 "Sync Tip Clamp with mid bias",
261 "Sync Tip Clamp with high bias",
264 static void ths7303_log_channel_status(struct v4l2_subdev *sd, u8 reg)
266 u8 val = ths7303_read(sd, reg);
268 if ((val & 0x7) == 0) {
269 v4l2_info(sd, "Channel %d Off\n", reg);
270 return;
273 v4l2_info(sd, "Channel %d On\n", reg);
274 v4l2_info(sd, " value 0x%x\n", val);
275 v4l2_info(sd, " %s\n", stc_lpf_sel_txt[(val >> 6) & 0x3]);
276 v4l2_info(sd, " %s\n", in_mux_sel_txt[(val >> 5) & 0x1]);
277 v4l2_info(sd, " %s\n", lpf_freq_sel_txt[(val >> 3) & 0x3]);
278 v4l2_info(sd, " %s\n", in_bias_sel_dis_cont_txt[(val >> 0) & 0x7]);
281 static int ths7303_log_status(struct v4l2_subdev *sd)
283 struct ths7303_state *state = to_state(sd);
285 v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off");
287 if (state->bt.pixelclock) {
288 struct v4l2_bt_timings *bt = &state->bt;
289 u32 frame_width, frame_height;
291 frame_width = V4L2_DV_BT_FRAME_WIDTH(bt);
292 frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt);
293 v4l2_info(sd,
294 "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n",
295 bt->width, bt->height, bt->interlaced ? "i" : "p",
296 (frame_height * frame_width) > 0 ?
297 (int)bt->pixelclock /
298 (frame_height * frame_width) : 0,
299 frame_width, frame_height,
300 (int)bt->pixelclock, bt->polarities);
301 } else {
302 v4l2_info(sd, "no timings set\n");
305 ths7303_log_channel_status(sd, THS7303_CHANNEL_1);
306 ths7303_log_channel_status(sd, THS7303_CHANNEL_2);
307 ths7303_log_channel_status(sd, THS7303_CHANNEL_3);
309 return 0;
312 static const struct v4l2_subdev_core_ops ths7303_core_ops = {
313 .log_status = ths7303_log_status,
314 #ifdef CONFIG_VIDEO_ADV_DEBUG
315 .g_register = ths7303_g_register,
316 .s_register = ths7303_s_register,
317 #endif
320 static const struct v4l2_subdev_ops ths7303_ops = {
321 .core = &ths7303_core_ops,
322 .video = &ths7303_video_ops,
325 static int ths7303_probe(struct i2c_client *client,
326 const struct i2c_device_id *id)
328 struct ths7303_platform_data *pdata = client->dev.platform_data;
329 struct ths7303_state *state;
330 struct v4l2_subdev *sd;
332 if (pdata == NULL) {
333 dev_err(&client->dev, "No platform data\n");
334 return -EINVAL;
337 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
338 return -ENODEV;
340 v4l_info(client, "chip found @ 0x%x (%s)\n",
341 client->addr << 1, client->adapter->name);
343 state = devm_kzalloc(&client->dev, sizeof(struct ths7303_state),
344 GFP_KERNEL);
345 if (!state)
346 return -ENOMEM;
348 state->pdata = pdata;
349 sd = &state->sd;
350 v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
352 /* set to default 480I_576I filter mode */
353 if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) {
354 v4l_err(client, "Setting to 480I_576I filter mode failed!\n");
355 return -EINVAL;
358 return 0;
361 static int ths7303_remove(struct i2c_client *client)
363 struct v4l2_subdev *sd = i2c_get_clientdata(client);
365 v4l2_device_unregister_subdev(sd);
367 return 0;
370 static const struct i2c_device_id ths7303_id[] = {
371 {"ths7303", 0},
372 {"ths7353", 0},
376 MODULE_DEVICE_TABLE(i2c, ths7303_id);
378 static struct i2c_driver ths7303_driver = {
379 .driver = {
380 .name = "ths73x3",
382 .probe = ths7303_probe,
383 .remove = ths7303_remove,
384 .id_table = ths7303_id,
387 module_i2c_driver(ths7303_driver);