15b59d809STakashi Sakamoto /* 25b59d809STakashi Sakamoto * oxfw_command.c - a part of driver for OXFW970/971 based devices 35b59d809STakashi Sakamoto * 45b59d809STakashi Sakamoto * Copyright (c) 2014 Takashi Sakamoto 55b59d809STakashi Sakamoto * 65b59d809STakashi Sakamoto * Licensed under the terms of the GNU General Public License, version 2. 75b59d809STakashi Sakamoto */ 85b59d809STakashi Sakamoto 95b59d809STakashi Sakamoto #include "oxfw.h" 105b59d809STakashi Sakamoto 115b59d809STakashi Sakamoto int avc_stream_set_format(struct fw_unit *unit, enum avc_general_plug_dir dir, 125b59d809STakashi Sakamoto unsigned int pid, u8 *format, unsigned int len) 135b59d809STakashi Sakamoto { 145b59d809STakashi Sakamoto u8 *buf; 155b59d809STakashi Sakamoto int err; 165b59d809STakashi Sakamoto 175b59d809STakashi Sakamoto buf = kmalloc(len + 10, GFP_KERNEL); 185b59d809STakashi Sakamoto if (buf == NULL) 195b59d809STakashi Sakamoto return -ENOMEM; 205b59d809STakashi Sakamoto 215b59d809STakashi Sakamoto buf[0] = 0x00; /* CONTROL */ 225b59d809STakashi Sakamoto buf[1] = 0xff; /* UNIT */ 235b59d809STakashi Sakamoto buf[2] = 0xbf; /* EXTENDED STREAM FORMAT INFORMATION */ 245b59d809STakashi Sakamoto buf[3] = 0xc0; /* SINGLE subfunction */ 255b59d809STakashi Sakamoto buf[4] = dir; /* Plug Direction */ 265b59d809STakashi Sakamoto buf[5] = 0x00; /* UNIT */ 275b59d809STakashi Sakamoto buf[6] = 0x00; /* PCR (Isochronous Plug) */ 285b59d809STakashi Sakamoto buf[7] = 0xff & pid; /* Plug ID */ 295b59d809STakashi Sakamoto buf[8] = 0xff; /* Padding */ 305b59d809STakashi Sakamoto buf[9] = 0xff; /* Support status in response */ 315b59d809STakashi Sakamoto memcpy(buf + 10, format, len); 325b59d809STakashi Sakamoto 335b59d809STakashi Sakamoto /* do transaction and check buf[1-8] are the same against command */ 345b59d809STakashi Sakamoto err = fcp_avc_transaction(unit, buf, len + 10, buf, len + 10, 355b59d809STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 365b59d809STakashi Sakamoto BIT(6) | BIT(7) | BIT(8)); 377e1621deSTakashi Sakamoto if (err < 0) 387e1621deSTakashi Sakamoto ; 397e1621deSTakashi Sakamoto else if (err < len + 10) 405b59d809STakashi Sakamoto err = -EIO; 415b59d809STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 425b59d809STakashi Sakamoto err = -ENOSYS; 435b59d809STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 445b59d809STakashi Sakamoto err = -EINVAL; 455b59d809STakashi Sakamoto else 465b59d809STakashi Sakamoto err = 0; 475b59d809STakashi Sakamoto 485b59d809STakashi Sakamoto kfree(buf); 495b59d809STakashi Sakamoto 505b59d809STakashi Sakamoto return err; 515b59d809STakashi Sakamoto } 525b59d809STakashi Sakamoto 535b59d809STakashi Sakamoto int avc_stream_get_format(struct fw_unit *unit, 545b59d809STakashi Sakamoto enum avc_general_plug_dir dir, unsigned int pid, 555b59d809STakashi Sakamoto u8 *buf, unsigned int *len, unsigned int eid) 565b59d809STakashi Sakamoto { 575b59d809STakashi Sakamoto unsigned int subfunc; 585b59d809STakashi Sakamoto int err; 595b59d809STakashi Sakamoto 605b59d809STakashi Sakamoto if (eid == 0xff) 615b59d809STakashi Sakamoto subfunc = 0xc0; /* SINGLE */ 625b59d809STakashi Sakamoto else 635b59d809STakashi Sakamoto subfunc = 0xc1; /* LIST */ 645b59d809STakashi Sakamoto 655b59d809STakashi Sakamoto buf[0] = 0x01; /* STATUS */ 665b59d809STakashi Sakamoto buf[1] = 0xff; /* UNIT */ 675b59d809STakashi Sakamoto buf[2] = 0xbf; /* EXTENDED STREAM FORMAT INFORMATION */ 685b59d809STakashi Sakamoto buf[3] = subfunc; /* SINGLE or LIST */ 695b59d809STakashi Sakamoto buf[4] = dir; /* Plug Direction */ 705b59d809STakashi Sakamoto buf[5] = 0x00; /* Unit */ 715b59d809STakashi Sakamoto buf[6] = 0x00; /* PCR (Isochronous Plug) */ 725b59d809STakashi Sakamoto buf[7] = 0xff & pid; /* Plug ID */ 735b59d809STakashi Sakamoto buf[8] = 0xff; /* Padding */ 745b59d809STakashi Sakamoto buf[9] = 0xff; /* support status in response */ 755b59d809STakashi Sakamoto buf[10] = 0xff & eid; /* entry ID for LIST subfunction */ 765b59d809STakashi Sakamoto buf[11] = 0xff; /* padding */ 775b59d809STakashi Sakamoto 785b59d809STakashi Sakamoto /* do transaction and check buf[1-7] are the same against command */ 795b59d809STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 12, buf, *len, 805b59d809STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | 815b59d809STakashi Sakamoto BIT(6) | BIT(7)); 827e1621deSTakashi Sakamoto if (err < 0) 837e1621deSTakashi Sakamoto ; 847e1621deSTakashi Sakamoto else if (err < 12) 855b59d809STakashi Sakamoto err = -EIO; 865b59d809STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 875b59d809STakashi Sakamoto err = -ENOSYS; 885b59d809STakashi Sakamoto else if (buf[0] == 0x0a) /* REJECTED */ 895b59d809STakashi Sakamoto err = -EINVAL; 905b59d809STakashi Sakamoto else if (buf[0] == 0x0b) /* IN TRANSITION */ 915b59d809STakashi Sakamoto err = -EAGAIN; 925b59d809STakashi Sakamoto /* LIST subfunction has entry ID */ 935b59d809STakashi Sakamoto else if ((subfunc == 0xc1) && (buf[10] != eid)) 945b59d809STakashi Sakamoto err = -EIO; 955b59d809STakashi Sakamoto if (err < 0) 965b59d809STakashi Sakamoto goto end; 975b59d809STakashi Sakamoto 985b59d809STakashi Sakamoto /* keep just stream format information */ 995b59d809STakashi Sakamoto if (subfunc == 0xc0) { 1005b59d809STakashi Sakamoto memmove(buf, buf + 10, err - 10); 1015b59d809STakashi Sakamoto *len = err - 10; 1025b59d809STakashi Sakamoto } else { 1035b59d809STakashi Sakamoto memmove(buf, buf + 11, err - 11); 1045b59d809STakashi Sakamoto *len = err - 11; 1055b59d809STakashi Sakamoto } 1065b59d809STakashi Sakamoto 1075b59d809STakashi Sakamoto err = 0; 1085b59d809STakashi Sakamoto end: 1095b59d809STakashi Sakamoto return err; 1105b59d809STakashi Sakamoto } 1115b59d809STakashi Sakamoto 1125b59d809STakashi Sakamoto int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate, 1135b59d809STakashi Sakamoto enum avc_general_plug_dir dir, 1145b59d809STakashi Sakamoto unsigned short pid) 1155b59d809STakashi Sakamoto { 1165b59d809STakashi Sakamoto unsigned int sfc; 1175b59d809STakashi Sakamoto u8 *buf; 1185b59d809STakashi Sakamoto int err; 1195b59d809STakashi Sakamoto 1205b59d809STakashi Sakamoto for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) { 1215b59d809STakashi Sakamoto if (amdtp_rate_table[sfc] == rate) 1225b59d809STakashi Sakamoto break; 1235b59d809STakashi Sakamoto } 1245b59d809STakashi Sakamoto if (sfc == CIP_SFC_COUNT) 1255b59d809STakashi Sakamoto return -EINVAL; 1265b59d809STakashi Sakamoto 1275b59d809STakashi Sakamoto buf = kzalloc(8, GFP_KERNEL); 1285b59d809STakashi Sakamoto if (buf == NULL) 1295b59d809STakashi Sakamoto return -ENOMEM; 1305b59d809STakashi Sakamoto 1315b59d809STakashi Sakamoto buf[0] = 0x02; /* SPECIFIC INQUIRY */ 1325b59d809STakashi Sakamoto buf[1] = 0xff; /* UNIT */ 1335b59d809STakashi Sakamoto if (dir == AVC_GENERAL_PLUG_DIR_IN) 1345b59d809STakashi Sakamoto buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ 1355b59d809STakashi Sakamoto else 1365b59d809STakashi Sakamoto buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */ 1375b59d809STakashi Sakamoto buf[3] = 0xff & pid; /* plug id */ 1385b59d809STakashi Sakamoto buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */ 1395b59d809STakashi Sakamoto buf[5] = 0x07 & sfc; /* FDF-hi. AM824, frequency */ 1405b59d809STakashi Sakamoto buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used) */ 1415b59d809STakashi Sakamoto buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */ 1425b59d809STakashi Sakamoto 1435b59d809STakashi Sakamoto /* do transaction and check buf[1-5] are the same against command */ 1445b59d809STakashi Sakamoto err = fcp_avc_transaction(unit, buf, 8, buf, 8, 1455b59d809STakashi Sakamoto BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); 1467e1621deSTakashi Sakamoto if (err < 0) 1477e1621deSTakashi Sakamoto ; 1487e1621deSTakashi Sakamoto else if (err < 8) 1495b59d809STakashi Sakamoto err = -EIO; 1505b59d809STakashi Sakamoto else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 1515b59d809STakashi Sakamoto err = -ENOSYS; 1525b59d809STakashi Sakamoto if (err < 0) 1535b59d809STakashi Sakamoto goto end; 1545b59d809STakashi Sakamoto 1555b59d809STakashi Sakamoto err = 0; 1565b59d809STakashi Sakamoto end: 1575b59d809STakashi Sakamoto kfree(buf); 1585b59d809STakashi Sakamoto return err; 1595b59d809STakashi Sakamoto } 160