pulse8-cec.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*
  2. * Pulse Eight HDMI CEC driver
  3. *
  4. * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version of 2 of the License, or (at your
  9. * option) any later version. See the file COPYING in the main directory of
  10. * this archive for more details.
  11. */
  12. /*
  13. * Notes:
  14. *
  15. * - Devices with firmware version < 2 do not store their configuration in
  16. * EEPROM.
  17. *
  18. * - In autonomous mode, only messages from a TV will be acknowledged, even
  19. * polling messages. Upon receiving a message from a TV, the dongle will
  20. * respond to messages from any logical address.
  21. *
  22. * - In autonomous mode, the dongle will by default reply Feature Abort
  23. * [Unrecognized Opcode] when it receives Give Device Vendor ID. It will
  24. * however observe vendor ID's reported by other devices and possibly
  25. * alter this behavior. When TV's (and TV's only) report that their vendor ID
  26. * is LG (0x00e091), the dongle will itself reply that it has the same vendor
  27. * ID, and it will respond to at least one vendor specific command.
  28. *
  29. * - In autonomous mode, the dongle is known to attempt wakeup if it receives
  30. * <User Control Pressed> ["Power On"], ["Power] or ["Power Toggle"], or if it
  31. * receives <Set Stream Path> with its own physical address. It also does this
  32. * if it receives <Vendor Specific Command> [0x03 0x00] from an LG TV.
  33. */
  34. #include <linux/completion.h>
  35. #include <linux/init.h>
  36. #include <linux/interrupt.h>
  37. #include <linux/kernel.h>
  38. #include <linux/module.h>
  39. #include <linux/workqueue.h>
  40. #include <linux/serio.h>
  41. #include <linux/slab.h>
  42. #include <linux/time.h>
  43. #include <linux/delay.h>
  44. #include <media/cec.h>
  45. MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
  46. MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver");
  47. MODULE_LICENSE("GPL");
  48. static int debug;
  49. static int persistent_config = 1;
  50. module_param(debug, int, 0644);
  51. module_param(persistent_config, int, 0644);
  52. MODULE_PARM_DESC(debug, "debug level (0-1)");
  53. MODULE_PARM_DESC(persistent_config, "read config from persistent memory (0-1)");
  54. enum pulse8_msgcodes {
  55. MSGCODE_NOTHING = 0,
  56. MSGCODE_PING,
  57. MSGCODE_TIMEOUT_ERROR,
  58. MSGCODE_HIGH_ERROR,
  59. MSGCODE_LOW_ERROR,
  60. MSGCODE_FRAME_START,
  61. MSGCODE_FRAME_DATA,
  62. MSGCODE_RECEIVE_FAILED,
  63. MSGCODE_COMMAND_ACCEPTED, /* 0x08 */
  64. MSGCODE_COMMAND_REJECTED,
  65. MSGCODE_SET_ACK_MASK,
  66. MSGCODE_TRANSMIT,
  67. MSGCODE_TRANSMIT_EOM,
  68. MSGCODE_TRANSMIT_IDLETIME,
  69. MSGCODE_TRANSMIT_ACK_POLARITY,
  70. MSGCODE_TRANSMIT_LINE_TIMEOUT,
  71. MSGCODE_TRANSMIT_SUCCEEDED, /* 0x10 */
  72. MSGCODE_TRANSMIT_FAILED_LINE,
  73. MSGCODE_TRANSMIT_FAILED_ACK,
  74. MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
  75. MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
  76. MSGCODE_FIRMWARE_VERSION,
  77. MSGCODE_START_BOOTLOADER,
  78. MSGCODE_GET_BUILDDATE,
  79. MSGCODE_SET_CONTROLLED, /* 0x18 */
  80. MSGCODE_GET_AUTO_ENABLED,
  81. MSGCODE_SET_AUTO_ENABLED,
  82. MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS,
  83. MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS,
  84. MSGCODE_GET_LOGICAL_ADDRESS_MASK,
  85. MSGCODE_SET_LOGICAL_ADDRESS_MASK,
  86. MSGCODE_GET_PHYSICAL_ADDRESS,
  87. MSGCODE_SET_PHYSICAL_ADDRESS, /* 0x20 */
  88. MSGCODE_GET_DEVICE_TYPE,
  89. MSGCODE_SET_DEVICE_TYPE,
  90. MSGCODE_GET_HDMI_VERSION,
  91. MSGCODE_SET_HDMI_VERSION,
  92. MSGCODE_GET_OSD_NAME,
  93. MSGCODE_SET_OSD_NAME,
  94. MSGCODE_WRITE_EEPROM,
  95. MSGCODE_GET_ADAPTER_TYPE, /* 0x28 */
  96. MSGCODE_SET_ACTIVE_SOURCE,
  97. MSGCODE_FRAME_EOM = 0x80,
  98. MSGCODE_FRAME_ACK = 0x40,
  99. };
  100. #define MSGSTART 0xff
  101. #define MSGEND 0xfe
  102. #define MSGESC 0xfd
  103. #define MSGOFFSET 3
  104. #define DATA_SIZE 256
  105. #define PING_PERIOD (15 * HZ)
  106. struct pulse8 {
  107. struct device *dev;
  108. struct serio *serio;
  109. struct cec_adapter *adap;
  110. unsigned int vers;
  111. struct completion cmd_done;
  112. struct work_struct work;
  113. struct delayed_work ping_eeprom_work;
  114. struct cec_msg rx_msg;
  115. u8 data[DATA_SIZE];
  116. unsigned int len;
  117. u8 buf[DATA_SIZE];
  118. unsigned int idx;
  119. bool escape;
  120. bool started;
  121. struct mutex config_lock;
  122. struct mutex write_lock;
  123. bool config_pending;
  124. bool restoring_config;
  125. bool autonomous;
  126. };
  127. static void pulse8_ping_eeprom_work_handler(struct work_struct *work);
  128. static void pulse8_irq_work_handler(struct work_struct *work)
  129. {
  130. struct pulse8 *pulse8 =
  131. container_of(work, struct pulse8, work);
  132. switch (pulse8->data[0] & 0x3f) {
  133. case MSGCODE_FRAME_DATA:
  134. cec_received_msg(pulse8->adap, &pulse8->rx_msg);
  135. break;
  136. case MSGCODE_TRANSMIT_SUCCEEDED:
  137. cec_transmit_done(pulse8->adap, CEC_TX_STATUS_OK,
  138. 0, 0, 0, 0);
  139. break;
  140. case MSGCODE_TRANSMIT_FAILED_ACK:
  141. cec_transmit_done(pulse8->adap, CEC_TX_STATUS_NACK,
  142. 0, 1, 0, 0);
  143. break;
  144. case MSGCODE_TRANSMIT_FAILED_LINE:
  145. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
  146. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
  147. cec_transmit_done(pulse8->adap, CEC_TX_STATUS_ERROR,
  148. 0, 0, 0, 1);
  149. break;
  150. }
  151. }
  152. static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
  153. unsigned int flags)
  154. {
  155. struct pulse8 *pulse8 = serio_get_drvdata(serio);
  156. if (!pulse8->started && data != MSGSTART)
  157. return IRQ_HANDLED;
  158. if (data == MSGESC) {
  159. pulse8->escape = true;
  160. return IRQ_HANDLED;
  161. }
  162. if (pulse8->escape) {
  163. data += MSGOFFSET;
  164. pulse8->escape = false;
  165. } else if (data == MSGEND) {
  166. struct cec_msg *msg = &pulse8->rx_msg;
  167. if (debug)
  168. dev_info(pulse8->dev, "received: %*ph\n",
  169. pulse8->idx, pulse8->buf);
  170. pulse8->data[0] = pulse8->buf[0];
  171. switch (pulse8->buf[0] & 0x3f) {
  172. case MSGCODE_FRAME_START:
  173. msg->len = 1;
  174. msg->msg[0] = pulse8->buf[1];
  175. break;
  176. case MSGCODE_FRAME_DATA:
  177. if (msg->len == CEC_MAX_MSG_SIZE)
  178. break;
  179. msg->msg[msg->len++] = pulse8->buf[1];
  180. if (pulse8->buf[0] & MSGCODE_FRAME_EOM)
  181. schedule_work(&pulse8->work);
  182. break;
  183. case MSGCODE_TRANSMIT_SUCCEEDED:
  184. case MSGCODE_TRANSMIT_FAILED_LINE:
  185. case MSGCODE_TRANSMIT_FAILED_ACK:
  186. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
  187. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
  188. schedule_work(&pulse8->work);
  189. break;
  190. case MSGCODE_HIGH_ERROR:
  191. case MSGCODE_LOW_ERROR:
  192. case MSGCODE_RECEIVE_FAILED:
  193. case MSGCODE_TIMEOUT_ERROR:
  194. break;
  195. case MSGCODE_COMMAND_ACCEPTED:
  196. case MSGCODE_COMMAND_REJECTED:
  197. default:
  198. if (pulse8->idx == 0)
  199. break;
  200. memcpy(pulse8->data, pulse8->buf, pulse8->idx);
  201. pulse8->len = pulse8->idx;
  202. complete(&pulse8->cmd_done);
  203. break;
  204. }
  205. pulse8->idx = 0;
  206. pulse8->started = false;
  207. return IRQ_HANDLED;
  208. } else if (data == MSGSTART) {
  209. pulse8->idx = 0;
  210. pulse8->started = true;
  211. return IRQ_HANDLED;
  212. }
  213. if (pulse8->idx >= DATA_SIZE) {
  214. dev_dbg(pulse8->dev,
  215. "throwing away %d bytes of garbage\n", pulse8->idx);
  216. pulse8->idx = 0;
  217. }
  218. pulse8->buf[pulse8->idx++] = data;
  219. return IRQ_HANDLED;
  220. }
  221. static void pulse8_disconnect(struct serio *serio)
  222. {
  223. struct pulse8 *pulse8 = serio_get_drvdata(serio);
  224. cec_unregister_adapter(pulse8->adap);
  225. cancel_delayed_work_sync(&pulse8->ping_eeprom_work);
  226. dev_info(&serio->dev, "disconnected\n");
  227. serio_close(serio);
  228. serio_set_drvdata(serio, NULL);
  229. kfree(pulse8);
  230. }
  231. static int pulse8_send(struct serio *serio, const u8 *command, u8 cmd_len)
  232. {
  233. int err = 0;
  234. err = serio_write(serio, MSGSTART);
  235. if (err)
  236. return err;
  237. for (; !err && cmd_len; command++, cmd_len--) {
  238. if (*command >= MSGESC) {
  239. err = serio_write(serio, MSGESC);
  240. if (!err)
  241. err = serio_write(serio, *command - MSGOFFSET);
  242. } else {
  243. err = serio_write(serio, *command);
  244. }
  245. }
  246. if (!err)
  247. err = serio_write(serio, MSGEND);
  248. return err;
  249. }
  250. static int pulse8_send_and_wait_once(struct pulse8 *pulse8,
  251. const u8 *cmd, u8 cmd_len,
  252. u8 response, u8 size)
  253. {
  254. int err;
  255. /*dev_info(pulse8->dev, "transmit: %*ph\n", cmd_len, cmd);*/
  256. init_completion(&pulse8->cmd_done);
  257. err = pulse8_send(pulse8->serio, cmd, cmd_len);
  258. if (err)
  259. return err;
  260. if (!wait_for_completion_timeout(&pulse8->cmd_done, HZ))
  261. return -ETIMEDOUT;
  262. if ((pulse8->data[0] & 0x3f) == MSGCODE_COMMAND_REJECTED &&
  263. cmd[0] != MSGCODE_SET_CONTROLLED &&
  264. cmd[0] != MSGCODE_SET_AUTO_ENABLED &&
  265. cmd[0] != MSGCODE_GET_BUILDDATE)
  266. return -ENOTTY;
  267. if (response &&
  268. ((pulse8->data[0] & 0x3f) != response || pulse8->len < size + 1)) {
  269. dev_info(pulse8->dev, "transmit: failed %02x\n",
  270. pulse8->data[0] & 0x3f);
  271. return -EIO;
  272. }
  273. return 0;
  274. }
  275. static int pulse8_send_and_wait(struct pulse8 *pulse8,
  276. const u8 *cmd, u8 cmd_len, u8 response, u8 size)
  277. {
  278. u8 cmd_sc[2];
  279. int err;
  280. mutex_lock(&pulse8->write_lock);
  281. err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len, response, size);
  282. if (err == -ENOTTY) {
  283. cmd_sc[0] = MSGCODE_SET_CONTROLLED;
  284. cmd_sc[1] = 1;
  285. err = pulse8_send_and_wait_once(pulse8, cmd_sc, 2,
  286. MSGCODE_COMMAND_ACCEPTED, 1);
  287. if (err)
  288. goto unlock;
  289. err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len,
  290. response, size);
  291. }
  292. unlock:
  293. mutex_unlock(&pulse8->write_lock);
  294. return err == -ENOTTY ? -EIO : err;
  295. }
  296. static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio,
  297. struct cec_log_addrs *log_addrs, u16 *pa)
  298. {
  299. u8 *data = pulse8->data + 1;
  300. u8 cmd[2];
  301. int err;
  302. struct tm tm;
  303. time_t date;
  304. pulse8->vers = 0;
  305. cmd[0] = MSGCODE_FIRMWARE_VERSION;
  306. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
  307. if (err)
  308. return err;
  309. pulse8->vers = (data[0] << 8) | data[1];
  310. dev_info(pulse8->dev, "Firmware version %04x\n", pulse8->vers);
  311. if (pulse8->vers < 2) {
  312. *pa = CEC_PHYS_ADDR_INVALID;
  313. return 0;
  314. }
  315. cmd[0] = MSGCODE_GET_BUILDDATE;
  316. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 4);
  317. if (err)
  318. return err;
  319. date = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
  320. time_to_tm(date, 0, &tm);
  321. dev_info(pulse8->dev, "Firmware build date %04ld.%02d.%02d %02d:%02d:%02d\n",
  322. tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  323. tm.tm_hour, tm.tm_min, tm.tm_sec);
  324. dev_dbg(pulse8->dev, "Persistent config:\n");
  325. cmd[0] = MSGCODE_GET_AUTO_ENABLED;
  326. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  327. if (err)
  328. return err;
  329. pulse8->autonomous = data[0];
  330. dev_dbg(pulse8->dev, "Autonomous mode: %s",
  331. data[0] ? "on" : "off");
  332. cmd[0] = MSGCODE_GET_DEVICE_TYPE;
  333. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  334. if (err)
  335. return err;
  336. log_addrs->primary_device_type[0] = data[0];
  337. dev_dbg(pulse8->dev, "Primary device type: %d\n", data[0]);
  338. switch (log_addrs->primary_device_type[0]) {
  339. case CEC_OP_PRIM_DEVTYPE_TV:
  340. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV;
  341. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV;
  342. break;
  343. case CEC_OP_PRIM_DEVTYPE_RECORD:
  344. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD;
  345. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD;
  346. break;
  347. case CEC_OP_PRIM_DEVTYPE_TUNER:
  348. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER;
  349. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER;
  350. break;
  351. case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
  352. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
  353. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
  354. break;
  355. case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
  356. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
  357. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
  358. break;
  359. case CEC_OP_PRIM_DEVTYPE_SWITCH:
  360. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
  361. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
  362. break;
  363. case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
  364. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_SPECIFIC;
  365. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
  366. break;
  367. default:
  368. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
  369. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
  370. dev_info(pulse8->dev, "Unknown Primary Device Type: %d\n",
  371. log_addrs->primary_device_type[0]);
  372. break;
  373. }
  374. cmd[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK;
  375. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
  376. if (err)
  377. return err;
  378. log_addrs->log_addr_mask = (data[0] << 8) | data[1];
  379. dev_dbg(pulse8->dev, "Logical address ACK mask: %x\n",
  380. log_addrs->log_addr_mask);
  381. if (log_addrs->log_addr_mask)
  382. log_addrs->num_log_addrs = 1;
  383. cmd[0] = MSGCODE_GET_PHYSICAL_ADDRESS;
  384. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  385. if (err)
  386. return err;
  387. *pa = (data[0] << 8) | data[1];
  388. dev_dbg(pulse8->dev, "Physical address: %x.%x.%x.%x\n",
  389. cec_phys_addr_exp(*pa));
  390. cmd[0] = MSGCODE_GET_HDMI_VERSION;
  391. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  392. if (err)
  393. return err;
  394. log_addrs->cec_version = data[0];
  395. dev_dbg(pulse8->dev, "CEC version: %d\n", log_addrs->cec_version);
  396. cmd[0] = MSGCODE_GET_OSD_NAME;
  397. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 0);
  398. if (err)
  399. return err;
  400. strncpy(log_addrs->osd_name, data, 13);
  401. dev_dbg(pulse8->dev, "OSD name: %s\n", log_addrs->osd_name);
  402. return 0;
  403. }
  404. static int pulse8_apply_persistent_config(struct pulse8 *pulse8,
  405. struct cec_log_addrs *log_addrs,
  406. u16 pa)
  407. {
  408. int err;
  409. err = cec_s_log_addrs(pulse8->adap, log_addrs, false);
  410. if (err)
  411. return err;
  412. cec_s_phys_addr(pulse8->adap, pa, false);
  413. return 0;
  414. }
  415. static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
  416. {
  417. struct pulse8 *pulse8 = adap->priv;
  418. u8 cmd[16];
  419. int err;
  420. cmd[0] = MSGCODE_SET_CONTROLLED;
  421. cmd[1] = enable;
  422. err = pulse8_send_and_wait(pulse8, cmd, 2,
  423. MSGCODE_COMMAND_ACCEPTED, 1);
  424. return enable ? err : 0;
  425. }
  426. static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
  427. {
  428. struct pulse8 *pulse8 = adap->priv;
  429. u16 mask = 0;
  430. u16 pa = adap->phys_addr;
  431. u8 cmd[16];
  432. int err = 0;
  433. mutex_lock(&pulse8->config_lock);
  434. if (log_addr != CEC_LOG_ADDR_INVALID)
  435. mask = 1 << log_addr;
  436. cmd[0] = MSGCODE_SET_ACK_MASK;
  437. cmd[1] = mask >> 8;
  438. cmd[2] = mask & 0xff;
  439. err = pulse8_send_and_wait(pulse8, cmd, 3,
  440. MSGCODE_COMMAND_ACCEPTED, 0);
  441. if ((err && mask != 0) || pulse8->restoring_config)
  442. goto unlock;
  443. cmd[0] = MSGCODE_SET_AUTO_ENABLED;
  444. cmd[1] = log_addr == CEC_LOG_ADDR_INVALID ? 0 : 1;
  445. err = pulse8_send_and_wait(pulse8, cmd, 2,
  446. MSGCODE_COMMAND_ACCEPTED, 0);
  447. if (err)
  448. goto unlock;
  449. pulse8->autonomous = cmd[1];
  450. if (log_addr == CEC_LOG_ADDR_INVALID)
  451. goto unlock;
  452. cmd[0] = MSGCODE_SET_DEVICE_TYPE;
  453. cmd[1] = adap->log_addrs.primary_device_type[0];
  454. err = pulse8_send_and_wait(pulse8, cmd, 2,
  455. MSGCODE_COMMAND_ACCEPTED, 0);
  456. if (err)
  457. goto unlock;
  458. switch (adap->log_addrs.primary_device_type[0]) {
  459. case CEC_OP_PRIM_DEVTYPE_TV:
  460. mask = CEC_LOG_ADDR_MASK_TV;
  461. break;
  462. case CEC_OP_PRIM_DEVTYPE_RECORD:
  463. mask = CEC_LOG_ADDR_MASK_RECORD;
  464. break;
  465. case CEC_OP_PRIM_DEVTYPE_TUNER:
  466. mask = CEC_LOG_ADDR_MASK_TUNER;
  467. break;
  468. case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
  469. mask = CEC_LOG_ADDR_MASK_PLAYBACK;
  470. break;
  471. case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
  472. mask = CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
  473. break;
  474. case CEC_OP_PRIM_DEVTYPE_SWITCH:
  475. mask = CEC_LOG_ADDR_MASK_UNREGISTERED;
  476. break;
  477. case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
  478. mask = CEC_LOG_ADDR_MASK_SPECIFIC;
  479. break;
  480. default:
  481. mask = 0;
  482. break;
  483. }
  484. cmd[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK;
  485. cmd[1] = mask >> 8;
  486. cmd[2] = mask & 0xff;
  487. err = pulse8_send_and_wait(pulse8, cmd, 3,
  488. MSGCODE_COMMAND_ACCEPTED, 0);
  489. if (err)
  490. goto unlock;
  491. cmd[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS;
  492. cmd[1] = log_addr;
  493. err = pulse8_send_and_wait(pulse8, cmd, 2,
  494. MSGCODE_COMMAND_ACCEPTED, 0);
  495. if (err)
  496. goto unlock;
  497. cmd[0] = MSGCODE_SET_PHYSICAL_ADDRESS;
  498. cmd[1] = pa >> 8;
  499. cmd[2] = pa & 0xff;
  500. err = pulse8_send_and_wait(pulse8, cmd, 3,
  501. MSGCODE_COMMAND_ACCEPTED, 0);
  502. if (err)
  503. goto unlock;
  504. cmd[0] = MSGCODE_SET_HDMI_VERSION;
  505. cmd[1] = adap->log_addrs.cec_version;
  506. err = pulse8_send_and_wait(pulse8, cmd, 2,
  507. MSGCODE_COMMAND_ACCEPTED, 0);
  508. if (err)
  509. goto unlock;
  510. if (adap->log_addrs.osd_name[0]) {
  511. size_t osd_len = strlen(adap->log_addrs.osd_name);
  512. char *osd_str = cmd + 1;
  513. cmd[0] = MSGCODE_SET_OSD_NAME;
  514. strncpy(cmd + 1, adap->log_addrs.osd_name, 13);
  515. if (osd_len < 4) {
  516. memset(osd_str + osd_len, ' ', 4 - osd_len);
  517. osd_len = 4;
  518. osd_str[osd_len] = '\0';
  519. strcpy(adap->log_addrs.osd_name, osd_str);
  520. }
  521. err = pulse8_send_and_wait(pulse8, cmd, 1 + osd_len,
  522. MSGCODE_COMMAND_ACCEPTED, 0);
  523. if (err)
  524. goto unlock;
  525. }
  526. unlock:
  527. if (pulse8->restoring_config)
  528. pulse8->restoring_config = false;
  529. else
  530. pulse8->config_pending = true;
  531. mutex_unlock(&pulse8->config_lock);
  532. return err;
  533. }
  534. static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
  535. u32 signal_free_time, struct cec_msg *msg)
  536. {
  537. struct pulse8 *pulse8 = adap->priv;
  538. u8 cmd[2];
  539. unsigned int i;
  540. int err;
  541. cmd[0] = MSGCODE_TRANSMIT_IDLETIME;
  542. cmd[1] = signal_free_time;
  543. err = pulse8_send_and_wait(pulse8, cmd, 2,
  544. MSGCODE_COMMAND_ACCEPTED, 1);
  545. cmd[0] = MSGCODE_TRANSMIT_ACK_POLARITY;
  546. cmd[1] = cec_msg_is_broadcast(msg);
  547. if (!err)
  548. err = pulse8_send_and_wait(pulse8, cmd, 2,
  549. MSGCODE_COMMAND_ACCEPTED, 1);
  550. cmd[0] = msg->len == 1 ? MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
  551. cmd[1] = msg->msg[0];
  552. if (!err)
  553. err = pulse8_send_and_wait(pulse8, cmd, 2,
  554. MSGCODE_COMMAND_ACCEPTED, 1);
  555. if (!err && msg->len > 1) {
  556. cmd[0] = msg->len == 2 ? MSGCODE_TRANSMIT_EOM :
  557. MSGCODE_TRANSMIT;
  558. cmd[1] = msg->msg[1];
  559. err = pulse8_send_and_wait(pulse8, cmd, 2,
  560. MSGCODE_COMMAND_ACCEPTED, 1);
  561. for (i = 0; !err && i + 2 < msg->len; i++) {
  562. cmd[0] = (i + 2 == msg->len - 1) ?
  563. MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
  564. cmd[1] = msg->msg[i + 2];
  565. err = pulse8_send_and_wait(pulse8, cmd, 2,
  566. MSGCODE_COMMAND_ACCEPTED, 1);
  567. }
  568. }
  569. return err;
  570. }
  571. static int pulse8_received(struct cec_adapter *adap, struct cec_msg *msg)
  572. {
  573. return -ENOMSG;
  574. }
  575. static const struct cec_adap_ops pulse8_cec_adap_ops = {
  576. .adap_enable = pulse8_cec_adap_enable,
  577. .adap_log_addr = pulse8_cec_adap_log_addr,
  578. .adap_transmit = pulse8_cec_adap_transmit,
  579. .received = pulse8_received,
  580. };
  581. static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
  582. {
  583. u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR |
  584. CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL;
  585. struct pulse8 *pulse8;
  586. int err = -ENOMEM;
  587. struct cec_log_addrs log_addrs = {};
  588. u16 pa = CEC_PHYS_ADDR_INVALID;
  589. pulse8 = kzalloc(sizeof(*pulse8), GFP_KERNEL);
  590. if (!pulse8)
  591. return -ENOMEM;
  592. pulse8->serio = serio;
  593. pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8,
  594. "HDMI CEC", caps, 1);
  595. err = PTR_ERR_OR_ZERO(pulse8->adap);
  596. if (err < 0)
  597. goto free_device;
  598. pulse8->dev = &serio->dev;
  599. serio_set_drvdata(serio, pulse8);
  600. INIT_WORK(&pulse8->work, pulse8_irq_work_handler);
  601. mutex_init(&pulse8->write_lock);
  602. mutex_init(&pulse8->config_lock);
  603. pulse8->config_pending = false;
  604. err = serio_open(serio, drv);
  605. if (err)
  606. goto delete_adap;
  607. err = pulse8_setup(pulse8, serio, &log_addrs, &pa);
  608. if (err)
  609. goto close_serio;
  610. err = cec_register_adapter(pulse8->adap, &serio->dev);
  611. if (err < 0)
  612. goto close_serio;
  613. pulse8->dev = &pulse8->adap->devnode.dev;
  614. if (persistent_config && pulse8->autonomous) {
  615. err = pulse8_apply_persistent_config(pulse8, &log_addrs, pa);
  616. if (err)
  617. goto close_serio;
  618. pulse8->restoring_config = true;
  619. }
  620. INIT_DELAYED_WORK(&pulse8->ping_eeprom_work,
  621. pulse8_ping_eeprom_work_handler);
  622. schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
  623. return 0;
  624. close_serio:
  625. serio_close(serio);
  626. delete_adap:
  627. cec_delete_adapter(pulse8->adap);
  628. serio_set_drvdata(serio, NULL);
  629. free_device:
  630. kfree(pulse8);
  631. return err;
  632. }
  633. static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
  634. {
  635. struct pulse8 *pulse8 =
  636. container_of(work, struct pulse8, ping_eeprom_work.work);
  637. u8 cmd;
  638. schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
  639. cmd = MSGCODE_PING;
  640. pulse8_send_and_wait(pulse8, &cmd, 1,
  641. MSGCODE_COMMAND_ACCEPTED, 0);
  642. if (pulse8->vers < 2)
  643. return;
  644. mutex_lock(&pulse8->config_lock);
  645. if (pulse8->config_pending && persistent_config) {
  646. dev_dbg(pulse8->dev, "writing pending config to EEPROM\n");
  647. cmd = MSGCODE_WRITE_EEPROM;
  648. if (pulse8_send_and_wait(pulse8, &cmd, 1,
  649. MSGCODE_COMMAND_ACCEPTED, 0))
  650. dev_info(pulse8->dev, "failed to write pending config to EEPROM\n");
  651. else
  652. pulse8->config_pending = false;
  653. }
  654. mutex_unlock(&pulse8->config_lock);
  655. }
  656. static struct serio_device_id pulse8_serio_ids[] = {
  657. {
  658. .type = SERIO_RS232,
  659. .proto = SERIO_PULSE8_CEC,
  660. .id = SERIO_ANY,
  661. .extra = SERIO_ANY,
  662. },
  663. { 0 }
  664. };
  665. MODULE_DEVICE_TABLE(serio, pulse8_serio_ids);
  666. static struct serio_driver pulse8_drv = {
  667. .driver = {
  668. .name = "pulse8-cec",
  669. },
  670. .description = "Pulse Eight HDMI CEC driver",
  671. .id_table = pulse8_serio_ids,
  672. .interrupt = pulse8_interrupt,
  673. .connect = pulse8_connect,
  674. .disconnect = pulse8_disconnect,
  675. };
  676. module_serio_driver(pulse8_drv);