140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S/* 288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * ths7303/53- THS7303/53 Video Amplifier driver 340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * 440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. 688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * 788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * Author: Chaithrika U S <chaithrika@ti.com> 888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * 988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * Contributors: 1088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * Hans Verkuil <hans.verkuil@cisco.com> 1188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * Lad, Prabhakar <prabhakar.lad@ti.com> 1288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar * Martin Bugge <marbugge@cisco.com> 1340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * 1440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * This program is free software; you can redistribute it and/or 1540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * modify it under the terms of the GNU General Public License as 1640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * published by the Free Software Foundation version 2. 1740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * 1840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * This program is distributed .as is. WITHOUT ANY WARRANTY of any 1940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * kind, whether express or implied; without even the implied warranty 2040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S * GNU General Public License for more details. 2240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S */ 2340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 2440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S#include <linux/i2c.h> 2540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S#include <linux/module.h> 2688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#include <linux/slab.h> 2740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 2888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#include <media/ths7303.h> 2988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#include <media/v4l2-device.h> 3040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 31ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli#define THS7303_CHANNEL_1 1 32ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli#define THS7303_CHANNEL_2 2 33ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli#define THS7303_CHANNEL_3 3 34ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli 3588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstruct ths7303_state { 3688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct v4l2_subdev sd; 37dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar const struct ths7303_platform_data *pdata; 3888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct v4l2_bt_timings bt; 3988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar int std_id; 4088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar int stream_on; 4188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar}; 4288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 43ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadlienum ths7303_filter_mode { 44ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli THS7303_FILTER_MODE_480I_576I, 45ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli THS7303_FILTER_MODE_480P_576P, 46ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli THS7303_FILTER_MODE_720P_1080I, 47ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli THS7303_FILTER_MODE_1080P, 48ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli THS7303_FILTER_MODE_DISABLE 49ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli}; 50ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli 5140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U SMODULE_DESCRIPTION("TI THS7303 video amplifier driver"); 5240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U SMODULE_AUTHOR("Chaithrika U S"); 5340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U SMODULE_LICENSE("GPL"); 5440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 5540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic int debug; 5640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Smodule_param(debug, int, 0644); 5740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U SMODULE_PARM_DESC(debug, "Debug level 0-1"); 5840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 5988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic inline struct ths7303_state *to_state(struct v4l2_subdev *sd) 6088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 6188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return container_of(sd, struct ths7303_state, sd); 6288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 6388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 6488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_read(struct v4l2_subdev *sd, u8 reg) 6588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 6688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct i2c_client *client = v4l2_get_subdevdata(sd); 6788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 6888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return i2c_smbus_read_byte_data(client, reg); 6988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 7088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 7188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val) 7288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 7388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct i2c_client *client = v4l2_get_subdevdata(sd); 7488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar int ret; 7588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar int i; 7688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 7788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar for (i = 0; i < 3; i++) { 7888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ret = i2c_smbus_write_byte_data(client, reg, val); 7988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (ret == 0) 8088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 8188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } 8288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return ret; 8388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 8488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 8540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S/* following function is used to set ths7303 */ 8606eb891edb4009245278a0ae50ccfd6fc99004d2Ricardo Ribaldastatic int ths7303_setval(struct v4l2_subdev *sd, 8706eb891edb4009245278a0ae50ccfd6fc99004d2Ricardo Ribalda enum ths7303_filter_mode mode) 8840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S{ 89ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli struct i2c_client *client = v4l2_get_subdevdata(sd); 9088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state = to_state(sd); 91dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar const struct ths7303_platform_data *pdata = state->pdata; 9288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar u8 val, sel = 0; 9388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar int err, disable = 0; 9440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 95ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli if (!client) 96ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli return -EINVAL; 97ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli 98ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli switch (mode) { 99ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli case THS7303_FILTER_MODE_1080P: 10088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar sel = 0x3; /*1080p and SXGA/UXGA */ 101ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli break; 102ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli case THS7303_FILTER_MODE_720P_1080I: 10388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar sel = 0x2; /*720p, 1080i and SVGA/XGA */ 104ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli break; 105ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli case THS7303_FILTER_MODE_480P_576P: 10688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar sel = 0x1; /* EDTV 480p/576p and VGA */ 107ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli break; 108ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli case THS7303_FILTER_MODE_480I_576I: 10988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar sel = 0x0; /* SDTV, S-Video, 480i/576i */ 110ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli break; 111ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli default: 112ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli /* disable all channels */ 113ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli disable = 1; 11440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S } 11588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 11688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar val = (sel << 6) | (sel << 3); 117ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli if (!disable) 11888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar val |= (pdata->ch_1 & 0x27); 11988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar err = ths7303_write(sd, THS7303_CHANNEL_1, val); 120ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli if (err) 121ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli goto out; 12240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 12388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar val = (sel << 6) | (sel << 3); 124ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli if (!disable) 12588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar val |= (pdata->ch_2 & 0x27); 12688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar err = ths7303_write(sd, THS7303_CHANNEL_2, val); 12740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S if (err) 128ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli goto out; 12940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 13088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar val = (sel << 6) | (sel << 3); 13188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (!disable) 13288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar val |= (pdata->ch_3 & 0x27); 13388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar err = ths7303_write(sd, THS7303_CHANNEL_3, val); 134ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli if (err) 135ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli goto out; 13688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 13788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 138ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadliout: 139ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli pr_info("write byte data failed\n"); 14040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S return err; 14140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S} 14240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 14340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) 14440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S{ 14588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state = to_state(sd); 14688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 14788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) { 14888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar state->std_id = 1; 14988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar state->bt.pixelclock = 0; 150ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I); 15188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } 15288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 15388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE); 154ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli} 155ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli 15688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_config(struct v4l2_subdev *sd) 157ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli{ 15888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state = to_state(sd); 15988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar int res; 16088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 16188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (!state->stream_on) { 16288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_write(sd, THS7303_CHANNEL_1, 16388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (ths7303_read(sd, THS7303_CHANNEL_1) & 0xf8) | 16488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 0x00); 16588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_write(sd, THS7303_CHANNEL_2, 16688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (ths7303_read(sd, THS7303_CHANNEL_2) & 0xf8) | 16788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 0x00); 16888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_write(sd, THS7303_CHANNEL_3, 16988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (ths7303_read(sd, THS7303_CHANNEL_3) & 0xf8) | 17088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 0x00); 17188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 17288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } 173ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli 17488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (state->bt.pixelclock > 120000000) 175ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P); 17688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar else if (state->bt.pixelclock > 70000000) 177ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I); 17888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar else if (state->bt.pixelclock > 20000000) 179ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P); 18088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar else if (state->std_id) 18188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar res = ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I); 182ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli else 183ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli /* disable all channels */ 184ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE); 185ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli 186ad7dcb334a0dbba9ac611d43c4e0ff7973eaa1cfManjunath Hadli return res; 18788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 18888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 18988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 19088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_s_stream(struct v4l2_subdev *sd, int enable) 19188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 19288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state = to_state(sd); 19388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 19488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar state->stream_on = enable; 19588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 19688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return ths7303_config(sd); 19788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 19888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 19988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar/* for setting filter for HD output */ 20088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_s_dv_timings(struct v4l2_subdev *sd, 20188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct v4l2_dv_timings *dv_timings) 20288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 20388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state = to_state(sd); 20488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 20588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (!dv_timings || dv_timings->type != V4L2_DV_BT_656_1120) 20688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return -EINVAL; 20788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 20888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar state->bt = dv_timings->bt; 20988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar state->std_id = 0; 21088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 21188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return ths7303_config(sd); 21240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S} 21340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 21440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic const struct v4l2_subdev_video_ops ths7303_video_ops = { 21588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar .s_stream = ths7303_s_stream, 21640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .s_std_output = ths7303_s_std_output, 21788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar .s_dv_timings = ths7303_s_dv_timings, 21840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S}; 21940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 22088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#ifdef CONFIG_VIDEO_ADV_DEBUG 22188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 22288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_g_register(struct v4l2_subdev *sd, 22388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct v4l2_dbg_register *reg) 22488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 22588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar reg->size = 1; 22688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar reg->val = ths7303_read(sd, reg->reg); 22788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 22888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 22988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 23088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_s_register(struct v4l2_subdev *sd, 231977ba3b1b73f24fae2d0c8bd59d7a4696f1e0cccHans Verkuil const struct v4l2_dbg_register *reg) 23288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 23388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_write(sd, reg->reg, reg->val); 23488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 23588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 23688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#endif 23788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 23888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic const char * const stc_lpf_sel_txt[4] = { 23988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "500-kHz Filter", 24088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "2.5-MHz Filter", 24188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "5-MHz Filter", 24288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "5-MHz Filter", 24388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar}; 24488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 24588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic const char * const in_mux_sel_txt[2] = { 24688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Input A Select", 24788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Input B Select", 24888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar}; 24988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 25088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic const char * const lpf_freq_sel_txt[4] = { 25188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "9-MHz LPF", 25288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "16-MHz LPF", 25388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "35-MHz LPF", 25488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Bypass LPF", 25588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar}; 25688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 25788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic const char * const in_bias_sel_dis_cont_txt[8] = { 25888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Disable Channel", 25988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Mute Function - No Output", 26088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "DC Bias Select", 26188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "DC Bias + 250 mV Offset Select", 26288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "AC Bias Select", 26388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Sync Tip Clamp with low bias", 26488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Sync Tip Clamp with mid bias", 26588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "Sync Tip Clamp with high bias", 26688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar}; 26788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 26888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic void ths7303_log_channel_status(struct v4l2_subdev *sd, u8 reg) 26988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 27088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar u8 val = ths7303_read(sd, reg); 27188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 27288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if ((val & 0x7) == 0) { 27388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, "Channel %d Off\n", reg); 27488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return; 27588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } 27688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 27788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, "Channel %d On\n", reg); 27888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, " value 0x%x\n", val); 27988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, " %s\n", stc_lpf_sel_txt[(val >> 6) & 0x3]); 28088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, " %s\n", in_mux_sel_txt[(val >> 5) & 0x1]); 28188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, " %s\n", lpf_freq_sel_txt[(val >> 3) & 0x3]); 28288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, " %s\n", in_bias_sel_dis_cont_txt[(val >> 0) & 0x7]); 28388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 28488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 28588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakarstatic int ths7303_log_status(struct v4l2_subdev *sd) 28688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar{ 28788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state = to_state(sd); 28888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 28988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off"); 29088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 29188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (state->bt.pixelclock) { 29288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct v4l2_bt_timings *bt = bt = &state->bt; 29388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar u32 frame_width, frame_height; 29488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 295eacf8f9aa80e2231af43b589cfc18c054e417220Hans Verkuil frame_width = V4L2_DV_BT_FRAME_WIDTH(bt); 296eacf8f9aa80e2231af43b589cfc18c054e417220Hans Verkuil frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt); 29788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, 29888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n", 29988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar bt->width, bt->height, bt->interlaced ? "i" : "p", 30088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (frame_height * frame_width) > 0 ? 30188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (int)bt->pixelclock / 30288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (frame_height * frame_width) : 0, 30388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar frame_width, frame_height, 30488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar (int)bt->pixelclock, bt->polarities); 30588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } else { 30688da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar v4l2_info(sd, "no timings set\n"); 30788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } 30888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 30988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_log_channel_status(sd, THS7303_CHANNEL_1); 31088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_log_channel_status(sd, THS7303_CHANNEL_2); 31188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar ths7303_log_channel_status(sd, THS7303_CHANNEL_3); 31288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 31388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 31488da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar} 31588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 31640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic const struct v4l2_subdev_core_ops ths7303_core_ops = { 31788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar .log_status = ths7303_log_status, 31888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#ifdef CONFIG_VIDEO_ADV_DEBUG 31988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar .g_register = ths7303_g_register, 32088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar .s_register = ths7303_s_register, 32188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar#endif 32240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S}; 32340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 32440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic const struct v4l2_subdev_ops ths7303_ops = { 32540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .core = &ths7303_core_ops, 32640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .video = &ths7303_video_ops, 32740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S}; 32840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 32940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic int ths7303_probe(struct i2c_client *client, 33040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S const struct i2c_device_id *id) 33140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S{ 33288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_platform_data *pdata = client->dev.platform_data; 33388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar struct ths7303_state *state; 33440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S struct v4l2_subdev *sd; 33540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 336dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar if (pdata == NULL) { 337dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar dev_err(&client->dev, "No platform data\n"); 338dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar return -EINVAL; 339dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar } 340dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar 34140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 34240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S return -ENODEV; 34340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 34440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S v4l_info(client, "chip found @ 0x%x (%s)\n", 34540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S client->addr << 1, client->adapter->name); 34640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 34788da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar state = devm_kzalloc(&client->dev, sizeof(struct ths7303_state), 34888da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar GFP_KERNEL); 34988da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar if (!state) 35040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S return -ENOMEM; 35140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 352dd8c393b3c39f7ebd9ad69ce50cc836773d512b6Lad, Prabhakar state->pdata = pdata; 35388da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar sd = &state->sd; 35440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S v4l2_i2c_subdev_init(sd, client, &ths7303_ops); 35540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 3568524ce558a0111762efa1a6b5ba9ce5e092b4707Lad, Prabhakar /* set to default 480I_576I filter mode */ 3578524ce558a0111762efa1a6b5ba9ce5e092b4707Lad, Prabhakar if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) { 3588524ce558a0111762efa1a6b5ba9ce5e092b4707Lad, Prabhakar v4l_err(client, "Setting to 480I_576I filter mode failed!\n"); 3598524ce558a0111762efa1a6b5ba9ce5e092b4707Lad, Prabhakar return -EINVAL; 36088da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar } 36188da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar 36288da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar return 0; 36340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S} 36440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 36540199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic int ths7303_remove(struct i2c_client *client) 36640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S{ 36740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S struct v4l2_subdev *sd = i2c_get_clientdata(client); 36840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 36940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S v4l2_device_unregister_subdev(sd); 37040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 37140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S return 0; 37240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S} 37340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 37440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic const struct i2c_device_id ths7303_id[] = { 375e12771100c93e101a7a8b302b6c5d57cff7b1551Hans Verkuil {"ths7303", 0}, 376e12771100c93e101a7a8b302b6c5d57cff7b1551Hans Verkuil {"ths7353", 0}, 37740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S {}, 37840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S}; 37940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 38040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U SMODULE_DEVICE_TABLE(i2c, ths7303_id); 38140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 38240199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U Sstatic struct i2c_driver ths7303_driver = { 38340199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .driver = { 38440199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .owner = THIS_MODULE, 38588da0183eb2b72048099b4e0ecae1705f5309c94Lad, Prabhakar .name = "ths73x3", 38640199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S }, 38740199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .probe = ths7303_probe, 38840199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .remove = ths7303_remove, 38940199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S .id_table = ths7303_id, 39040199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S}; 39140199c50b891d24d1a8f1d480f886680a3ac9b74Chaithrika U S 392c6e8d86fffd8edf1bfccbd441b1812ee919fe3d5Axel Linmodule_i2c_driver(ths7303_driver); 393