radio-usb-si4713.c (14963B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. 4 * All rights reserved. 5 */ 6 7/* kernel includes */ 8#include <linux/kernel.h> 9#include <linux/module.h> 10#include <linux/usb.h> 11#include <linux/init.h> 12#include <linux/slab.h> 13#include <linux/input.h> 14#include <linux/mutex.h> 15#include <linux/i2c.h> 16/* V4l includes */ 17#include <linux/videodev2.h> 18#include <media/v4l2-common.h> 19#include <media/v4l2-device.h> 20#include <media/v4l2-ioctl.h> 21#include <media/v4l2-event.h> 22#include <linux/platform_data/media/si4713.h> 23 24#include "si4713.h" 25 26/* driver and module definitions */ 27MODULE_AUTHOR("Dinesh Ram <dinesh.ram@cern.ch>"); 28MODULE_DESCRIPTION("Si4713 FM Transmitter USB driver"); 29MODULE_LICENSE("GPL v2"); 30 31/* The Device announces itself as Cygnal Integrated Products, Inc. */ 32#define USB_SI4713_VENDOR 0x10c4 33#define USB_SI4713_PRODUCT 0x8244 34 35#define BUFFER_LENGTH 64 36#define USB_TIMEOUT 1000 37#define USB_RESP_TIMEOUT 50000 38 39/* USB Device ID List */ 40static const struct usb_device_id usb_si4713_usb_device_table[] = { 41 {USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT, 42 USB_CLASS_HID, 0, 0) }, 43 { } /* Terminating entry */ 44}; 45 46MODULE_DEVICE_TABLE(usb, usb_si4713_usb_device_table); 47 48struct si4713_usb_device { 49 struct usb_device *usbdev; 50 struct usb_interface *intf; 51 struct video_device vdev; 52 struct v4l2_device v4l2_dev; 53 struct v4l2_subdev *v4l2_subdev; 54 struct mutex lock; 55 struct i2c_adapter i2c_adapter; 56 57 u8 *buffer; 58}; 59 60static inline struct si4713_usb_device *to_si4713_dev(struct v4l2_device *v4l2_dev) 61{ 62 return container_of(v4l2_dev, struct si4713_usb_device, v4l2_dev); 63} 64 65static int vidioc_querycap(struct file *file, void *priv, 66 struct v4l2_capability *v) 67{ 68 struct si4713_usb_device *radio = video_drvdata(file); 69 70 strscpy(v->driver, "radio-usb-si4713", sizeof(v->driver)); 71 strscpy(v->card, "Si4713 FM Transmitter", sizeof(v->card)); 72 usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); 73 return 0; 74} 75 76static int vidioc_g_modulator(struct file *file, void *priv, 77 struct v4l2_modulator *vm) 78{ 79 struct si4713_usb_device *radio = video_drvdata(file); 80 81 return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_modulator, vm); 82} 83 84static int vidioc_s_modulator(struct file *file, void *priv, 85 const struct v4l2_modulator *vm) 86{ 87 struct si4713_usb_device *radio = video_drvdata(file); 88 89 return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_modulator, vm); 90} 91 92static int vidioc_s_frequency(struct file *file, void *priv, 93 const struct v4l2_frequency *vf) 94{ 95 struct si4713_usb_device *radio = video_drvdata(file); 96 97 return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_frequency, vf); 98} 99 100static int vidioc_g_frequency(struct file *file, void *priv, 101 struct v4l2_frequency *vf) 102{ 103 struct si4713_usb_device *radio = video_drvdata(file); 104 105 return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_frequency, vf); 106} 107 108static const struct v4l2_ioctl_ops usb_si4713_ioctl_ops = { 109 .vidioc_querycap = vidioc_querycap, 110 .vidioc_g_modulator = vidioc_g_modulator, 111 .vidioc_s_modulator = vidioc_s_modulator, 112 .vidioc_g_frequency = vidioc_g_frequency, 113 .vidioc_s_frequency = vidioc_s_frequency, 114 .vidioc_log_status = v4l2_ctrl_log_status, 115 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 116 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 117}; 118 119/* File system interface */ 120static const struct v4l2_file_operations usb_si4713_fops = { 121 .owner = THIS_MODULE, 122 .open = v4l2_fh_open, 123 .release = v4l2_fh_release, 124 .poll = v4l2_ctrl_poll, 125 .unlocked_ioctl = video_ioctl2, 126}; 127 128static void usb_si4713_video_device_release(struct v4l2_device *v4l2_dev) 129{ 130 struct si4713_usb_device *radio = to_si4713_dev(v4l2_dev); 131 struct i2c_adapter *adapter = &radio->i2c_adapter; 132 133 i2c_del_adapter(adapter); 134 v4l2_device_unregister(&radio->v4l2_dev); 135 kfree(radio->buffer); 136 kfree(radio); 137} 138 139/* 140 * This command sequence emulates the behaviour of the Windows driver. 141 * The structure of these commands was determined by sniffing the 142 * usb traffic of the device during startup. 143 * Most likely, these commands make some queries to the device. 144 * Commands are sent to enquire parameters like the bus mode, 145 * component revision, boot mode, the device serial number etc. 146 * 147 * These commands are necessary to be sent in this order during startup. 148 * The device fails to powerup if these commands are not sent. 149 * 150 * The complete list of startup commands is given in the start_seq table below. 151 */ 152static int si4713_send_startup_command(struct si4713_usb_device *radio) 153{ 154 unsigned long until_jiffies = jiffies + usecs_to_jiffies(USB_RESP_TIMEOUT) + 1; 155 u8 *buffer = radio->buffer; 156 int retval; 157 158 /* send the command */ 159 retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), 160 0x09, 0x21, 0x033f, 0, radio->buffer, 161 BUFFER_LENGTH, USB_TIMEOUT); 162 if (retval < 0) 163 return retval; 164 165 for (;;) { 166 /* receive the response */ 167 retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), 168 0x01, 0xa1, 0x033f, 0, radio->buffer, 169 BUFFER_LENGTH, USB_TIMEOUT); 170 if (retval < 0) 171 return retval; 172 if (!radio->buffer[1]) { 173 /* USB traffic sniffing showed that some commands require 174 * additional checks. */ 175 switch (buffer[1]) { 176 case 0x32: 177 if (radio->buffer[2] == 0) 178 return 0; 179 break; 180 case 0x14: 181 case 0x12: 182 if (radio->buffer[2] & SI4713_CTS) 183 return 0; 184 break; 185 case 0x06: 186 if ((radio->buffer[2] & SI4713_CTS) && radio->buffer[9] == 0x08) 187 return 0; 188 break; 189 default: 190 return 0; 191 } 192 } 193 if (time_is_before_jiffies(until_jiffies)) 194 return -EIO; 195 msleep(3); 196 } 197 198 return retval; 199} 200 201struct si4713_start_seq_table { 202 int len; 203 u8 payload[8]; 204}; 205 206/* 207 * Some of the startup commands that could be recognized are : 208 * (0x03): Get serial number of the board (Response : CB000-00-00) 209 * (0x06, 0x03, 0x03, 0x08, 0x01, 0x0f) : Get Component revision 210 */ 211static const struct si4713_start_seq_table start_seq[] = { 212 213 { 1, { 0x03 } }, 214 { 2, { 0x32, 0x7f } }, 215 { 6, { 0x06, 0x03, 0x03, 0x08, 0x01, 0x0f } }, 216 { 2, { 0x14, 0x02 } }, 217 { 2, { 0x09, 0x90 } }, 218 { 3, { 0x08, 0x90, 0xfa } }, 219 { 2, { 0x36, 0x01 } }, 220 { 2, { 0x05, 0x03 } }, 221 { 7, { 0x06, 0x00, 0x06, 0x0e, 0x01, 0x0f, 0x05 } }, 222 { 1, { 0x12 } }, 223 /* Commands that are sent after pressing the 'Initialize' 224 button in the windows application */ 225 { 1, { 0x03 } }, 226 { 1, { 0x01 } }, 227 { 2, { 0x09, 0x90 } }, 228 { 3, { 0x08, 0x90, 0xfa } }, 229 { 1, { 0x34 } }, 230 { 2, { 0x35, 0x01 } }, 231 { 2, { 0x36, 0x01 } }, 232 { 2, { 0x30, 0x09 } }, 233 { 4, { 0x30, 0x06, 0x00, 0xe2 } }, 234 { 3, { 0x31, 0x01, 0x30 } }, 235 { 3, { 0x31, 0x04, 0x09 } }, 236 { 2, { 0x05, 0x02 } }, 237 { 6, { 0x06, 0x03, 0x03, 0x08, 0x01, 0x0f } }, 238}; 239 240static int si4713_start_seq(struct si4713_usb_device *radio) 241{ 242 int retval = 0; 243 int i; 244 245 radio->buffer[0] = 0x3f; 246 247 for (i = 0; i < ARRAY_SIZE(start_seq); i++) { 248 int len = start_seq[i].len; 249 const u8 *payload = start_seq[i].payload; 250 251 memcpy(radio->buffer + 1, payload, len); 252 memset(radio->buffer + len + 1, 0, BUFFER_LENGTH - 1 - len); 253 retval = si4713_send_startup_command(radio); 254 } 255 256 return retval; 257} 258 259static struct i2c_board_info si4713_board_info = { 260 I2C_BOARD_INFO("si4713", SI4713_I2C_ADDR_BUSEN_HIGH), 261}; 262 263struct si4713_command_table { 264 int command_id; 265 u8 payload[8]; 266}; 267 268/* 269 * Structure of a command : 270 * Byte 1 : 0x3f (always) 271 * Byte 2 : 0x06 (send a command) 272 * Byte 3 : Unknown 273 * Byte 4 : Number of arguments + 1 (for the command byte) 274 * Byte 5 : Number of response bytes 275 */ 276static struct si4713_command_table command_table[] = { 277 278 { SI4713_CMD_POWER_UP, { 0x00, SI4713_PWUP_NARGS + 1, SI4713_PWUP_NRESP} }, 279 { SI4713_CMD_GET_REV, { 0x03, 0x01, SI4713_GETREV_NRESP } }, 280 { SI4713_CMD_POWER_DOWN, { 0x00, 0x01, SI4713_PWDN_NRESP} }, 281 { SI4713_CMD_SET_PROPERTY, { 0x00, SI4713_SET_PROP_NARGS + 1, SI4713_SET_PROP_NRESP } }, 282 { SI4713_CMD_GET_PROPERTY, { 0x00, SI4713_GET_PROP_NARGS + 1, SI4713_GET_PROP_NRESP } }, 283 { SI4713_CMD_TX_TUNE_FREQ, { 0x03, SI4713_TXFREQ_NARGS + 1, SI4713_TXFREQ_NRESP } }, 284 { SI4713_CMD_TX_TUNE_POWER, { 0x03, SI4713_TXPWR_NARGS + 1, SI4713_TXPWR_NRESP } }, 285 { SI4713_CMD_TX_TUNE_MEASURE, { 0x03, SI4713_TXMEA_NARGS + 1, SI4713_TXMEA_NRESP } }, 286 { SI4713_CMD_TX_TUNE_STATUS, { 0x00, SI4713_TXSTATUS_NARGS + 1, SI4713_TXSTATUS_NRESP } }, 287 { SI4713_CMD_TX_ASQ_STATUS, { 0x03, SI4713_ASQSTATUS_NARGS + 1, SI4713_ASQSTATUS_NRESP } }, 288 { SI4713_CMD_GET_INT_STATUS, { 0x03, 0x01, SI4713_GET_STATUS_NRESP } }, 289 { SI4713_CMD_TX_RDS_BUFF, { 0x03, SI4713_RDSBUFF_NARGS + 1, SI4713_RDSBUFF_NRESP } }, 290 { SI4713_CMD_TX_RDS_PS, { 0x00, SI4713_RDSPS_NARGS + 1, SI4713_RDSPS_NRESP } }, 291}; 292 293static int send_command(struct si4713_usb_device *radio, u8 *payload, char *data, int len) 294{ 295 int retval; 296 297 radio->buffer[0] = 0x3f; 298 radio->buffer[1] = 0x06; 299 300 memcpy(radio->buffer + 2, payload, 3); 301 memcpy(radio->buffer + 5, data, len); 302 memset(radio->buffer + 5 + len, 0, BUFFER_LENGTH - 5 - len); 303 304 /* send the command */ 305 retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), 306 0x09, 0x21, 0x033f, 0, radio->buffer, 307 BUFFER_LENGTH, USB_TIMEOUT); 308 309 return retval < 0 ? retval : 0; 310} 311 312static int si4713_i2c_read(struct si4713_usb_device *radio, char *data, int len) 313{ 314 unsigned long until_jiffies = jiffies + usecs_to_jiffies(USB_RESP_TIMEOUT) + 1; 315 int retval; 316 317 /* receive the response */ 318 for (;;) { 319 retval = usb_control_msg(radio->usbdev, 320 usb_rcvctrlpipe(radio->usbdev, 0), 321 0x01, 0xa1, 0x033f, 0, radio->buffer, 322 BUFFER_LENGTH, USB_TIMEOUT); 323 if (retval < 0) 324 return retval; 325 326 /* 327 * Check that we get a valid reply back (buffer[1] == 0) and 328 * that CTS is set before returning, otherwise we wait and try 329 * again. The i2c driver also does the CTS check, but the timeouts 330 * used there are much too small for this USB driver, so we wait 331 * for it here. 332 */ 333 if (radio->buffer[1] == 0 && (radio->buffer[2] & SI4713_CTS)) { 334 memcpy(data, radio->buffer + 2, len); 335 return 0; 336 } 337 if (time_is_before_jiffies(until_jiffies)) { 338 /* Zero the status value, ensuring CTS isn't set */ 339 data[0] = 0; 340 return 0; 341 } 342 msleep(3); 343 } 344} 345 346static int si4713_i2c_write(struct si4713_usb_device *radio, char *data, int len) 347{ 348 int retval = -EINVAL; 349 int i; 350 351 if (len > BUFFER_LENGTH - 5) 352 return -EINVAL; 353 354 for (i = 0; i < ARRAY_SIZE(command_table); i++) { 355 if (data[0] == command_table[i].command_id) 356 retval = send_command(radio, command_table[i].payload, 357 data, len); 358 } 359 360 return retval < 0 ? retval : 0; 361} 362 363static int si4713_transfer(struct i2c_adapter *i2c_adapter, 364 struct i2c_msg *msgs, int num) 365{ 366 struct si4713_usb_device *radio = i2c_get_adapdata(i2c_adapter); 367 int retval = -EINVAL; 368 int i; 369 370 for (i = 0; i < num; i++) { 371 if (msgs[i].flags & I2C_M_RD) 372 retval = si4713_i2c_read(radio, msgs[i].buf, msgs[i].len); 373 else 374 retval = si4713_i2c_write(radio, msgs[i].buf, msgs[i].len); 375 if (retval) 376 break; 377 } 378 379 return retval ? retval : num; 380} 381 382static u32 si4713_functionality(struct i2c_adapter *adapter) 383{ 384 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 385} 386 387static const struct i2c_algorithm si4713_algo = { 388 .master_xfer = si4713_transfer, 389 .functionality = si4713_functionality, 390}; 391 392/* This name value shows up in the sysfs filename associated 393 with this I2C adapter */ 394static const struct i2c_adapter si4713_i2c_adapter_template = { 395 .name = "si4713-i2c", 396 .owner = THIS_MODULE, 397 .algo = &si4713_algo, 398}; 399 400static int si4713_register_i2c_adapter(struct si4713_usb_device *radio) 401{ 402 radio->i2c_adapter = si4713_i2c_adapter_template; 403 /* set up sysfs linkage to our parent device */ 404 radio->i2c_adapter.dev.parent = &radio->usbdev->dev; 405 i2c_set_adapdata(&radio->i2c_adapter, radio); 406 407 return i2c_add_adapter(&radio->i2c_adapter); 408} 409 410/* check if the device is present and register with v4l and usb if it is */ 411static int usb_si4713_probe(struct usb_interface *intf, 412 const struct usb_device_id *id) 413{ 414 struct si4713_usb_device *radio; 415 struct i2c_adapter *adapter; 416 struct v4l2_subdev *sd; 417 int retval; 418 419 dev_info(&intf->dev, "Si4713 development board discovered: (%04X:%04X)\n", 420 id->idVendor, id->idProduct); 421 422 /* Initialize local device structure */ 423 radio = kzalloc(sizeof(struct si4713_usb_device), GFP_KERNEL); 424 if (radio) 425 radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); 426 427 if (!radio || !radio->buffer) { 428 dev_err(&intf->dev, "kmalloc for si4713_usb_device failed\n"); 429 kfree(radio); 430 return -ENOMEM; 431 } 432 433 mutex_init(&radio->lock); 434 435 radio->usbdev = interface_to_usbdev(intf); 436 radio->intf = intf; 437 usb_set_intfdata(intf, &radio->v4l2_dev); 438 439 retval = si4713_start_seq(radio); 440 if (retval < 0) 441 goto err_v4l2; 442 443 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); 444 if (retval < 0) { 445 dev_err(&intf->dev, "couldn't register v4l2_device\n"); 446 goto err_v4l2; 447 } 448 449 retval = si4713_register_i2c_adapter(radio); 450 if (retval < 0) { 451 dev_err(&intf->dev, "could not register i2c device\n"); 452 goto err_i2cdev; 453 } 454 455 adapter = &radio->i2c_adapter; 456 sd = v4l2_i2c_new_subdev_board(&radio->v4l2_dev, adapter, 457 &si4713_board_info, NULL); 458 radio->v4l2_subdev = sd; 459 if (!sd) { 460 dev_err(&intf->dev, "cannot get v4l2 subdevice\n"); 461 retval = -ENODEV; 462 goto del_adapter; 463 } 464 465 radio->vdev.ctrl_handler = sd->ctrl_handler; 466 radio->v4l2_dev.release = usb_si4713_video_device_release; 467 strscpy(radio->vdev.name, radio->v4l2_dev.name, 468 sizeof(radio->vdev.name)); 469 radio->vdev.v4l2_dev = &radio->v4l2_dev; 470 radio->vdev.fops = &usb_si4713_fops; 471 radio->vdev.ioctl_ops = &usb_si4713_ioctl_ops; 472 radio->vdev.lock = &radio->lock; 473 radio->vdev.release = video_device_release_empty; 474 radio->vdev.vfl_dir = VFL_DIR_TX; 475 radio->vdev.device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; 476 477 video_set_drvdata(&radio->vdev, radio); 478 479 retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); 480 if (retval < 0) { 481 dev_err(&intf->dev, "could not register video device\n"); 482 goto del_adapter; 483 } 484 485 dev_info(&intf->dev, "V4L2 device registered as %s\n", 486 video_device_node_name(&radio->vdev)); 487 488 return 0; 489 490del_adapter: 491 i2c_del_adapter(adapter); 492err_i2cdev: 493 v4l2_device_unregister(&radio->v4l2_dev); 494err_v4l2: 495 kfree(radio->buffer); 496 kfree(radio); 497 return retval; 498} 499 500static void usb_si4713_disconnect(struct usb_interface *intf) 501{ 502 struct si4713_usb_device *radio = to_si4713_dev(usb_get_intfdata(intf)); 503 504 dev_info(&intf->dev, "Si4713 development board now disconnected\n"); 505 506 mutex_lock(&radio->lock); 507 usb_set_intfdata(intf, NULL); 508 video_unregister_device(&radio->vdev); 509 v4l2_device_disconnect(&radio->v4l2_dev); 510 mutex_unlock(&radio->lock); 511 v4l2_device_put(&radio->v4l2_dev); 512} 513 514/* USB subsystem interface */ 515static struct usb_driver usb_si4713_driver = { 516 .name = "radio-usb-si4713", 517 .probe = usb_si4713_probe, 518 .disconnect = usb_si4713_disconnect, 519 .id_table = usb_si4713_usb_device_table, 520}; 521 522module_usb_driver(usb_si4713_driver);