pulse8-cec.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  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;
  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_attempt_done(pulse8->adap, CEC_TX_STATUS_OK);
  138. break;
  139. case MSGCODE_TRANSMIT_FAILED_ACK:
  140. cec_transmit_attempt_done(pulse8->adap, CEC_TX_STATUS_NACK);
  141. break;
  142. case MSGCODE_TRANSMIT_FAILED_LINE:
  143. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
  144. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
  145. cec_transmit_attempt_done(pulse8->adap, CEC_TX_STATUS_ERROR);
  146. break;
  147. }
  148. }
  149. static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
  150. unsigned int flags)
  151. {
  152. struct pulse8 *pulse8 = serio_get_drvdata(serio);
  153. if (!pulse8->started && data != MSGSTART)
  154. return IRQ_HANDLED;
  155. if (data == MSGESC) {
  156. pulse8->escape = true;
  157. return IRQ_HANDLED;
  158. }
  159. if (pulse8->escape) {
  160. data += MSGOFFSET;
  161. pulse8->escape = false;
  162. } else if (data == MSGEND) {
  163. struct cec_msg *msg = &pulse8->rx_msg;
  164. if (debug)
  165. dev_info(pulse8->dev, "received: %*ph\n",
  166. pulse8->idx, pulse8->buf);
  167. pulse8->data[0] = pulse8->buf[0];
  168. switch (pulse8->buf[0] & 0x3f) {
  169. case MSGCODE_FRAME_START:
  170. msg->len = 1;
  171. msg->msg[0] = pulse8->buf[1];
  172. break;
  173. case MSGCODE_FRAME_DATA:
  174. if (msg->len == CEC_MAX_MSG_SIZE)
  175. break;
  176. msg->msg[msg->len++] = pulse8->buf[1];
  177. if (pulse8->buf[0] & MSGCODE_FRAME_EOM)
  178. schedule_work(&pulse8->work);
  179. break;
  180. case MSGCODE_TRANSMIT_SUCCEEDED:
  181. case MSGCODE_TRANSMIT_FAILED_LINE:
  182. case MSGCODE_TRANSMIT_FAILED_ACK:
  183. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
  184. case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
  185. schedule_work(&pulse8->work);
  186. break;
  187. case MSGCODE_HIGH_ERROR:
  188. case MSGCODE_LOW_ERROR:
  189. case MSGCODE_RECEIVE_FAILED:
  190. case MSGCODE_TIMEOUT_ERROR:
  191. break;
  192. case MSGCODE_COMMAND_ACCEPTED:
  193. case MSGCODE_COMMAND_REJECTED:
  194. default:
  195. if (pulse8->idx == 0)
  196. break;
  197. memcpy(pulse8->data, pulse8->buf, pulse8->idx);
  198. pulse8->len = pulse8->idx;
  199. complete(&pulse8->cmd_done);
  200. break;
  201. }
  202. pulse8->idx = 0;
  203. pulse8->started = false;
  204. return IRQ_HANDLED;
  205. } else if (data == MSGSTART) {
  206. pulse8->idx = 0;
  207. pulse8->started = true;
  208. return IRQ_HANDLED;
  209. }
  210. if (pulse8->idx >= DATA_SIZE) {
  211. dev_dbg(pulse8->dev,
  212. "throwing away %d bytes of garbage\n", pulse8->idx);
  213. pulse8->idx = 0;
  214. }
  215. pulse8->buf[pulse8->idx++] = data;
  216. return IRQ_HANDLED;
  217. }
  218. static void pulse8_disconnect(struct serio *serio)
  219. {
  220. struct pulse8 *pulse8 = serio_get_drvdata(serio);
  221. cec_unregister_adapter(pulse8->adap);
  222. cancel_delayed_work_sync(&pulse8->ping_eeprom_work);
  223. dev_info(&serio->dev, "disconnected\n");
  224. serio_close(serio);
  225. serio_set_drvdata(serio, NULL);
  226. kfree(pulse8);
  227. }
  228. static int pulse8_send(struct serio *serio, const u8 *command, u8 cmd_len)
  229. {
  230. int err = 0;
  231. err = serio_write(serio, MSGSTART);
  232. if (err)
  233. return err;
  234. for (; !err && cmd_len; command++, cmd_len--) {
  235. if (*command >= MSGESC) {
  236. err = serio_write(serio, MSGESC);
  237. if (!err)
  238. err = serio_write(serio, *command - MSGOFFSET);
  239. } else {
  240. err = serio_write(serio, *command);
  241. }
  242. }
  243. if (!err)
  244. err = serio_write(serio, MSGEND);
  245. return err;
  246. }
  247. static int pulse8_send_and_wait_once(struct pulse8 *pulse8,
  248. const u8 *cmd, u8 cmd_len,
  249. u8 response, u8 size)
  250. {
  251. int err;
  252. /*dev_info(pulse8->dev, "transmit: %*ph\n", cmd_len, cmd);*/
  253. init_completion(&pulse8->cmd_done);
  254. err = pulse8_send(pulse8->serio, cmd, cmd_len);
  255. if (err)
  256. return err;
  257. if (!wait_for_completion_timeout(&pulse8->cmd_done, HZ))
  258. return -ETIMEDOUT;
  259. if ((pulse8->data[0] & 0x3f) == MSGCODE_COMMAND_REJECTED &&
  260. cmd[0] != MSGCODE_SET_CONTROLLED &&
  261. cmd[0] != MSGCODE_SET_AUTO_ENABLED &&
  262. cmd[0] != MSGCODE_GET_BUILDDATE)
  263. return -ENOTTY;
  264. if (response &&
  265. ((pulse8->data[0] & 0x3f) != response || pulse8->len < size + 1)) {
  266. dev_info(pulse8->dev, "transmit: failed %02x\n",
  267. pulse8->data[0] & 0x3f);
  268. return -EIO;
  269. }
  270. return 0;
  271. }
  272. static int pulse8_send_and_wait(struct pulse8 *pulse8,
  273. const u8 *cmd, u8 cmd_len, u8 response, u8 size)
  274. {
  275. u8 cmd_sc[2];
  276. int err;
  277. mutex_lock(&pulse8->write_lock);
  278. err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len, response, size);
  279. if (err == -ENOTTY) {
  280. cmd_sc[0] = MSGCODE_SET_CONTROLLED;
  281. cmd_sc[1] = 1;
  282. err = pulse8_send_and_wait_once(pulse8, cmd_sc, 2,
  283. MSGCODE_COMMAND_ACCEPTED, 1);
  284. if (err)
  285. goto unlock;
  286. err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len,
  287. response, size);
  288. }
  289. unlock:
  290. mutex_unlock(&pulse8->write_lock);
  291. return err == -ENOTTY ? -EIO : err;
  292. }
  293. static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio,
  294. struct cec_log_addrs *log_addrs, u16 *pa)
  295. {
  296. u8 *data = pulse8->data + 1;
  297. u8 cmd[2];
  298. int err;
  299. struct tm tm;
  300. time64_t date;
  301. pulse8->vers = 0;
  302. cmd[0] = MSGCODE_FIRMWARE_VERSION;
  303. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
  304. if (err)
  305. return err;
  306. pulse8->vers = (data[0] << 8) | data[1];
  307. dev_info(pulse8->dev, "Firmware version %04x\n", pulse8->vers);
  308. if (pulse8->vers < 2) {
  309. *pa = CEC_PHYS_ADDR_INVALID;
  310. return 0;
  311. }
  312. cmd[0] = MSGCODE_GET_BUILDDATE;
  313. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 4);
  314. if (err)
  315. return err;
  316. date = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
  317. time64_to_tm(date, 0, &tm);
  318. dev_info(pulse8->dev, "Firmware build date %04ld.%02d.%02d %02d:%02d:%02d\n",
  319. tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  320. tm.tm_hour, tm.tm_min, tm.tm_sec);
  321. dev_dbg(pulse8->dev, "Persistent config:\n");
  322. cmd[0] = MSGCODE_GET_AUTO_ENABLED;
  323. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  324. if (err)
  325. return err;
  326. pulse8->autonomous = data[0];
  327. dev_dbg(pulse8->dev, "Autonomous mode: %s",
  328. data[0] ? "on" : "off");
  329. cmd[0] = MSGCODE_GET_DEVICE_TYPE;
  330. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  331. if (err)
  332. return err;
  333. log_addrs->primary_device_type[0] = data[0];
  334. dev_dbg(pulse8->dev, "Primary device type: %d\n", data[0]);
  335. switch (log_addrs->primary_device_type[0]) {
  336. case CEC_OP_PRIM_DEVTYPE_TV:
  337. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV;
  338. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV;
  339. break;
  340. case CEC_OP_PRIM_DEVTYPE_RECORD:
  341. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD;
  342. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD;
  343. break;
  344. case CEC_OP_PRIM_DEVTYPE_TUNER:
  345. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER;
  346. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER;
  347. break;
  348. case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
  349. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
  350. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
  351. break;
  352. case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
  353. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
  354. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
  355. break;
  356. case CEC_OP_PRIM_DEVTYPE_SWITCH:
  357. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
  358. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
  359. break;
  360. case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
  361. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_SPECIFIC;
  362. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
  363. break;
  364. default:
  365. log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
  366. log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
  367. dev_info(pulse8->dev, "Unknown Primary Device Type: %d\n",
  368. log_addrs->primary_device_type[0]);
  369. break;
  370. }
  371. cmd[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK;
  372. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
  373. if (err)
  374. return err;
  375. log_addrs->log_addr_mask = (data[0] << 8) | data[1];
  376. dev_dbg(pulse8->dev, "Logical address ACK mask: %x\n",
  377. log_addrs->log_addr_mask);
  378. if (log_addrs->log_addr_mask)
  379. log_addrs->num_log_addrs = 1;
  380. cmd[0] = MSGCODE_GET_PHYSICAL_ADDRESS;
  381. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  382. if (err)
  383. return err;
  384. *pa = (data[0] << 8) | data[1];
  385. dev_dbg(pulse8->dev, "Physical address: %x.%x.%x.%x\n",
  386. cec_phys_addr_exp(*pa));
  387. cmd[0] = MSGCODE_GET_HDMI_VERSION;
  388. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
  389. if (err)
  390. return err;
  391. log_addrs->cec_version = data[0];
  392. dev_dbg(pulse8->dev, "CEC version: %d\n", log_addrs->cec_version);
  393. cmd[0] = MSGCODE_GET_OSD_NAME;
  394. err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 0);
  395. if (err)
  396. return err;
  397. strncpy(log_addrs->osd_name, data, 13);
  398. dev_dbg(pulse8->dev, "OSD name: %s\n", log_addrs->osd_name);
  399. return 0;
  400. }
  401. static int pulse8_apply_persistent_config(struct pulse8 *pulse8,
  402. struct cec_log_addrs *log_addrs,
  403. u16 pa)
  404. {
  405. int err;
  406. err = cec_s_log_addrs(pulse8->adap, log_addrs, false);
  407. if (err)
  408. return err;
  409. cec_s_phys_addr(pulse8->adap, pa, false);
  410. return 0;
  411. }
  412. static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
  413. {
  414. struct pulse8 *pulse8 = cec_get_drvdata(adap);
  415. u8 cmd[16];
  416. int err;
  417. cmd[0] = MSGCODE_SET_CONTROLLED;
  418. cmd[1] = enable;
  419. err = pulse8_send_and_wait(pulse8, cmd, 2,
  420. MSGCODE_COMMAND_ACCEPTED, 1);
  421. return enable ? err : 0;
  422. }
  423. static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
  424. {
  425. struct pulse8 *pulse8 = cec_get_drvdata(adap);
  426. u16 mask = 0;
  427. u16 pa = adap->phys_addr;
  428. u8 cmd[16];
  429. int err = 0;
  430. mutex_lock(&pulse8->config_lock);
  431. if (log_addr != CEC_LOG_ADDR_INVALID)
  432. mask = 1 << log_addr;
  433. cmd[0] = MSGCODE_SET_ACK_MASK;
  434. cmd[1] = mask >> 8;
  435. cmd[2] = mask & 0xff;
  436. err = pulse8_send_and_wait(pulse8, cmd, 3,
  437. MSGCODE_COMMAND_ACCEPTED, 0);
  438. if ((err && mask != 0) || pulse8->restoring_config)
  439. goto unlock;
  440. cmd[0] = MSGCODE_SET_AUTO_ENABLED;
  441. cmd[1] = log_addr == CEC_LOG_ADDR_INVALID ? 0 : 1;
  442. err = pulse8_send_and_wait(pulse8, cmd, 2,
  443. MSGCODE_COMMAND_ACCEPTED, 0);
  444. if (err)
  445. goto unlock;
  446. pulse8->autonomous = cmd[1];
  447. if (log_addr == CEC_LOG_ADDR_INVALID)
  448. goto unlock;
  449. cmd[0] = MSGCODE_SET_DEVICE_TYPE;
  450. cmd[1] = adap->log_addrs.primary_device_type[0];
  451. err = pulse8_send_and_wait(pulse8, cmd, 2,
  452. MSGCODE_COMMAND_ACCEPTED, 0);
  453. if (err)
  454. goto unlock;
  455. switch (adap->log_addrs.primary_device_type[0]) {
  456. case CEC_OP_PRIM_DEVTYPE_TV:
  457. mask = CEC_LOG_ADDR_MASK_TV;
  458. break;
  459. case CEC_OP_PRIM_DEVTYPE_RECORD:
  460. mask = CEC_LOG_ADDR_MASK_RECORD;
  461. break;
  462. case CEC_OP_PRIM_DEVTYPE_TUNER:
  463. mask = CEC_LOG_ADDR_MASK_TUNER;
  464. break;
  465. case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
  466. mask = CEC_LOG_ADDR_MASK_PLAYBACK;
  467. break;
  468. case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
  469. mask = CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
  470. break;
  471. case CEC_OP_PRIM_DEVTYPE_SWITCH:
  472. mask = CEC_LOG_ADDR_MASK_UNREGISTERED;
  473. break;
  474. case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
  475. mask = CEC_LOG_ADDR_MASK_SPECIFIC;
  476. break;
  477. default:
  478. mask = 0;
  479. break;
  480. }
  481. cmd[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK;
  482. cmd[1] = mask >> 8;
  483. cmd[2] = mask & 0xff;
  484. err = pulse8_send_and_wait(pulse8, cmd, 3,
  485. MSGCODE_COMMAND_ACCEPTED, 0);
  486. if (err)
  487. goto unlock;
  488. cmd[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS;
  489. cmd[1] = log_addr;
  490. err = pulse8_send_and_wait(pulse8, cmd, 2,
  491. MSGCODE_COMMAND_ACCEPTED, 0);
  492. if (err)
  493. goto unlock;
  494. cmd[0] = MSGCODE_SET_PHYSICAL_ADDRESS;
  495. cmd[1] = pa >> 8;
  496. cmd[2] = pa & 0xff;
  497. err = pulse8_send_and_wait(pulse8, cmd, 3,
  498. MSGCODE_COMMAND_ACCEPTED, 0);
  499. if (err)
  500. goto unlock;
  501. cmd[0] = MSGCODE_SET_HDMI_VERSION;
  502. cmd[1] = adap->log_addrs.cec_version;
  503. err = pulse8_send_and_wait(pulse8, cmd, 2,
  504. MSGCODE_COMMAND_ACCEPTED, 0);
  505. if (err)
  506. goto unlock;
  507. if (adap->log_addrs.osd_name[0]) {
  508. size_t osd_len = strlen(adap->log_addrs.osd_name);
  509. char *osd_str = cmd + 1;
  510. cmd[0] = MSGCODE_SET_OSD_NAME;
  511. strncpy(cmd + 1, adap->log_addrs.osd_name, 13);
  512. if (osd_len < 4) {
  513. memset(osd_str + osd_len, ' ', 4 - osd_len);
  514. osd_len = 4;
  515. osd_str[osd_len] = '\0';
  516. strscpy(adap->log_addrs.osd_name, osd_str,
  517. sizeof(adap->log_addrs.osd_name));
  518. }
  519. err = pulse8_send_and_wait(pulse8, cmd, 1 + osd_len,
  520. MSGCODE_COMMAND_ACCEPTED, 0);
  521. if (err)
  522. goto unlock;
  523. }
  524. unlock:
  525. if (pulse8->restoring_config)
  526. pulse8->restoring_config = false;
  527. else
  528. pulse8->config_pending = true;
  529. mutex_unlock(&pulse8->config_lock);
  530. return err;
  531. }
  532. static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
  533. u32 signal_free_time, struct cec_msg *msg)
  534. {
  535. struct pulse8 *pulse8 = cec_get_drvdata(adap);
  536. u8 cmd[2];
  537. unsigned int i;
  538. int err;
  539. cmd[0] = MSGCODE_TRANSMIT_IDLETIME;
  540. cmd[1] = signal_free_time;
  541. err = pulse8_send_and_wait(pulse8, cmd, 2,
  542. MSGCODE_COMMAND_ACCEPTED, 1);
  543. cmd[0] = MSGCODE_TRANSMIT_ACK_POLARITY;
  544. cmd[1] = cec_msg_is_broadcast(msg);
  545. if (!err)
  546. err = pulse8_send_and_wait(pulse8, cmd, 2,
  547. MSGCODE_COMMAND_ACCEPTED, 1);
  548. cmd[0] = msg->len == 1 ? MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
  549. cmd[1] = msg->msg[0];
  550. if (!err)
  551. err = pulse8_send_and_wait(pulse8, cmd, 2,
  552. MSGCODE_COMMAND_ACCEPTED, 1);
  553. if (!err && msg->len > 1) {
  554. cmd[0] = msg->len == 2 ? MSGCODE_TRANSMIT_EOM :
  555. MSGCODE_TRANSMIT;
  556. cmd[1] = msg->msg[1];
  557. err = pulse8_send_and_wait(pulse8, cmd, 2,
  558. MSGCODE_COMMAND_ACCEPTED, 1);
  559. for (i = 0; !err && i + 2 < msg->len; i++) {
  560. cmd[0] = (i + 2 == msg->len - 1) ?
  561. MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
  562. cmd[1] = msg->msg[i + 2];
  563. err = pulse8_send_and_wait(pulse8, cmd, 2,
  564. MSGCODE_COMMAND_ACCEPTED, 1);
  565. }
  566. }
  567. return err;
  568. }
  569. static int pulse8_received(struct cec_adapter *adap, struct cec_msg *msg)
  570. {
  571. return -ENOMSG;
  572. }
  573. static const struct cec_adap_ops pulse8_cec_adap_ops = {
  574. .adap_enable = pulse8_cec_adap_enable,
  575. .adap_log_addr = pulse8_cec_adap_log_addr,
  576. .adap_transmit = pulse8_cec_adap_transmit,
  577. .received = pulse8_received,
  578. };
  579. static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
  580. {
  581. u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_CAP_MONITOR_ALL;
  582. struct pulse8 *pulse8;
  583. int err = -ENOMEM;
  584. struct cec_log_addrs log_addrs = {};
  585. u16 pa = CEC_PHYS_ADDR_INVALID;
  586. pulse8 = kzalloc(sizeof(*pulse8), GFP_KERNEL);
  587. if (!pulse8)
  588. return -ENOMEM;
  589. pulse8->serio = serio;
  590. pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8,
  591. dev_name(&serio->dev), caps, 1);
  592. err = PTR_ERR_OR_ZERO(pulse8->adap);
  593. if (err < 0)
  594. goto free_device;
  595. pulse8->dev = &serio->dev;
  596. serio_set_drvdata(serio, pulse8);
  597. INIT_WORK(&pulse8->work, pulse8_irq_work_handler);
  598. mutex_init(&pulse8->write_lock);
  599. mutex_init(&pulse8->config_lock);
  600. pulse8->config_pending = false;
  601. err = serio_open(serio, drv);
  602. if (err)
  603. goto delete_adap;
  604. err = pulse8_setup(pulse8, serio, &log_addrs, &pa);
  605. if (err)
  606. goto close_serio;
  607. err = cec_register_adapter(pulse8->adap, &serio->dev);
  608. if (err < 0)
  609. goto close_serio;
  610. pulse8->dev = &pulse8->adap->devnode.dev;
  611. if (persistent_config && pulse8->autonomous) {
  612. err = pulse8_apply_persistent_config(pulse8, &log_addrs, pa);
  613. if (err)
  614. goto close_serio;
  615. pulse8->restoring_config = true;
  616. }
  617. INIT_DELAYED_WORK(&pulse8->ping_eeprom_work,
  618. pulse8_ping_eeprom_work_handler);
  619. schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
  620. return 0;
  621. close_serio:
  622. serio_close(serio);
  623. delete_adap:
  624. cec_delete_adapter(pulse8->adap);
  625. serio_set_drvdata(serio, NULL);
  626. free_device:
  627. kfree(pulse8);
  628. return err;
  629. }
  630. static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
  631. {
  632. struct pulse8 *pulse8 =
  633. container_of(work, struct pulse8, ping_eeprom_work.work);
  634. u8 cmd;
  635. schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
  636. cmd = MSGCODE_PING;
  637. pulse8_send_and_wait(pulse8, &cmd, 1,
  638. MSGCODE_COMMAND_ACCEPTED, 0);
  639. if (pulse8->vers < 2)
  640. return;
  641. mutex_lock(&pulse8->config_lock);
  642. if (pulse8->config_pending && persistent_config) {
  643. dev_dbg(pulse8->dev, "writing pending config to EEPROM\n");
  644. cmd = MSGCODE_WRITE_EEPROM;
  645. if (pulse8_send_and_wait(pulse8, &cmd, 1,
  646. MSGCODE_COMMAND_ACCEPTED, 0))
  647. dev_info(pulse8->dev, "failed to write pending config to EEPROM\n");
  648. else
  649. pulse8->config_pending = false;
  650. }
  651. mutex_unlock(&pulse8->config_lock);
  652. }
  653. static const struct serio_device_id pulse8_serio_ids[] = {
  654. {
  655. .type = SERIO_RS232,
  656. .proto = SERIO_PULSE8_CEC,
  657. .id = SERIO_ANY,
  658. .extra = SERIO_ANY,
  659. },
  660. { 0 }
  661. };
  662. MODULE_DEVICE_TABLE(serio, pulse8_serio_ids);
  663. static struct serio_driver pulse8_drv = {
  664. .driver = {
  665. .name = "pulse8-cec",
  666. },
  667. .description = "Pulse Eight HDMI CEC driver",
  668. .id_table = pulse8_serio_ids,
  669. .interrupt = pulse8_interrupt,
  670. .connect = pulse8_connect,
  671. .disconnect = pulse8_disconnect,
  672. };
  673. module_serio_driver(pulse8_drv);