1/* 2 * ths7303- THS7303 Video Amplifier driver 3 * 4 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation version 2. 9 * 10 * This program is distributed .as is. WITHOUT ANY WARRANTY of any 11 * kind, whether express or implied; without even the implied warranty 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/ctype.h> 19#include <linux/slab.h> 20#include <linux/i2c.h> 21#include <linux/device.h> 22#include <linux/delay.h> 23#include <linux/module.h> 24#include <linux/uaccess.h> 25#include <linux/videodev2.h> 26 27#include <media/v4l2-device.h> 28#include <media/v4l2-subdev.h> 29#include <media/v4l2-chip-ident.h> 30 31MODULE_DESCRIPTION("TI THS7303 video amplifier driver"); 32MODULE_AUTHOR("Chaithrika U S"); 33MODULE_LICENSE("GPL"); 34 35static int debug; 36module_param(debug, int, 0644); 37MODULE_PARM_DESC(debug, "Debug level 0-1"); 38 39/* following function is used to set ths7303 */ 40static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std) 41{ 42 int err = 0; 43 u8 val; 44 struct i2c_client *client; 45 46 client = v4l2_get_subdevdata(sd); 47 48 if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) { 49 val = 0x02; 50 v4l2_dbg(1, debug, sd, "setting value for SDTV format\n"); 51 } else { 52 val = 0x00; 53 v4l2_dbg(1, debug, sd, "disabling all channels\n"); 54 } 55 56 err |= i2c_smbus_write_byte_data(client, 0x01, val); 57 err |= i2c_smbus_write_byte_data(client, 0x02, val); 58 err |= i2c_smbus_write_byte_data(client, 0x03, val); 59 60 if (err) 61 v4l2_err(sd, "write failed\n"); 62 63 return err; 64} 65 66static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) 67{ 68 return ths7303_setvalue(sd, norm); 69} 70 71static int ths7303_g_chip_ident(struct v4l2_subdev *sd, 72 struct v4l2_dbg_chip_ident *chip) 73{ 74 struct i2c_client *client = v4l2_get_subdevdata(sd); 75 76 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_THS7303, 0); 77} 78 79static const struct v4l2_subdev_video_ops ths7303_video_ops = { 80 .s_std_output = ths7303_s_std_output, 81}; 82 83static const struct v4l2_subdev_core_ops ths7303_core_ops = { 84 .g_chip_ident = ths7303_g_chip_ident, 85}; 86 87static const struct v4l2_subdev_ops ths7303_ops = { 88 .core = &ths7303_core_ops, 89 .video = &ths7303_video_ops, 90}; 91 92static int ths7303_probe(struct i2c_client *client, 93 const struct i2c_device_id *id) 94{ 95 struct v4l2_subdev *sd; 96 v4l2_std_id std_id = V4L2_STD_NTSC; 97 98 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 99 return -ENODEV; 100 101 v4l_info(client, "chip found @ 0x%x (%s)\n", 102 client->addr << 1, client->adapter->name); 103 104 sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); 105 if (sd == NULL) 106 return -ENOMEM; 107 108 v4l2_i2c_subdev_init(sd, client, &ths7303_ops); 109 110 return ths7303_setvalue(sd, std_id); 111} 112 113static int ths7303_remove(struct i2c_client *client) 114{ 115 struct v4l2_subdev *sd = i2c_get_clientdata(client); 116 117 v4l2_device_unregister_subdev(sd); 118 kfree(sd); 119 120 return 0; 121} 122 123static const struct i2c_device_id ths7303_id[] = { 124 {"ths7303", 0}, 125 {}, 126}; 127 128MODULE_DEVICE_TABLE(i2c, ths7303_id); 129 130static struct i2c_driver ths7303_driver = { 131 .driver = { 132 .owner = THIS_MODULE, 133 .name = "ths7303", 134 }, 135 .probe = ths7303_probe, 136 .remove = ths7303_remove, 137 .id_table = ths7303_id, 138}; 139 140static int __init ths7303_init(void) 141{ 142 return i2c_add_driver(&ths7303_driver); 143} 144 145static void __exit ths7303_exit(void) 146{ 147 i2c_del_driver(&ths7303_driver); 148} 149 150module_init(ths7303_init); 151module_exit(ths7303_exit); 152 153