Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.24 212 lines 5.1 kB view raw
1/* 2 * vp27smpx - driver version 0.0.1 3 * 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 5 * 6 * Based on a tvaudio patch from Takahiro Adachi <tadachi@tadachi-net.com> 7 * and Kazuhiko Kawakami <kazz-0@mail.goo.ne.jp> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24#include <linux/module.h> 25#include <linux/types.h> 26#include <linux/ioctl.h> 27#include <asm/uaccess.h> 28#include <linux/i2c.h> 29#include <linux/i2c-id.h> 30#include <linux/videodev.h> 31#include <media/v4l2-common.h> 32#include <media/v4l2-chip-ident.h> 33 34MODULE_DESCRIPTION("vp27smpx driver"); 35MODULE_AUTHOR("Hans Verkuil"); 36MODULE_LICENSE("GPL"); 37 38static unsigned short normal_i2c[] = { 0xb6 >> 1, I2C_CLIENT_END }; 39 40 41I2C_CLIENT_INSMOD; 42 43/* ----------------------------------------------------------------------- */ 44 45struct vp27smpx_state { 46 int radio; 47 u32 audmode; 48}; 49 50static void vp27smpx_set_audmode(struct i2c_client *client, u32 audmode) 51{ 52 struct vp27smpx_state *state = i2c_get_clientdata(client); 53 u8 data[3] = { 0x00, 0x00, 0x04 }; 54 55 switch (audmode) { 56 case V4L2_TUNER_MODE_MONO: 57 case V4L2_TUNER_MODE_LANG1: 58 break; 59 case V4L2_TUNER_MODE_STEREO: 60 case V4L2_TUNER_MODE_LANG1_LANG2: 61 data[1] = 0x01; 62 break; 63 case V4L2_TUNER_MODE_LANG2: 64 data[1] = 0x02; 65 break; 66 } 67 68 if (i2c_master_send(client, data, sizeof(data)) != sizeof(data)) { 69 v4l_err(client, "%s: I/O error setting audmode\n", client->name); 70 } 71 else { 72 state->audmode = audmode; 73 } 74} 75 76static int vp27smpx_command(struct i2c_client *client, unsigned int cmd, 77 void *arg) 78{ 79 struct vp27smpx_state *state = i2c_get_clientdata(client); 80 struct v4l2_tuner *vt = arg; 81 82 switch (cmd) { 83 case AUDC_SET_RADIO: 84 state->radio = 1; 85 break; 86 87 case VIDIOC_S_STD: 88 state->radio = 0; 89 break; 90 91 case VIDIOC_S_TUNER: 92 if (!state->radio) 93 vp27smpx_set_audmode(client, vt->audmode); 94 break; 95 96 case VIDIOC_G_TUNER: 97 if (state->radio) 98 break; 99 vt->audmode = state->audmode; 100 vt->capability = V4L2_TUNER_CAP_STEREO | 101 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; 102 vt->rxsubchans = V4L2_TUNER_SUB_MONO; 103 break; 104 105 case VIDIOC_G_CHIP_IDENT: 106 return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_VP27SMPX, 0); 107 108 case VIDIOC_LOG_STATUS: 109 v4l_info(client, "Audio Mode: %u%s\n", state->audmode, 110 state->radio ? " (Radio)" : ""); 111 break; 112 113 default: 114 return -EINVAL; 115 } 116 return 0; 117} 118 119/* ----------------------------------------------------------------------- */ 120 121/* i2c implementation */ 122 123/* 124 * Generic i2c probe 125 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 126 */ 127 128static struct i2c_driver i2c_driver; 129 130static int vp27smpx_attach(struct i2c_adapter *adapter, int address, int kind) 131{ 132 struct i2c_client *client; 133 struct vp27smpx_state *state; 134 135 /* Check if the adapter supports the needed features */ 136 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 137 return 0; 138 139 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); 140 if (client == 0) 141 return -ENOMEM; 142 143 client->addr = address; 144 client->adapter = adapter; 145 client->driver = &i2c_driver; 146 snprintf(client->name, sizeof(client->name) - 1, "vp27smpx"); 147 148 v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); 149 150 state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL); 151 if (state == NULL) { 152 kfree(client); 153 return -ENOMEM; 154 } 155 state->audmode = V4L2_TUNER_MODE_STEREO; 156 i2c_set_clientdata(client, state); 157 158 /* initialize vp27smpx */ 159 vp27smpx_set_audmode(client, state->audmode); 160 i2c_attach_client(client); 161 162 return 0; 163} 164 165static int vp27smpx_probe(struct i2c_adapter *adapter) 166{ 167 if (adapter->class & I2C_CLASS_TV_ANALOG) 168 return i2c_probe(adapter, &addr_data, vp27smpx_attach); 169 return 0; 170} 171 172static int vp27smpx_detach(struct i2c_client *client) 173{ 174 struct vp27smpx_state *state = i2c_get_clientdata(client); 175 int err; 176 177 err = i2c_detach_client(client); 178 if (err) { 179 return err; 180 } 181 kfree(state); 182 kfree(client); 183 184 return 0; 185} 186 187/* ----------------------------------------------------------------------- */ 188 189/* i2c implementation */ 190static struct i2c_driver i2c_driver = { 191 .driver = { 192 .name = "vp27smpx", 193 }, 194 .id = I2C_DRIVERID_VP27SMPX, 195 .attach_adapter = vp27smpx_probe, 196 .detach_client = vp27smpx_detach, 197 .command = vp27smpx_command, 198}; 199 200 201static int __init vp27smpx_init_module(void) 202{ 203 return i2c_add_driver(&i2c_driver); 204} 205 206static void __exit vp27smpx_cleanup_module(void) 207{ 208 i2c_del_driver(&i2c_driver); 209} 210 211module_init(vp27smpx_init_module); 212module_exit(vp27smpx_cleanup_module);