PageRenderTime 72ms CodeModel.GetById 41ms RepoModel.GetById 1ms app.codeStats 0ms

/sound/usb/6fire/control.c

https://bitbucket.org/mirror/linux
C | 617 lines | 515 code | 78 blank | 24 comment | 55 complexity | cb55a834dd930968bfbd47d3e907f97f MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Linux driver for TerraTec DMX 6Fire USB
  4. *
  5. * Mixer control
  6. *
  7. * Author: Torsten Schenk <torsten.schenk@zoho.com>
  8. * Created: Jan 01, 2011
  9. * Copyright: (C) Torsten Schenk
  10. *
  11. * Thanks to:
  12. * - Holger Ruckdeschel: he found out how to control individual channel
  13. * volumes and introduced mute switch
  14. */
  15. #include <linux/interrupt.h>
  16. #include <sound/control.h>
  17. #include <sound/tlv.h>
  18. #include "control.h"
  19. #include "comm.h"
  20. #include "chip.h"
  21. static const char * const opt_coax_texts[2] = { "Optical", "Coax" };
  22. static const char * const line_phono_texts[2] = { "Line", "Phono" };
  23. /*
  24. * data that needs to be sent to device. sets up card internal stuff.
  25. * values dumped from windows driver and filtered by trial'n'error.
  26. */
  27. static const struct {
  28. u8 type;
  29. u8 reg;
  30. u8 value;
  31. }
  32. init_data[] = {
  33. { 0x22, 0x00, 0x00 }, { 0x20, 0x00, 0x08 }, { 0x22, 0x01, 0x01 },
  34. { 0x20, 0x01, 0x08 }, { 0x22, 0x02, 0x00 }, { 0x20, 0x02, 0x08 },
  35. { 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
  36. { 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
  37. { 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
  38. { 0x12, 0x0d, 0x38 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
  39. { 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
  40. { 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
  41. { 0 } /* TERMINATING ENTRY */
  42. };
  43. static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
  44. /* values to write to soundcard register for all samplerates */
  45. static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
  46. static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
  47. static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0);
  48. static DECLARE_TLV_DB_MINMAX(tlv_input, -1500, 1500);
  49. enum {
  50. DIGITAL_THRU_ONLY_SAMPLERATE = 3
  51. };
  52. static void usb6fire_control_output_vol_update(struct control_runtime *rt)
  53. {
  54. struct comm_runtime *comm_rt = rt->chip->comm;
  55. int i;
  56. if (comm_rt)
  57. for (i = 0; i < 6; i++)
  58. if (!(rt->ovol_updated & (1 << i))) {
  59. comm_rt->write8(comm_rt, 0x12, 0x0f + i,
  60. 180 - rt->output_vol[i]);
  61. rt->ovol_updated |= 1 << i;
  62. }
  63. }
  64. static void usb6fire_control_output_mute_update(struct control_runtime *rt)
  65. {
  66. struct comm_runtime *comm_rt = rt->chip->comm;
  67. if (comm_rt)
  68. comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute);
  69. }
  70. static void usb6fire_control_input_vol_update(struct control_runtime *rt)
  71. {
  72. struct comm_runtime *comm_rt = rt->chip->comm;
  73. int i;
  74. if (comm_rt)
  75. for (i = 0; i < 2; i++)
  76. if (!(rt->ivol_updated & (1 << i))) {
  77. comm_rt->write8(comm_rt, 0x12, 0x1c + i,
  78. rt->input_vol[i] & 0x3f);
  79. rt->ivol_updated |= 1 << i;
  80. }
  81. }
  82. static void usb6fire_control_line_phono_update(struct control_runtime *rt)
  83. {
  84. struct comm_runtime *comm_rt = rt->chip->comm;
  85. if (comm_rt) {
  86. comm_rt->write8(comm_rt, 0x22, 0x02, rt->line_phono_switch);
  87. comm_rt->write8(comm_rt, 0x21, 0x02, rt->line_phono_switch);
  88. }
  89. }
  90. static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
  91. {
  92. struct comm_runtime *comm_rt = rt->chip->comm;
  93. if (comm_rt) {
  94. comm_rt->write8(comm_rt, 0x22, 0x00, rt->opt_coax_switch);
  95. comm_rt->write8(comm_rt, 0x21, 0x00, rt->opt_coax_switch);
  96. }
  97. }
  98. static int usb6fire_control_set_rate(struct control_runtime *rt, int rate)
  99. {
  100. int ret;
  101. struct usb_device *device = rt->chip->dev;
  102. struct comm_runtime *comm_rt = rt->chip->comm;
  103. if (rate < 0 || rate >= CONTROL_N_RATES)
  104. return -EINVAL;
  105. ret = usb_set_interface(device, 1, rates_altsetting[rate]);
  106. if (ret < 0)
  107. return ret;
  108. /* set soundcard clock */
  109. ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rate],
  110. rates_6fire_vh[rate]);
  111. if (ret < 0)
  112. return ret;
  113. return 0;
  114. }
  115. static int usb6fire_control_set_channels(
  116. struct control_runtime *rt, int n_analog_out,
  117. int n_analog_in, bool spdif_out, bool spdif_in)
  118. {
  119. int ret;
  120. struct comm_runtime *comm_rt = rt->chip->comm;
  121. /* enable analog inputs and outputs
  122. * (one bit per stereo-channel) */
  123. ret = comm_rt->write16(comm_rt, 0x02, 0x02,
  124. (1 << (n_analog_out / 2)) - 1,
  125. (1 << (n_analog_in / 2)) - 1);
  126. if (ret < 0)
  127. return ret;
  128. /* disable digital inputs and outputs */
  129. /* TODO: use spdif_x to enable/disable digital channels */
  130. ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
  131. if (ret < 0)
  132. return ret;
  133. return 0;
  134. }
  135. static int usb6fire_control_streaming_update(struct control_runtime *rt)
  136. {
  137. struct comm_runtime *comm_rt = rt->chip->comm;
  138. if (comm_rt) {
  139. if (!rt->usb_streaming && rt->digital_thru_switch)
  140. usb6fire_control_set_rate(rt,
  141. DIGITAL_THRU_ONLY_SAMPLERATE);
  142. return comm_rt->write16(comm_rt, 0x02, 0x00, 0x00,
  143. (rt->usb_streaming ? 0x01 : 0x00) |
  144. (rt->digital_thru_switch ? 0x08 : 0x00));
  145. }
  146. return -EINVAL;
  147. }
  148. static int usb6fire_control_output_vol_info(struct snd_kcontrol *kcontrol,
  149. struct snd_ctl_elem_info *uinfo)
  150. {
  151. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  152. uinfo->count = 2;
  153. uinfo->value.integer.min = 0;
  154. uinfo->value.integer.max = 180;
  155. return 0;
  156. }
  157. static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol,
  158. struct snd_ctl_elem_value *ucontrol)
  159. {
  160. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  161. unsigned int ch = kcontrol->private_value;
  162. int changed = 0;
  163. if (ch > 4) {
  164. dev_err(&rt->chip->dev->dev,
  165. "Invalid channel in volume control.");
  166. return -EINVAL;
  167. }
  168. if (rt->output_vol[ch] != ucontrol->value.integer.value[0]) {
  169. rt->output_vol[ch] = ucontrol->value.integer.value[0];
  170. rt->ovol_updated &= ~(1 << ch);
  171. changed = 1;
  172. }
  173. if (rt->output_vol[ch + 1] != ucontrol->value.integer.value[1]) {
  174. rt->output_vol[ch + 1] = ucontrol->value.integer.value[1];
  175. rt->ovol_updated &= ~(2 << ch);
  176. changed = 1;
  177. }
  178. if (changed)
  179. usb6fire_control_output_vol_update(rt);
  180. return changed;
  181. }
  182. static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol,
  183. struct snd_ctl_elem_value *ucontrol)
  184. {
  185. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  186. unsigned int ch = kcontrol->private_value;
  187. if (ch > 4) {
  188. dev_err(&rt->chip->dev->dev,
  189. "Invalid channel in volume control.");
  190. return -EINVAL;
  191. }
  192. ucontrol->value.integer.value[0] = rt->output_vol[ch];
  193. ucontrol->value.integer.value[1] = rt->output_vol[ch + 1];
  194. return 0;
  195. }
  196. static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol,
  197. struct snd_ctl_elem_value *ucontrol)
  198. {
  199. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  200. unsigned int ch = kcontrol->private_value;
  201. u8 old = rt->output_mute;
  202. u8 value = 0;
  203. if (ch > 4) {
  204. dev_err(&rt->chip->dev->dev,
  205. "Invalid channel in volume control.");
  206. return -EINVAL;
  207. }
  208. rt->output_mute &= ~(3 << ch);
  209. if (ucontrol->value.integer.value[0])
  210. value |= 1;
  211. if (ucontrol->value.integer.value[1])
  212. value |= 2;
  213. rt->output_mute |= value << ch;
  214. if (rt->output_mute != old)
  215. usb6fire_control_output_mute_update(rt);
  216. return rt->output_mute != old;
  217. }
  218. static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol,
  219. struct snd_ctl_elem_value *ucontrol)
  220. {
  221. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  222. unsigned int ch = kcontrol->private_value;
  223. u8 value = rt->output_mute >> ch;
  224. if (ch > 4) {
  225. dev_err(&rt->chip->dev->dev,
  226. "Invalid channel in volume control.");
  227. return -EINVAL;
  228. }
  229. ucontrol->value.integer.value[0] = 1 & value;
  230. value >>= 1;
  231. ucontrol->value.integer.value[1] = 1 & value;
  232. return 0;
  233. }
  234. static int usb6fire_control_input_vol_info(struct snd_kcontrol *kcontrol,
  235. struct snd_ctl_elem_info *uinfo)
  236. {
  237. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  238. uinfo->count = 2;
  239. uinfo->value.integer.min = 0;
  240. uinfo->value.integer.max = 30;
  241. return 0;
  242. }
  243. static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol,
  244. struct snd_ctl_elem_value *ucontrol)
  245. {
  246. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  247. int changed = 0;
  248. if (rt->input_vol[0] != ucontrol->value.integer.value[0]) {
  249. rt->input_vol[0] = ucontrol->value.integer.value[0] - 15;
  250. rt->ivol_updated &= ~(1 << 0);
  251. changed = 1;
  252. }
  253. if (rt->input_vol[1] != ucontrol->value.integer.value[1]) {
  254. rt->input_vol[1] = ucontrol->value.integer.value[1] - 15;
  255. rt->ivol_updated &= ~(1 << 1);
  256. changed = 1;
  257. }
  258. if (changed)
  259. usb6fire_control_input_vol_update(rt);
  260. return changed;
  261. }
  262. static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol,
  263. struct snd_ctl_elem_value *ucontrol)
  264. {
  265. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  266. ucontrol->value.integer.value[0] = rt->input_vol[0] + 15;
  267. ucontrol->value.integer.value[1] = rt->input_vol[1] + 15;
  268. return 0;
  269. }
  270. static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol,
  271. struct snd_ctl_elem_info *uinfo)
  272. {
  273. return snd_ctl_enum_info(uinfo, 1, 2, line_phono_texts);
  274. }
  275. static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol,
  276. struct snd_ctl_elem_value *ucontrol)
  277. {
  278. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  279. int changed = 0;
  280. if (rt->line_phono_switch != ucontrol->value.integer.value[0]) {
  281. rt->line_phono_switch = ucontrol->value.integer.value[0];
  282. usb6fire_control_line_phono_update(rt);
  283. changed = 1;
  284. }
  285. return changed;
  286. }
  287. static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol,
  288. struct snd_ctl_elem_value *ucontrol)
  289. {
  290. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  291. ucontrol->value.integer.value[0] = rt->line_phono_switch;
  292. return 0;
  293. }
  294. static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol,
  295. struct snd_ctl_elem_info *uinfo)
  296. {
  297. return snd_ctl_enum_info(uinfo, 1, 2, opt_coax_texts);
  298. }
  299. static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol,
  300. struct snd_ctl_elem_value *ucontrol)
  301. {
  302. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  303. int changed = 0;
  304. if (rt->opt_coax_switch != ucontrol->value.enumerated.item[0]) {
  305. rt->opt_coax_switch = ucontrol->value.enumerated.item[0];
  306. usb6fire_control_opt_coax_update(rt);
  307. changed = 1;
  308. }
  309. return changed;
  310. }
  311. static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
  312. struct snd_ctl_elem_value *ucontrol)
  313. {
  314. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  315. ucontrol->value.enumerated.item[0] = rt->opt_coax_switch;
  316. return 0;
  317. }
  318. static int usb6fire_control_digital_thru_put(struct snd_kcontrol *kcontrol,
  319. struct snd_ctl_elem_value *ucontrol)
  320. {
  321. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  322. int changed = 0;
  323. if (rt->digital_thru_switch != ucontrol->value.integer.value[0]) {
  324. rt->digital_thru_switch = ucontrol->value.integer.value[0];
  325. usb6fire_control_streaming_update(rt);
  326. changed = 1;
  327. }
  328. return changed;
  329. }
  330. static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
  331. struct snd_ctl_elem_value *ucontrol)
  332. {
  333. struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
  334. ucontrol->value.integer.value[0] = rt->digital_thru_switch;
  335. return 0;
  336. }
  337. static const struct snd_kcontrol_new vol_elements[] = {
  338. {
  339. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  340. .name = "Analog Playback Volume",
  341. .index = 0,
  342. .private_value = 0,
  343. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
  344. SNDRV_CTL_ELEM_ACCESS_TLV_READ,
  345. .info = usb6fire_control_output_vol_info,
  346. .get = usb6fire_control_output_vol_get,
  347. .put = usb6fire_control_output_vol_put,
  348. .tlv = { .p = tlv_output }
  349. },
  350. {
  351. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  352. .name = "Analog Playback Volume",
  353. .index = 1,
  354. .private_value = 2,
  355. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
  356. SNDRV_CTL_ELEM_ACCESS_TLV_READ,
  357. .info = usb6fire_control_output_vol_info,
  358. .get = usb6fire_control_output_vol_get,
  359. .put = usb6fire_control_output_vol_put,
  360. .tlv = { .p = tlv_output }
  361. },
  362. {
  363. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  364. .name = "Analog Playback Volume",
  365. .index = 2,
  366. .private_value = 4,
  367. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
  368. SNDRV_CTL_ELEM_ACCESS_TLV_READ,
  369. .info = usb6fire_control_output_vol_info,
  370. .get = usb6fire_control_output_vol_get,
  371. .put = usb6fire_control_output_vol_put,
  372. .tlv = { .p = tlv_output }
  373. },
  374. {}
  375. };
  376. static const struct snd_kcontrol_new mute_elements[] = {
  377. {
  378. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  379. .name = "Analog Playback Switch",
  380. .index = 0,
  381. .private_value = 0,
  382. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  383. .info = snd_ctl_boolean_stereo_info,
  384. .get = usb6fire_control_output_mute_get,
  385. .put = usb6fire_control_output_mute_put,
  386. },
  387. {
  388. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  389. .name = "Analog Playback Switch",
  390. .index = 1,
  391. .private_value = 2,
  392. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  393. .info = snd_ctl_boolean_stereo_info,
  394. .get = usb6fire_control_output_mute_get,
  395. .put = usb6fire_control_output_mute_put,
  396. },
  397. {
  398. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  399. .name = "Analog Playback Switch",
  400. .index = 2,
  401. .private_value = 4,
  402. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  403. .info = snd_ctl_boolean_stereo_info,
  404. .get = usb6fire_control_output_mute_get,
  405. .put = usb6fire_control_output_mute_put,
  406. },
  407. {}
  408. };
  409. static const struct snd_kcontrol_new elements[] = {
  410. {
  411. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  412. .name = "Line/Phono Capture Route",
  413. .index = 0,
  414. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  415. .info = usb6fire_control_line_phono_info,
  416. .get = usb6fire_control_line_phono_get,
  417. .put = usb6fire_control_line_phono_put
  418. },
  419. {
  420. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  421. .name = "Opt/Coax Capture Route",
  422. .index = 0,
  423. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  424. .info = usb6fire_control_opt_coax_info,
  425. .get = usb6fire_control_opt_coax_get,
  426. .put = usb6fire_control_opt_coax_put
  427. },
  428. {
  429. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  430. .name = "Digital Thru Playback Route",
  431. .index = 0,
  432. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  433. .info = snd_ctl_boolean_mono_info,
  434. .get = usb6fire_control_digital_thru_get,
  435. .put = usb6fire_control_digital_thru_put
  436. },
  437. {
  438. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  439. .name = "Analog Capture Volume",
  440. .index = 0,
  441. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
  442. SNDRV_CTL_ELEM_ACCESS_TLV_READ,
  443. .info = usb6fire_control_input_vol_info,
  444. .get = usb6fire_control_input_vol_get,
  445. .put = usb6fire_control_input_vol_put,
  446. .tlv = { .p = tlv_input }
  447. },
  448. {}
  449. };
  450. static int usb6fire_control_add_virtual(
  451. struct control_runtime *rt,
  452. struct snd_card *card,
  453. char *name,
  454. const struct snd_kcontrol_new *elems)
  455. {
  456. int ret;
  457. int i;
  458. struct snd_kcontrol *vmaster =
  459. snd_ctl_make_virtual_master(name, tlv_output);
  460. struct snd_kcontrol *control;
  461. if (!vmaster)
  462. return -ENOMEM;
  463. ret = snd_ctl_add(card, vmaster);
  464. if (ret < 0)
  465. return ret;
  466. i = 0;
  467. while (elems[i].name) {
  468. control = snd_ctl_new1(&elems[i], rt);
  469. if (!control)
  470. return -ENOMEM;
  471. ret = snd_ctl_add(card, control);
  472. if (ret < 0)
  473. return ret;
  474. ret = snd_ctl_add_slave(vmaster, control);
  475. if (ret < 0)
  476. return ret;
  477. i++;
  478. }
  479. return 0;
  480. }
  481. int usb6fire_control_init(struct sfire_chip *chip)
  482. {
  483. int i;
  484. int ret;
  485. struct control_runtime *rt = kzalloc(sizeof(struct control_runtime),
  486. GFP_KERNEL);
  487. struct comm_runtime *comm_rt = chip->comm;
  488. if (!rt)
  489. return -ENOMEM;
  490. rt->chip = chip;
  491. rt->update_streaming = usb6fire_control_streaming_update;
  492. rt->set_rate = usb6fire_control_set_rate;
  493. rt->set_channels = usb6fire_control_set_channels;
  494. i = 0;
  495. while (init_data[i].type) {
  496. comm_rt->write8(comm_rt, init_data[i].type, init_data[i].reg,
  497. init_data[i].value);
  498. i++;
  499. }
  500. usb6fire_control_opt_coax_update(rt);
  501. usb6fire_control_line_phono_update(rt);
  502. usb6fire_control_output_vol_update(rt);
  503. usb6fire_control_output_mute_update(rt);
  504. usb6fire_control_input_vol_update(rt);
  505. usb6fire_control_streaming_update(rt);
  506. ret = usb6fire_control_add_virtual(rt, chip->card,
  507. "Master Playback Volume", vol_elements);
  508. if (ret) {
  509. dev_err(&chip->dev->dev, "cannot add control.\n");
  510. kfree(rt);
  511. return ret;
  512. }
  513. ret = usb6fire_control_add_virtual(rt, chip->card,
  514. "Master Playback Switch", mute_elements);
  515. if (ret) {
  516. dev_err(&chip->dev->dev, "cannot add control.\n");
  517. kfree(rt);
  518. return ret;
  519. }
  520. i = 0;
  521. while (elements[i].name) {
  522. ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
  523. if (ret < 0) {
  524. kfree(rt);
  525. dev_err(&chip->dev->dev, "cannot add control.\n");
  526. return ret;
  527. }
  528. i++;
  529. }
  530. chip->control = rt;
  531. return 0;
  532. }
  533. void usb6fire_control_abort(struct sfire_chip *chip)
  534. {}
  535. void usb6fire_control_destroy(struct sfire_chip *chip)
  536. {
  537. kfree(chip->control);
  538. chip->control = NULL;
  539. }