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