^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * oxfw_command.c - a part of driver for OXFW970/971 based devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014 Takashi Sakamoto
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "oxfw.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) int avc_stream_set_format(struct fw_unit *unit, enum avc_general_plug_dir dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) unsigned int pid, u8 *format, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) buf = kmalloc(len + 10, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) if (buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) buf[0] = 0x00; /* CONTROL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) buf[1] = 0xff; /* UNIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) buf[2] = 0xbf; /* EXTENDED STREAM FORMAT INFORMATION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) buf[3] = 0xc0; /* SINGLE subfunction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) buf[4] = dir; /* Plug Direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) buf[5] = 0x00; /* UNIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) buf[6] = 0x00; /* PCR (Isochronous Plug) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) buf[7] = 0xff & pid; /* Plug ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) buf[8] = 0xff; /* Padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) buf[9] = 0xff; /* Support status in response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) memcpy(buf + 10, format, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* do transaction and check buf[1-8] are the same against command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) err = fcp_avc_transaction(unit, buf, len + 10, buf, len + 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) BIT(6) | BIT(7) | BIT(8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) else if (err < len + 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) else if (buf[0] == 0x0a) /* REJECTED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int avc_stream_get_format(struct fw_unit *unit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) enum avc_general_plug_dir dir, unsigned int pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u8 *buf, unsigned int *len, unsigned int eid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned int subfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (eid == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) subfunc = 0xc0; /* SINGLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) subfunc = 0xc1; /* LIST */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) buf[0] = 0x01; /* STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) buf[1] = 0xff; /* UNIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) buf[2] = 0xbf; /* EXTENDED STREAM FORMAT INFORMATION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) buf[3] = subfunc; /* SINGLE or LIST */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) buf[4] = dir; /* Plug Direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) buf[5] = 0x00; /* Unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) buf[6] = 0x00; /* PCR (Isochronous Plug) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) buf[7] = 0xff & pid; /* Plug ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) buf[8] = 0xff; /* Padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) buf[9] = 0xff; /* support status in response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) buf[10] = 0xff & eid; /* entry ID for LIST subfunction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) buf[11] = 0xff; /* padding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* do transaction and check buf[1-7] are the same against command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) err = fcp_avc_transaction(unit, buf, 12, buf, *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) BIT(6) | BIT(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else if (err < 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) else if (buf[0] == 0x0a) /* REJECTED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) else if (buf[0] == 0x0b) /* IN TRANSITION */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) err = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* LIST subfunction has entry ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) else if ((subfunc == 0xc1) && (buf[10] != eid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* keep just stream format information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (subfunc == 0xc0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) memmove(buf, buf + 10, err - 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *len = err - 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) memmove(buf, buf + 11, err - 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *len = err - 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) enum avc_general_plug_dir dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned short pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int sfc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (amdtp_rate_table[sfc] == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (sfc == CIP_SFC_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) buf = kzalloc(8, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) buf[0] = 0x02; /* SPECIFIC INQUIRY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) buf[1] = 0xff; /* UNIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (dir == AVC_GENERAL_PLUG_DIR_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) buf[3] = 0xff & pid; /* plug id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) buf[5] = 0x07 & sfc; /* FDF-hi. AM824, frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* do transaction and check buf[1-5] are the same against command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) err = fcp_avc_transaction(unit, buf, 8, buf, 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else if (err < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }