| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  |  * ths7303/53- THS7303/53 Video Amplifier driver | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  |  * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Author: Chaithrika U S <chaithrika@ti.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributors: | 
					
						
							|  |  |  |  *     Hans Verkuil <hans.verkuil@cisco.com> | 
					
						
							|  |  |  |  *     Lad, Prabhakar <prabhakar.lad@ti.com> | 
					
						
							|  |  |  |  *     Martin Bugge <marbugge@cisco.com> | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License as | 
					
						
							|  |  |  |  * published by the Free Software Foundation version 2. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed .as is. WITHOUT ANY WARRANTY of any | 
					
						
							|  |  |  |  * kind, whether express or implied; without even the implied warranty | 
					
						
							|  |  |  |  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/i2c.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | #include <linux/slab.h>
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | #include <media/ths7303.h>
 | 
					
						
							|  |  |  | #include <media/v4l2-device.h>
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | #define THS7303_CHANNEL_1	1
 | 
					
						
							|  |  |  | #define THS7303_CHANNEL_2	2
 | 
					
						
							|  |  |  | #define THS7303_CHANNEL_3	3
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | struct ths7303_state { | 
					
						
							|  |  |  | 	struct v4l2_subdev		sd; | 
					
						
							| 
									
										
										
										
											2013-05-25 13:39:36 -03:00
										 |  |  | 	const struct ths7303_platform_data *pdata; | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	struct v4l2_bt_timings		bt; | 
					
						
							|  |  |  | 	int std_id; | 
					
						
							|  |  |  | 	int stream_on; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | enum ths7303_filter_mode { | 
					
						
							|  |  |  | 	THS7303_FILTER_MODE_480I_576I, | 
					
						
							|  |  |  | 	THS7303_FILTER_MODE_480P_576P, | 
					
						
							|  |  |  | 	THS7303_FILTER_MODE_720P_1080I, | 
					
						
							|  |  |  | 	THS7303_FILTER_MODE_1080P, | 
					
						
							|  |  |  | 	THS7303_FILTER_MODE_DISABLE | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | MODULE_DESCRIPTION("TI THS7303 video amplifier driver"); | 
					
						
							|  |  |  | MODULE_AUTHOR("Chaithrika U S"); | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int debug; | 
					
						
							|  |  |  | module_param(debug, int, 0644); | 
					
						
							|  |  |  | MODULE_PARM_DESC(debug, "Debug level 0-1"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | static inline struct ths7303_state *to_state(struct v4l2_subdev *sd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return container_of(sd, struct ths7303_state, sd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_read(struct v4l2_subdev *sd, u8 reg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct i2c_client *client = v4l2_get_subdevdata(sd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return i2c_smbus_read_byte_data(client, reg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct i2c_client *client = v4l2_get_subdevdata(sd); | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 		ret = i2c_smbus_write_byte_data(client, reg, val); | 
					
						
							|  |  |  | 		if (ret == 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | /* following function is used to set ths7303 */ | 
					
						
							| 
									
										
										
										
											2013-11-06 11:40:18 -03:00
										 |  |  | static int ths7303_setval(struct v4l2_subdev *sd, | 
					
						
							|  |  |  | 			  enum ths7303_filter_mode mode) | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	struct i2c_client *client = v4l2_get_subdevdata(sd); | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	struct ths7303_state *state = to_state(sd); | 
					
						
							| 
									
										
										
										
											2013-05-25 13:39:36 -03:00
										 |  |  | 	const struct ths7303_platform_data *pdata = state->pdata; | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	u8 val, sel = 0; | 
					
						
							|  |  |  | 	int err, disable = 0; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	if (!client) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (mode) { | 
					
						
							|  |  |  | 	case THS7303_FILTER_MODE_1080P: | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		sel = 0x3;	/*1080p and SXGA/UXGA */ | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case THS7303_FILTER_MODE_720P_1080I: | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		sel = 0x2;	/*720p, 1080i and SVGA/XGA */ | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case THS7303_FILTER_MODE_480P_576P: | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		sel = 0x1;	/* EDTV 480p/576p and VGA */ | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case THS7303_FILTER_MODE_480I_576I: | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		sel = 0x0;	/* SDTV, S-Video, 480i/576i */ | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		/* disable all channels */ | 
					
						
							|  |  |  | 		disable = 1; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	val = (sel << 6) | (sel << 3); | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	if (!disable) | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		val |= (pdata->ch_1 & 0x27); | 
					
						
							|  |  |  | 	err = ths7303_write(sd, THS7303_CHANNEL_1, val); | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	if (err) | 
					
						
							|  |  |  | 		goto out; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	val = (sel << 6) | (sel << 3); | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	if (!disable) | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		val |= (pdata->ch_2 & 0x27); | 
					
						
							|  |  |  | 	err = ths7303_write(sd, THS7303_CHANNEL_2, val); | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	if (err) | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		goto out; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	val = (sel << 6) | (sel << 3); | 
					
						
							|  |  |  | 	if (!disable) | 
					
						
							|  |  |  | 		val |= (pdata->ch_3 & 0x27); | 
					
						
							|  |  |  | 	err = ths7303_write(sd, THS7303_CHANNEL_3, val); | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	if (err) | 
					
						
							|  |  |  | 		goto out; | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | out: | 
					
						
							|  |  |  | 	pr_info("write byte data failed\n"); | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	struct ths7303_state *state = to_state(sd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) { | 
					
						
							|  |  |  | 		state->std_id = 1; | 
					
						
							|  |  |  | 		state->bt.pixelclock = 0; | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I); | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE); | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | static int ths7303_config(struct v4l2_subdev *sd) | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	struct ths7303_state *state = to_state(sd); | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!state->stream_on) { | 
					
						
							|  |  |  | 		ths7303_write(sd, THS7303_CHANNEL_1, | 
					
						
							|  |  |  | 			      (ths7303_read(sd, THS7303_CHANNEL_1) & 0xf8) | | 
					
						
							|  |  |  | 			      0x00); | 
					
						
							|  |  |  | 		ths7303_write(sd, THS7303_CHANNEL_2, | 
					
						
							|  |  |  | 			      (ths7303_read(sd, THS7303_CHANNEL_2) & 0xf8) | | 
					
						
							|  |  |  | 			      0x00); | 
					
						
							|  |  |  | 		ths7303_write(sd, THS7303_CHANNEL_3, | 
					
						
							|  |  |  | 			      (ths7303_read(sd, THS7303_CHANNEL_3) & 0xf8) | | 
					
						
							|  |  |  | 			      0x00); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	if (state->bt.pixelclock > 120000000) | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P); | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	else if (state->bt.pixelclock > 70000000) | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I); | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	else if (state->bt.pixelclock > 20000000) | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 		res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P); | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	else if (state->std_id) | 
					
						
							|  |  |  | 		res = ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I); | 
					
						
							| 
									
										
										
										
											2012-10-01 11:46:35 -03:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		/* disable all channels */ | 
					
						
							|  |  |  | 		res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_s_stream(struct v4l2_subdev *sd, int enable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ths7303_state *state = to_state(sd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	state->stream_on = enable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ths7303_config(sd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* for setting filter for HD output */ | 
					
						
							|  |  |  | static int ths7303_s_dv_timings(struct v4l2_subdev *sd, | 
					
						
							|  |  |  | 			       struct v4l2_dv_timings *dv_timings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ths7303_state *state = to_state(sd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!dv_timings || dv_timings->type != V4L2_DV_BT_656_1120) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	state->bt = dv_timings->bt; | 
					
						
							|  |  |  | 	state->std_id = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ths7303_config(sd); | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct v4l2_subdev_video_ops ths7303_video_ops = { | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	.s_stream	= ths7303_s_stream, | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	.s_std_output	= ths7303_s_std_output, | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	.s_dv_timings   = ths7303_s_dv_timings, | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | #ifdef CONFIG_VIDEO_ADV_DEBUG
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_g_register(struct v4l2_subdev *sd, | 
					
						
							|  |  |  | 			      struct v4l2_dbg_register *reg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	reg->size = 1; | 
					
						
							|  |  |  | 	reg->val = ths7303_read(sd, reg->reg); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_s_register(struct v4l2_subdev *sd, | 
					
						
							| 
									
										
										
										
											2013-03-24 08:28:46 -03:00
										 |  |  | 			      const struct v4l2_dbg_register *reg) | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	ths7303_write(sd, reg->reg, reg->val); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * const stc_lpf_sel_txt[4] = { | 
					
						
							|  |  |  | 	"500-kHz Filter", | 
					
						
							|  |  |  | 	"2.5-MHz Filter", | 
					
						
							|  |  |  | 	"5-MHz Filter", | 
					
						
							|  |  |  | 	"5-MHz Filter", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * const in_mux_sel_txt[2] = { | 
					
						
							|  |  |  | 	"Input A Select", | 
					
						
							|  |  |  | 	"Input B Select", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * const lpf_freq_sel_txt[4] = { | 
					
						
							|  |  |  | 	"9-MHz LPF", | 
					
						
							|  |  |  | 	"16-MHz LPF", | 
					
						
							|  |  |  | 	"35-MHz LPF", | 
					
						
							|  |  |  | 	"Bypass LPF", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char * const in_bias_sel_dis_cont_txt[8] = { | 
					
						
							|  |  |  | 	"Disable Channel", | 
					
						
							|  |  |  | 	"Mute Function - No Output", | 
					
						
							|  |  |  | 	"DC Bias Select", | 
					
						
							|  |  |  | 	"DC Bias + 250 mV Offset Select", | 
					
						
							|  |  |  | 	"AC Bias Select", | 
					
						
							|  |  |  | 	"Sync Tip Clamp with low bias", | 
					
						
							|  |  |  | 	"Sync Tip Clamp with mid bias", | 
					
						
							|  |  |  | 	"Sync Tip Clamp with high bias", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ths7303_log_channel_status(struct v4l2_subdev *sd, u8 reg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u8 val = ths7303_read(sd, reg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((val & 0x7) == 0) { | 
					
						
							|  |  |  | 		v4l2_info(sd, "Channel %d Off\n", reg); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v4l2_info(sd, "Channel %d On\n", reg); | 
					
						
							|  |  |  | 	v4l2_info(sd, "  value 0x%x\n", val); | 
					
						
							|  |  |  | 	v4l2_info(sd, "  %s\n", stc_lpf_sel_txt[(val >> 6) & 0x3]); | 
					
						
							|  |  |  | 	v4l2_info(sd, "  %s\n", in_mux_sel_txt[(val >> 5) & 0x1]); | 
					
						
							|  |  |  | 	v4l2_info(sd, "  %s\n", lpf_freq_sel_txt[(val >> 3) & 0x3]); | 
					
						
							|  |  |  | 	v4l2_info(sd, "  %s\n", in_bias_sel_dis_cont_txt[(val >> 0) & 0x7]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_log_status(struct v4l2_subdev *sd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ths7303_state *state = to_state(sd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (state->bt.pixelclock) { | 
					
						
							|  |  |  | 		struct v4l2_bt_timings *bt = bt = &state->bt; | 
					
						
							|  |  |  | 		u32 frame_width, frame_height; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:40:59 -03:00
										 |  |  | 		frame_width = V4L2_DV_BT_FRAME_WIDTH(bt); | 
					
						
							|  |  |  | 		frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt); | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		v4l2_info(sd, | 
					
						
							|  |  |  | 			  "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n", | 
					
						
							|  |  |  | 			  bt->width, bt->height, bt->interlaced ? "i" : "p", | 
					
						
							|  |  |  | 			  (frame_height * frame_width) > 0 ? | 
					
						
							|  |  |  | 			  (int)bt->pixelclock / | 
					
						
							|  |  |  | 			  (frame_height * frame_width) : 0, | 
					
						
							|  |  |  | 			  frame_width, frame_height, | 
					
						
							|  |  |  | 			  (int)bt->pixelclock, bt->polarities); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		v4l2_info(sd, "no timings set\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ths7303_log_channel_status(sd, THS7303_CHANNEL_1); | 
					
						
							|  |  |  | 	ths7303_log_channel_status(sd, THS7303_CHANNEL_2); | 
					
						
							|  |  |  | 	ths7303_log_channel_status(sd, THS7303_CHANNEL_3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | static const struct v4l2_subdev_core_ops ths7303_core_ops = { | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	.log_status = ths7303_log_status, | 
					
						
							|  |  |  | #ifdef CONFIG_VIDEO_ADV_DEBUG
 | 
					
						
							|  |  |  | 	.g_register = ths7303_g_register, | 
					
						
							|  |  |  | 	.s_register = ths7303_s_register, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct v4l2_subdev_ops ths7303_ops = { | 
					
						
							|  |  |  | 	.core	= &ths7303_core_ops, | 
					
						
							|  |  |  | 	.video 	= &ths7303_video_ops, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_probe(struct i2c_client *client, | 
					
						
							|  |  |  | 			const struct i2c_device_id *id) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	struct ths7303_platform_data *pdata = client->dev.platform_data; | 
					
						
							|  |  |  | 	struct ths7303_state *state; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	struct v4l2_subdev *sd; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-25 13:39:36 -03:00
										 |  |  | 	if (pdata == NULL) { | 
					
						
							|  |  |  | 		dev_err(&client->dev, "No platform data\n"); | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 
					
						
							|  |  |  | 		return -ENODEV; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v4l_info(client, "chip found @ 0x%x (%s)\n", | 
					
						
							|  |  |  | 			client->addr << 1, client->adapter->name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	state = devm_kzalloc(&client->dev, sizeof(struct ths7303_state), | 
					
						
							|  |  |  | 			     GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!state) | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-25 13:39:36 -03:00
										 |  |  | 	state->pdata = pdata; | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	sd = &state->sd; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	v4l2_i2c_subdev_init(sd, client, &ths7303_ops); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-25 13:39:35 -03:00
										 |  |  | 	/* set to default 480I_576I filter mode */ | 
					
						
							|  |  |  | 	if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) { | 
					
						
							|  |  |  | 		v4l_err(client, "Setting to 480I_576I filter mode failed!\n"); | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ths7303_remove(struct i2c_client *client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct v4l2_subdev *sd = i2c_get_clientdata(client); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v4l2_device_unregister_subdev(sd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct i2c_device_id ths7303_id[] = { | 
					
						
							| 
									
										
										
										
											2013-05-29 06:59:51 -03:00
										 |  |  | 	{"ths7303", 0}, | 
					
						
							|  |  |  | 	{"ths7353", 0}, | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	{}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_DEVICE_TABLE(i2c, ths7303_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct i2c_driver ths7303_driver = { | 
					
						
							|  |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.owner	= THIS_MODULE, | 
					
						
							| 
									
										
										
										
											2013-02-18 07:56:41 -03:00
										 |  |  | 		.name	= "ths73x3", | 
					
						
							| 
									
										
										
										
											2009-05-07 09:29:25 -03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 	.probe		= ths7303_probe, | 
					
						
							|  |  |  | 	.remove		= ths7303_remove, | 
					
						
							|  |  |  | 	.id_table	= ths7303_id, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 06:56:32 -03:00
										 |  |  | module_i2c_driver(ths7303_driver); |