pulse8-cec.c 20 KB

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