1/* 2 * device driver for Telegent tlg2300 based TV cards 3 * 4 * Author : 5 * Kang Yong <kangyong@telegent.com> 6 * Zhang Xiaobing <xbzhang@telegent.com> 7 * Huang Shijie <zyziii@telegent.com> or <shijie8@gmail.com> 8 * 9 * (c) 2009 Telegent Systems 10 * (c) 2010 Telegent Systems 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 */ 26 27#include <linux/kernel.h> 28#include <linux/errno.h> 29#include <linux/init.h> 30#include <linux/slab.h> 31#include <linux/module.h> 32#include <linux/kref.h> 33#include <linux/suspend.h> 34#include <linux/usb/quirks.h> 35#include <linux/ctype.h> 36#include <linux/string.h> 37#include <linux/types.h> 38#include <linux/firmware.h> 39#include <linux/smp_lock.h> 40 41#include "vendorcmds.h" 42#include "pd-common.h" 43 44#define VENDOR_ID 0x1B24 45#define PRODUCT_ID 0x4001 46static struct usb_device_id id_table[] = { 47 { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) }, 48 { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) }, 49 { }, 50}; 51MODULE_DEVICE_TABLE(usb, id_table); 52 53int debug_mode; 54module_param(debug_mode, int, 0644); 55MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); 56 57static const char *firmware_name = "tlg2300_firmware.bin"; 58static struct usb_driver poseidon_driver; 59static LIST_HEAD(pd_device_list); 60 61/* 62 * send set request to USB firmware. 63 */ 64s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status) 65{ 66 s32 ret; 67 s8 data[32] = {}; 68 u16 lower_16, upper_16; 69 70 if (pd->state & POSEIDON_STATE_DISCONNECT) 71 return -ENODEV; 72 73 mdelay(30); 74 75 if (param == 0) { 76 upper_16 = lower_16 = 0; 77 } else { 78 /* send 32 bit param as two 16 bit param,little endian */ 79 lower_16 = (unsigned short)(param & 0xffff); 80 upper_16 = (unsigned short)((param >> 16) & 0xffff); 81 } 82 ret = usb_control_msg(pd->udev, 83 usb_rcvctrlpipe(pd->udev, 0), 84 REQ_SET_CMD | cmdid, 85 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 86 lower_16, 87 upper_16, 88 &data, 89 sizeof(*cmd_status), 90 USB_CTRL_GET_TIMEOUT); 91 92 if (!ret) { 93 return -ENXIO; 94 } else { 95 /* 1st 4 bytes into cmd_status */ 96 memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status)); 97 } 98 return 0; 99} 100 101/* 102 * send get request to Poseidon firmware. 103 */ 104s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param, 105 void *buf, s32 *cmd_status, s32 datalen) 106{ 107 s32 ret; 108 s8 data[128] = {}; 109 u16 lower_16, upper_16; 110 111 if (pd->state & POSEIDON_STATE_DISCONNECT) 112 return -ENODEV; 113 114 mdelay(30); 115 if (param == 0) { 116 upper_16 = lower_16 = 0; 117 } else { 118 /*send 32 bit param as two 16 bit param, little endian */ 119 lower_16 = (unsigned short)(param & 0xffff); 120 upper_16 = (unsigned short)((param >> 16) & 0xffff); 121 } 122 ret = usb_control_msg(pd->udev, 123 usb_rcvctrlpipe(pd->udev, 0), 124 REQ_GET_CMD | cmdid, 125 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 126 lower_16, 127 upper_16, 128 &data, 129 (datalen + sizeof(*cmd_status)), 130 USB_CTRL_GET_TIMEOUT); 131 132 if (ret < 0) { 133 return -ENXIO; 134 } else { 135 /* 1st 4 bytes into cmd_status, remaining data into cmd_data */ 136 memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status)); 137 memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen); 138 } 139 return 0; 140} 141 142static int pm_notifier_block(struct notifier_block *nb, 143 unsigned long event, void *dummy) 144{ 145 struct poseidon *pd = NULL; 146 struct list_head *node, *next; 147 148 switch (event) { 149 case PM_POST_HIBERNATION: 150 list_for_each_safe(node, next, &pd_device_list) { 151 struct usb_device *udev; 152 struct usb_interface *iface; 153 int rc = 0; 154 155 pd = container_of(node, struct poseidon, device_list); 156 udev = pd->udev; 157 iface = pd->interface; 158 159 /* It will cause the system to reload the firmware */ 160 rc = usb_lock_device_for_reset(udev, iface); 161 if (rc >= 0) { 162 usb_reset_device(udev); 163 usb_unlock_device(udev); 164 } 165 } 166 break; 167 default: 168 break; 169 } 170 log("event :%ld\n", event); 171 return 0; 172} 173 174static struct notifier_block pm_notifer = { 175 .notifier_call = pm_notifier_block, 176}; 177 178int set_tuner_mode(struct poseidon *pd, unsigned char mode) 179{ 180 s32 ret, cmd_status; 181 182 if (pd->state & POSEIDON_STATE_DISCONNECT) 183 return -ENODEV; 184 185 ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status); 186 if (ret || cmd_status) 187 return -ENXIO; 188 return 0; 189} 190 191void poseidon_delete(struct kref *kref) 192{ 193 struct poseidon *pd = container_of(kref, struct poseidon, kref); 194 195 if (!pd) 196 return; 197 list_del_init(&pd->device_list); 198 199 pd_dvb_usb_device_cleanup(pd); 200 /* clean_audio_data(&pd->audio_data);*/ 201 202 if (pd->udev) { 203 usb_put_dev(pd->udev); 204 pd->udev = NULL; 205 } 206 if (pd->interface) { 207 usb_put_intf(pd->interface); 208 pd->interface = NULL; 209 } 210 kfree(pd); 211 log(); 212} 213 214static int firmware_download(struct usb_device *udev) 215{ 216 int ret = 0, actual_length; 217 const struct firmware *fw = NULL; 218 void *fwbuf = NULL; 219 size_t fwlength = 0, offset; 220 size_t max_packet_size; 221 222 ret = request_firmware(&fw, firmware_name, &udev->dev); 223 if (ret) { 224 log("download err : %d", ret); 225 return ret; 226 } 227 228 fwlength = fw->size; 229 230 fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL); 231 if (!fwbuf) { 232 ret = -ENOMEM; 233 goto out; 234 } 235 236 max_packet_size = udev->ep_out[0x1]->desc.wMaxPacketSize; 237 log("\t\t download size : %d", (int)max_packet_size); 238 239 for (offset = 0; offset < fwlength; offset += max_packet_size) { 240 actual_length = 0; 241 ret = usb_bulk_msg(udev, 242 usb_sndbulkpipe(udev, 0x01), /* ep 1 */ 243 fwbuf + offset, 244 min(max_packet_size, fwlength - offset), 245 &actual_length, 246 HZ * 10); 247 if (ret) 248 break; 249 } 250 kfree(fwbuf); 251out: 252 release_firmware(fw); 253 return ret; 254} 255 256static inline struct poseidon *get_pd(struct usb_interface *intf) 257{ 258 return usb_get_intfdata(intf); 259} 260 261#ifdef CONFIG_PM 262/* one-to-one map : poseidon{} <----> usb_device{}'s port */ 263static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) 264{ 265 pd->portnum = udev->portnum; 266} 267 268static inline int get_autopm_ref(struct poseidon *pd) 269{ 270 return pd->video_data.users + pd->vbi_data.users + pd->audio.users 271 + atomic_read(&pd->dvb_data.users) + pd->radio_data.users; 272} 273 274/* fixup something for poseidon */ 275static inline struct poseidon *fixup(struct poseidon *pd) 276{ 277 int count; 278 279 /* old udev and interface have gone, so put back reference . */ 280 count = get_autopm_ref(pd); 281 log("count : %d, ref count : %d", count, get_pm_count(pd)); 282 while (count--) 283 usb_autopm_put_interface(pd->interface); 284 /*usb_autopm_set_interface(pd->interface); */ 285 286 usb_put_dev(pd->udev); 287 usb_put_intf(pd->interface); 288 log("event : %d\n", pd->msg.event); 289 return pd; 290} 291 292static struct poseidon *find_old_poseidon(struct usb_device *udev) 293{ 294 struct poseidon *pd; 295 296 list_for_each_entry(pd, &pd_device_list, device_list) { 297 if (pd->portnum == udev->portnum && in_hibernation(pd)) 298 return fixup(pd); 299 } 300 return NULL; 301} 302 303/* Is the card working now ? */ 304static inline int is_working(struct poseidon *pd) 305{ 306 return get_pm_count(pd) > 0; 307} 308 309static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg) 310{ 311 struct poseidon *pd = get_pd(intf); 312 313 if (!pd) 314 return 0; 315 if (!is_working(pd)) { 316 if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) { 317 pd->msg.event = PM_EVENT_AUTO_SUSPEND; 318 pd->pm_resume = NULL; /* a good guard */ 319 printk(KERN_DEBUG "\n\t+ TLG2300 auto suspend +\n\n"); 320 } 321 return 0; 322 } 323 pd->msg = msg; /* save it here */ 324 logpm(pd); 325 return pd->pm_suspend ? pd->pm_suspend(pd) : 0; 326} 327 328static int poseidon_resume(struct usb_interface *intf) 329{ 330 struct poseidon *pd = get_pd(intf); 331 332 if (!pd) 333 return 0; 334 printk(KERN_DEBUG "\n\t ++ TLG2300 resume ++\n\n"); 335 336 if (!is_working(pd)) { 337 if (PM_EVENT_AUTO_SUSPEND == pd->msg.event) 338 pd->msg = PMSG_ON; 339 return 0; 340 } 341 if (in_hibernation(pd)) { 342 logpm(pd); 343 return 0; 344 } 345 logpm(pd); 346 return pd->pm_resume ? pd->pm_resume(pd) : 0; 347} 348 349static void hibernation_resume(struct work_struct *w) 350{ 351 struct poseidon *pd = container_of(w, struct poseidon, pm_work); 352 int count; 353 354 pd->msg.event = 0; /* clear it here */ 355 pd->state &= ~POSEIDON_STATE_DISCONNECT; 356 357 /* set the new interface's reference */ 358 count = get_autopm_ref(pd); 359 while (count--) 360 usb_autopm_get_interface(pd->interface); 361 362 /* resume the context */ 363 logpm(pd); 364 if (pd->pm_resume) 365 pd->pm_resume(pd); 366} 367#else /* CONFIG_PM is not enabled: */ 368static inline struct poseidon *find_old_poseidon(struct usb_device *udev) 369{ 370 return NULL; 371} 372 373static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) 374{ 375} 376#endif 377 378static bool check_firmware(struct usb_device *udev, int *down_firmware) 379{ 380 void *buf; 381 int ret; 382 struct cmd_firmware_vers_s *cmd_firm; 383 384 buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL); 385 if (!buf) 386 return -ENOMEM; 387 ret = usb_control_msg(udev, 388 usb_rcvctrlpipe(udev, 0), 389 REQ_GET_CMD | GET_FW_ID, 390 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 391 0, 392 0, 393 buf, 394 sizeof(*cmd_firm) + sizeof(u32), 395 USB_CTRL_GET_TIMEOUT); 396 kfree(buf); 397 398 if (ret < 0) { 399 *down_firmware = 1; 400 return firmware_download(udev); 401 } 402 return ret; 403} 404 405static int poseidon_probe(struct usb_interface *interface, 406 const struct usb_device_id *id) 407{ 408 struct usb_device *udev = interface_to_usbdev(interface); 409 struct poseidon *pd = NULL; 410 int ret = 0; 411 int new_one = 0; 412 413 /* download firmware */ 414 check_firmware(udev, &ret); 415 if (ret) 416 return 0; 417 418 /* Do I recovery from the hibernate ? */ 419 pd = find_old_poseidon(udev); 420 if (!pd) { 421 pd = kzalloc(sizeof(*pd), GFP_KERNEL); 422 if (!pd) 423 return -ENOMEM; 424 kref_init(&pd->kref); 425 set_map_flags(pd, udev); 426 new_one = 1; 427 } 428 429 pd->udev = usb_get_dev(udev); 430 pd->interface = usb_get_intf(interface); 431 usb_set_intfdata(interface, pd); 432 433 if (new_one) { 434 struct device *dev = &interface->dev; 435 436 logpm(pd); 437 mutex_init(&pd->lock); 438 439 /* register v4l2 device */ 440 snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s", 441 dev->driver->name, dev_name(dev)); 442 ret = v4l2_device_register(NULL, &pd->v4l2_dev); 443 444 /* register devices in directory /dev */ 445 ret = pd_video_init(pd); 446 poseidon_audio_init(pd); 447 poseidon_fm_init(pd); 448 pd_dvb_usb_device_init(pd); 449 450 INIT_LIST_HEAD(&pd->device_list); 451 list_add_tail(&pd->device_list, &pd_device_list); 452 } 453 454 device_init_wakeup(&udev->dev, 1); 455#ifdef CONFIG_PM 456 pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY; 457 usb_enable_autosuspend(pd->udev); 458 459 if (in_hibernation(pd)) { 460 INIT_WORK(&pd->pm_work, hibernation_resume); 461 schedule_work(&pd->pm_work); 462 } 463#endif 464 return 0; 465} 466 467static void poseidon_disconnect(struct usb_interface *interface) 468{ 469 struct poseidon *pd = get_pd(interface); 470 471 if (!pd) 472 return; 473 logpm(pd); 474 if (in_hibernation(pd)) 475 return; 476 477 mutex_lock(&pd->lock); 478 pd->state |= POSEIDON_STATE_DISCONNECT; 479 mutex_unlock(&pd->lock); 480 481 /* stop urb transferring */ 482 stop_all_video_stream(pd); 483 dvb_stop_streaming(&pd->dvb_data); 484 485 /*unregister v4l2 device */ 486 v4l2_device_unregister(&pd->v4l2_dev); 487 488 lock_kernel(); 489 { 490 pd_dvb_usb_device_exit(pd); 491 poseidon_fm_exit(pd); 492 493 poseidon_audio_free(pd); 494 pd_video_exit(pd); 495 } 496 unlock_kernel(); 497 498 usb_set_intfdata(interface, NULL); 499 kref_put(&pd->kref, poseidon_delete); 500} 501 502static struct usb_driver poseidon_driver = { 503 .name = "poseidon", 504 .probe = poseidon_probe, 505 .disconnect = poseidon_disconnect, 506 .id_table = id_table, 507#ifdef CONFIG_PM 508 .suspend = poseidon_suspend, 509 .resume = poseidon_resume, 510#endif 511 .supports_autosuspend = 1, 512}; 513 514static int __init poseidon_init(void) 515{ 516 int ret; 517 518 ret = usb_register(&poseidon_driver); 519 if (ret) 520 return ret; 521 register_pm_notifier(&pm_notifer); 522 return ret; 523} 524 525static void __exit poseidon_exit(void) 526{ 527 log(); 528 unregister_pm_notifier(&pm_notifer); 529 usb_deregister(&poseidon_driver); 530} 531 532module_init(poseidon_init); 533module_exit(poseidon_exit); 534 535MODULE_AUTHOR("Telegent Systems"); 536MODULE_DESCRIPTION("For tlg2300-based USB device "); 537MODULE_LICENSE("GPL"); 538