xref: /openbmc/linux/include/uapi/linux/cec-funcs.h (revision d7ca5afd)
1e2be04c7SGreg Kroah-Hartman /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
20dbacebeSHans Verkuil /*
30dbacebeSHans Verkuil  * cec - HDMI Consumer Electronics Control message functions
40dbacebeSHans Verkuil  *
50dbacebeSHans Verkuil  * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
60dbacebeSHans Verkuil  */
70dbacebeSHans Verkuil 
80dbacebeSHans Verkuil #ifndef _CEC_UAPI_FUNCS_H
90dbacebeSHans Verkuil #define _CEC_UAPI_FUNCS_H
100dbacebeSHans Verkuil 
110dbacebeSHans Verkuil #include <linux/cec.h>
120dbacebeSHans Verkuil 
130dbacebeSHans Verkuil /* One Touch Play Feature */
140dbacebeSHans Verkuil static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
150dbacebeSHans Verkuil {
160dbacebeSHans Verkuil 	msg->len = 4;
170dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
180dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_ACTIVE_SOURCE;
190dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
200dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
210dbacebeSHans Verkuil }
220dbacebeSHans Verkuil 
230dbacebeSHans Verkuil static inline void cec_ops_active_source(const struct cec_msg *msg,
240dbacebeSHans Verkuil 					 __u16 *phys_addr)
250dbacebeSHans Verkuil {
260dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
270dbacebeSHans Verkuil }
280dbacebeSHans Verkuil 
290dbacebeSHans Verkuil static inline void cec_msg_image_view_on(struct cec_msg *msg)
300dbacebeSHans Verkuil {
310dbacebeSHans Verkuil 	msg->len = 2;
320dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;
330dbacebeSHans Verkuil }
340dbacebeSHans Verkuil 
350dbacebeSHans Verkuil static inline void cec_msg_text_view_on(struct cec_msg *msg)
360dbacebeSHans Verkuil {
370dbacebeSHans Verkuil 	msg->len = 2;
380dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;
390dbacebeSHans Verkuil }
400dbacebeSHans Verkuil 
410dbacebeSHans Verkuil 
420dbacebeSHans Verkuil /* Routing Control Feature */
430dbacebeSHans Verkuil static inline void cec_msg_inactive_source(struct cec_msg *msg,
440dbacebeSHans Verkuil 					   __u16 phys_addr)
450dbacebeSHans Verkuil {
460dbacebeSHans Verkuil 	msg->len = 4;
470dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_INACTIVE_SOURCE;
480dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
490dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
500dbacebeSHans Verkuil }
510dbacebeSHans Verkuil 
520dbacebeSHans Verkuil static inline void cec_ops_inactive_source(const struct cec_msg *msg,
530dbacebeSHans Verkuil 					   __u16 *phys_addr)
540dbacebeSHans Verkuil {
550dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
560dbacebeSHans Verkuil }
570dbacebeSHans Verkuil 
580dbacebeSHans Verkuil static inline void cec_msg_request_active_source(struct cec_msg *msg,
593145c754SHans Verkuil 						 int reply)
600dbacebeSHans Verkuil {
610dbacebeSHans Verkuil 	msg->len = 2;
620dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
630dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE;
640dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;
650dbacebeSHans Verkuil }
660dbacebeSHans Verkuil 
670dbacebeSHans Verkuil static inline void cec_msg_routing_information(struct cec_msg *msg,
680dbacebeSHans Verkuil 					       __u16 phys_addr)
690dbacebeSHans Verkuil {
700dbacebeSHans Verkuil 	msg->len = 4;
710dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
720dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_ROUTING_INFORMATION;
730dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
740dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
750dbacebeSHans Verkuil }
760dbacebeSHans Verkuil 
770dbacebeSHans Verkuil static inline void cec_ops_routing_information(const struct cec_msg *msg,
780dbacebeSHans Verkuil 					       __u16 *phys_addr)
790dbacebeSHans Verkuil {
800dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
810dbacebeSHans Verkuil }
820dbacebeSHans Verkuil 
830dbacebeSHans Verkuil static inline void cec_msg_routing_change(struct cec_msg *msg,
843145c754SHans Verkuil 					  int reply,
850dbacebeSHans Verkuil 					  __u16 orig_phys_addr,
860dbacebeSHans Verkuil 					  __u16 new_phys_addr)
870dbacebeSHans Verkuil {
880dbacebeSHans Verkuil 	msg->len = 6;
890dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
900dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_ROUTING_CHANGE;
910dbacebeSHans Verkuil 	msg->msg[2] = orig_phys_addr >> 8;
920dbacebeSHans Verkuil 	msg->msg[3] = orig_phys_addr & 0xff;
930dbacebeSHans Verkuil 	msg->msg[4] = new_phys_addr >> 8;
940dbacebeSHans Verkuil 	msg->msg[5] = new_phys_addr & 0xff;
950dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0;
960dbacebeSHans Verkuil }
970dbacebeSHans Verkuil 
980dbacebeSHans Verkuil static inline void cec_ops_routing_change(const struct cec_msg *msg,
990dbacebeSHans Verkuil 					  __u16 *orig_phys_addr,
1000dbacebeSHans Verkuil 					  __u16 *new_phys_addr)
1010dbacebeSHans Verkuil {
1020dbacebeSHans Verkuil 	*orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1030dbacebeSHans Verkuil 	*new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];
1040dbacebeSHans Verkuil }
1050dbacebeSHans Verkuil 
1060dbacebeSHans Verkuil static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
1070dbacebeSHans Verkuil {
1080dbacebeSHans Verkuil 	msg->len = 4;
1090dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
1100dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_STREAM_PATH;
1110dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
1120dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
1130dbacebeSHans Verkuil }
1140dbacebeSHans Verkuil 
1150dbacebeSHans Verkuil static inline void cec_ops_set_stream_path(const struct cec_msg *msg,
1160dbacebeSHans Verkuil 					   __u16 *phys_addr)
1170dbacebeSHans Verkuil {
1180dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1190dbacebeSHans Verkuil }
1200dbacebeSHans Verkuil 
1210dbacebeSHans Verkuil 
1220dbacebeSHans Verkuil /* Standby Feature */
1230dbacebeSHans Verkuil static inline void cec_msg_standby(struct cec_msg *msg)
1240dbacebeSHans Verkuil {
1250dbacebeSHans Verkuil 	msg->len = 2;
1260dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_STANDBY;
1270dbacebeSHans Verkuil }
1280dbacebeSHans Verkuil 
1290dbacebeSHans Verkuil 
1300dbacebeSHans Verkuil /* One Touch Record Feature */
1313145c754SHans Verkuil static inline void cec_msg_record_off(struct cec_msg *msg, int reply)
1320dbacebeSHans Verkuil {
1330dbacebeSHans Verkuil 	msg->len = 2;
1340dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_OFF;
1350dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
1360dbacebeSHans Verkuil }
1370dbacebeSHans Verkuil 
1380dbacebeSHans Verkuil struct cec_op_arib_data {
1390dbacebeSHans Verkuil 	__u16 transport_id;
1400dbacebeSHans Verkuil 	__u16 service_id;
1410dbacebeSHans Verkuil 	__u16 orig_network_id;
1420dbacebeSHans Verkuil };
1430dbacebeSHans Verkuil 
1440dbacebeSHans Verkuil struct cec_op_atsc_data {
1450dbacebeSHans Verkuil 	__u16 transport_id;
1460dbacebeSHans Verkuil 	__u16 program_number;
1470dbacebeSHans Verkuil };
1480dbacebeSHans Verkuil 
1490dbacebeSHans Verkuil struct cec_op_dvb_data {
1500dbacebeSHans Verkuil 	__u16 transport_id;
1510dbacebeSHans Verkuil 	__u16 service_id;
1520dbacebeSHans Verkuil 	__u16 orig_network_id;
1530dbacebeSHans Verkuil };
1540dbacebeSHans Verkuil 
1550dbacebeSHans Verkuil struct cec_op_channel_data {
1560dbacebeSHans Verkuil 	__u8 channel_number_fmt;
1570dbacebeSHans Verkuil 	__u16 major;
1580dbacebeSHans Verkuil 	__u16 minor;
1590dbacebeSHans Verkuil };
1600dbacebeSHans Verkuil 
1610dbacebeSHans Verkuil struct cec_op_digital_service_id {
1620dbacebeSHans Verkuil 	__u8 service_id_method;
1630dbacebeSHans Verkuil 	__u8 dig_bcast_system;
1640dbacebeSHans Verkuil 	union {
1650dbacebeSHans Verkuil 		struct cec_op_arib_data arib;
1660dbacebeSHans Verkuil 		struct cec_op_atsc_data atsc;
1670dbacebeSHans Verkuil 		struct cec_op_dvb_data dvb;
1680dbacebeSHans Verkuil 		struct cec_op_channel_data channel;
1690dbacebeSHans Verkuil 	};
1700dbacebeSHans Verkuil };
1710dbacebeSHans Verkuil 
1720dbacebeSHans Verkuil struct cec_op_record_src {
1730dbacebeSHans Verkuil 	__u8 type;
1740dbacebeSHans Verkuil 	union {
1750dbacebeSHans Verkuil 		struct cec_op_digital_service_id digital;
1760dbacebeSHans Verkuil 		struct {
1770dbacebeSHans Verkuil 			__u8 ana_bcast_type;
1780dbacebeSHans Verkuil 			__u16 ana_freq;
1790dbacebeSHans Verkuil 			__u8 bcast_system;
1800dbacebeSHans Verkuil 		} analog;
1810dbacebeSHans Verkuil 		struct {
1820dbacebeSHans Verkuil 			__u8 plug;
1830dbacebeSHans Verkuil 		} ext_plug;
1840dbacebeSHans Verkuil 		struct {
1850dbacebeSHans Verkuil 			__u16 phys_addr;
1860dbacebeSHans Verkuil 		} ext_phys_addr;
1870dbacebeSHans Verkuil 	};
1880dbacebeSHans Verkuil };
1890dbacebeSHans Verkuil 
1900dbacebeSHans Verkuil static inline void cec_set_digital_service_id(__u8 *msg,
1910dbacebeSHans Verkuil 	      const struct cec_op_digital_service_id *digital)
1920dbacebeSHans Verkuil {
1930dbacebeSHans Verkuil 	*msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system;
1940dbacebeSHans Verkuil 	if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
1950dbacebeSHans Verkuil 		*msg++ = (digital->channel.channel_number_fmt << 2) |
1960dbacebeSHans Verkuil 			 (digital->channel.major >> 8);
1970dbacebeSHans Verkuil 		*msg++ = digital->channel.major & 0xff;
1980dbacebeSHans Verkuil 		*msg++ = digital->channel.minor >> 8;
1990dbacebeSHans Verkuil 		*msg++ = digital->channel.minor & 0xff;
2000dbacebeSHans Verkuil 		*msg++ = 0;
2010dbacebeSHans Verkuil 		*msg++ = 0;
2020dbacebeSHans Verkuil 		return;
2030dbacebeSHans Verkuil 	}
2040dbacebeSHans Verkuil 	switch (digital->dig_bcast_system) {
2050dbacebeSHans Verkuil 	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
2060dbacebeSHans Verkuil 	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
2070dbacebeSHans Verkuil 	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
2080dbacebeSHans Verkuil 	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
2090dbacebeSHans Verkuil 		*msg++ = digital->atsc.transport_id >> 8;
2100dbacebeSHans Verkuil 		*msg++ = digital->atsc.transport_id & 0xff;
2110dbacebeSHans Verkuil 		*msg++ = digital->atsc.program_number >> 8;
2120dbacebeSHans Verkuil 		*msg++ = digital->atsc.program_number & 0xff;
2130dbacebeSHans Verkuil 		*msg++ = 0;
2140dbacebeSHans Verkuil 		*msg++ = 0;
2150dbacebeSHans Verkuil 		break;
2160dbacebeSHans Verkuil 	default:
2170dbacebeSHans Verkuil 		*msg++ = digital->dvb.transport_id >> 8;
2180dbacebeSHans Verkuil 		*msg++ = digital->dvb.transport_id & 0xff;
2190dbacebeSHans Verkuil 		*msg++ = digital->dvb.service_id >> 8;
2200dbacebeSHans Verkuil 		*msg++ = digital->dvb.service_id & 0xff;
2210dbacebeSHans Verkuil 		*msg++ = digital->dvb.orig_network_id >> 8;
2220dbacebeSHans Verkuil 		*msg++ = digital->dvb.orig_network_id & 0xff;
2230dbacebeSHans Verkuil 		break;
2240dbacebeSHans Verkuil 	}
2250dbacebeSHans Verkuil }
2260dbacebeSHans Verkuil 
2270dbacebeSHans Verkuil static inline void cec_get_digital_service_id(const __u8 *msg,
2280dbacebeSHans Verkuil 	      struct cec_op_digital_service_id *digital)
2290dbacebeSHans Verkuil {
2300dbacebeSHans Verkuil 	digital->service_id_method = msg[0] >> 7;
2310dbacebeSHans Verkuil 	digital->dig_bcast_system = msg[0] & 0x7f;
2320dbacebeSHans Verkuil 	if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
2330dbacebeSHans Verkuil 		digital->channel.channel_number_fmt = msg[1] >> 2;
2340dbacebeSHans Verkuil 		digital->channel.major = ((msg[1] & 3) << 6) | msg[2];
2350dbacebeSHans Verkuil 		digital->channel.minor = (msg[3] << 8) | msg[4];
2360dbacebeSHans Verkuil 		return;
2370dbacebeSHans Verkuil 	}
2380dbacebeSHans Verkuil 	digital->dvb.transport_id = (msg[1] << 8) | msg[2];
2390dbacebeSHans Verkuil 	digital->dvb.service_id = (msg[3] << 8) | msg[4];
2400dbacebeSHans Verkuil 	digital->dvb.orig_network_id = (msg[5] << 8) | msg[6];
2410dbacebeSHans Verkuil }
2420dbacebeSHans Verkuil 
2430dbacebeSHans Verkuil static inline void cec_msg_record_on_own(struct cec_msg *msg)
2440dbacebeSHans Verkuil {
2450dbacebeSHans Verkuil 	msg->len = 3;
2460dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_ON;
2470dbacebeSHans Verkuil 	msg->msg[2] = CEC_OP_RECORD_SRC_OWN;
2480dbacebeSHans Verkuil }
2490dbacebeSHans Verkuil 
2500dbacebeSHans Verkuil static inline void cec_msg_record_on_digital(struct cec_msg *msg,
2510dbacebeSHans Verkuil 			     const struct cec_op_digital_service_id *digital)
2520dbacebeSHans Verkuil {
2530dbacebeSHans Verkuil 	msg->len = 10;
2540dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_ON;
2550dbacebeSHans Verkuil 	msg->msg[2] = CEC_OP_RECORD_SRC_DIGITAL;
2560dbacebeSHans Verkuil 	cec_set_digital_service_id(msg->msg + 3, digital);
2570dbacebeSHans Verkuil }
2580dbacebeSHans Verkuil 
2590dbacebeSHans Verkuil static inline void cec_msg_record_on_analog(struct cec_msg *msg,
2600dbacebeSHans Verkuil 					    __u8 ana_bcast_type,
2610dbacebeSHans Verkuil 					    __u16 ana_freq,
2620dbacebeSHans Verkuil 					    __u8 bcast_system)
2630dbacebeSHans Verkuil {
2640dbacebeSHans Verkuil 	msg->len = 7;
2650dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_ON;
2660dbacebeSHans Verkuil 	msg->msg[2] = CEC_OP_RECORD_SRC_ANALOG;
2670dbacebeSHans Verkuil 	msg->msg[3] = ana_bcast_type;
2680dbacebeSHans Verkuil 	msg->msg[4] = ana_freq >> 8;
2690dbacebeSHans Verkuil 	msg->msg[5] = ana_freq & 0xff;
2700dbacebeSHans Verkuil 	msg->msg[6] = bcast_system;
2710dbacebeSHans Verkuil }
2720dbacebeSHans Verkuil 
2730dbacebeSHans Verkuil static inline void cec_msg_record_on_plug(struct cec_msg *msg,
2740dbacebeSHans Verkuil 					  __u8 plug)
2750dbacebeSHans Verkuil {
2760dbacebeSHans Verkuil 	msg->len = 4;
2770dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_ON;
2780dbacebeSHans Verkuil 	msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG;
2790dbacebeSHans Verkuil 	msg->msg[3] = plug;
2800dbacebeSHans Verkuil }
2810dbacebeSHans Verkuil 
2820dbacebeSHans Verkuil static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,
2830dbacebeSHans Verkuil 					       __u16 phys_addr)
2840dbacebeSHans Verkuil {
2850dbacebeSHans Verkuil 	msg->len = 5;
2860dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_ON;
2870dbacebeSHans Verkuil 	msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR;
2880dbacebeSHans Verkuil 	msg->msg[3] = phys_addr >> 8;
2890dbacebeSHans Verkuil 	msg->msg[4] = phys_addr & 0xff;
2900dbacebeSHans Verkuil }
2910dbacebeSHans Verkuil 
2920dbacebeSHans Verkuil static inline void cec_msg_record_on(struct cec_msg *msg,
2933145c754SHans Verkuil 				     int reply,
2940dbacebeSHans Verkuil 				     const struct cec_op_record_src *rec_src)
2950dbacebeSHans Verkuil {
2960dbacebeSHans Verkuil 	switch (rec_src->type) {
2970dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_OWN:
2980dbacebeSHans Verkuil 		cec_msg_record_on_own(msg);
2990dbacebeSHans Verkuil 		break;
3000dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_DIGITAL:
3010dbacebeSHans Verkuil 		cec_msg_record_on_digital(msg, &rec_src->digital);
3020dbacebeSHans Verkuil 		break;
3030dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_ANALOG:
3040dbacebeSHans Verkuil 		cec_msg_record_on_analog(msg,
3050dbacebeSHans Verkuil 					 rec_src->analog.ana_bcast_type,
3060dbacebeSHans Verkuil 					 rec_src->analog.ana_freq,
3070dbacebeSHans Verkuil 					 rec_src->analog.bcast_system);
3080dbacebeSHans Verkuil 		break;
3090dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_EXT_PLUG:
3100dbacebeSHans Verkuil 		cec_msg_record_on_plug(msg, rec_src->ext_plug.plug);
3110dbacebeSHans Verkuil 		break;
3120dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
3130dbacebeSHans Verkuil 		cec_msg_record_on_phys_addr(msg,
3140dbacebeSHans Verkuil 					    rec_src->ext_phys_addr.phys_addr);
3150dbacebeSHans Verkuil 		break;
3160dbacebeSHans Verkuil 	}
3170dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
3180dbacebeSHans Verkuil }
3190dbacebeSHans Verkuil 
3200dbacebeSHans Verkuil static inline void cec_ops_record_on(const struct cec_msg *msg,
3210dbacebeSHans Verkuil 				     struct cec_op_record_src *rec_src)
3220dbacebeSHans Verkuil {
3230dbacebeSHans Verkuil 	rec_src->type = msg->msg[2];
3240dbacebeSHans Verkuil 	switch (rec_src->type) {
3250dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_OWN:
3260dbacebeSHans Verkuil 		break;
3270dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_DIGITAL:
3280dbacebeSHans Verkuil 		cec_get_digital_service_id(msg->msg + 3, &rec_src->digital);
3290dbacebeSHans Verkuil 		break;
3300dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_ANALOG:
3310dbacebeSHans Verkuil 		rec_src->analog.ana_bcast_type = msg->msg[3];
3320dbacebeSHans Verkuil 		rec_src->analog.ana_freq =
3330dbacebeSHans Verkuil 			(msg->msg[4] << 8) | msg->msg[5];
3340dbacebeSHans Verkuil 		rec_src->analog.bcast_system = msg->msg[6];
3350dbacebeSHans Verkuil 		break;
3360dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_EXT_PLUG:
3370dbacebeSHans Verkuil 		rec_src->ext_plug.plug = msg->msg[3];
3380dbacebeSHans Verkuil 		break;
3390dbacebeSHans Verkuil 	case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
3400dbacebeSHans Verkuil 		rec_src->ext_phys_addr.phys_addr =
3410dbacebeSHans Verkuil 			(msg->msg[3] << 8) | msg->msg[4];
3420dbacebeSHans Verkuil 		break;
3430dbacebeSHans Verkuil 	}
3440dbacebeSHans Verkuil }
3450dbacebeSHans Verkuil 
3460dbacebeSHans Verkuil static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
3470dbacebeSHans Verkuil {
3480dbacebeSHans Verkuil 	msg->len = 3;
3490dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_STATUS;
3500dbacebeSHans Verkuil 	msg->msg[2] = rec_status;
3510dbacebeSHans Verkuil }
3520dbacebeSHans Verkuil 
3530dbacebeSHans Verkuil static inline void cec_ops_record_status(const struct cec_msg *msg,
3540dbacebeSHans Verkuil 					 __u8 *rec_status)
3550dbacebeSHans Verkuil {
3560dbacebeSHans Verkuil 	*rec_status = msg->msg[2];
3570dbacebeSHans Verkuil }
3580dbacebeSHans Verkuil 
3590dbacebeSHans Verkuil static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
3603145c754SHans Verkuil 					    int reply)
3610dbacebeSHans Verkuil {
3620dbacebeSHans Verkuil 	msg->len = 2;
3630dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN;
3640dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_RECORD_ON : 0;
3650dbacebeSHans Verkuil }
3660dbacebeSHans Verkuil 
3670dbacebeSHans Verkuil 
3680dbacebeSHans Verkuil /* Timer Programming Feature */
3690dbacebeSHans Verkuil static inline void cec_msg_timer_status(struct cec_msg *msg,
3700dbacebeSHans Verkuil 					__u8 timer_overlap_warning,
3710dbacebeSHans Verkuil 					__u8 media_info,
3720dbacebeSHans Verkuil 					__u8 prog_info,
3730dbacebeSHans Verkuil 					__u8 prog_error,
3740dbacebeSHans Verkuil 					__u8 duration_hr,
3750dbacebeSHans Verkuil 					__u8 duration_min)
3760dbacebeSHans Verkuil {
3770dbacebeSHans Verkuil 	msg->len = 3;
3780dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TIMER_STATUS;
3790dbacebeSHans Verkuil 	msg->msg[2] = (timer_overlap_warning << 7) |
3800dbacebeSHans Verkuil 		(media_info << 5) |
3810dbacebeSHans Verkuil 		(prog_info ? 0x10 : 0) |
3820dbacebeSHans Verkuil 		(prog_info ? prog_info : prog_error);
3830dbacebeSHans Verkuil 	if (prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
3840dbacebeSHans Verkuil 	    prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
3850dbacebeSHans Verkuil 	    prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
3860dbacebeSHans Verkuil 		msg->len += 2;
3870dbacebeSHans Verkuil 		msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10);
3880dbacebeSHans Verkuil 		msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10);
3890dbacebeSHans Verkuil 	}
3900dbacebeSHans Verkuil }
3910dbacebeSHans Verkuil 
3920dbacebeSHans Verkuil static inline void cec_ops_timer_status(const struct cec_msg *msg,
3930dbacebeSHans Verkuil 					__u8 *timer_overlap_warning,
3940dbacebeSHans Verkuil 					__u8 *media_info,
3950dbacebeSHans Verkuil 					__u8 *prog_info,
3960dbacebeSHans Verkuil 					__u8 *prog_error,
3970dbacebeSHans Verkuil 					__u8 *duration_hr,
3980dbacebeSHans Verkuil 					__u8 *duration_min)
3990dbacebeSHans Verkuil {
4000dbacebeSHans Verkuil 	*timer_overlap_warning = msg->msg[2] >> 7;
4010dbacebeSHans Verkuil 	*media_info = (msg->msg[2] >> 5) & 3;
4020dbacebeSHans Verkuil 	if (msg->msg[2] & 0x10) {
4030dbacebeSHans Verkuil 		*prog_info = msg->msg[2] & 0xf;
4040dbacebeSHans Verkuil 		*prog_error = 0;
4050dbacebeSHans Verkuil 	} else {
4060dbacebeSHans Verkuil 		*prog_info = 0;
4070dbacebeSHans Verkuil 		*prog_error = msg->msg[2] & 0xf;
4080dbacebeSHans Verkuil 	}
4090dbacebeSHans Verkuil 	if (*prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
4100dbacebeSHans Verkuil 	    *prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
4110dbacebeSHans Verkuil 	    *prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
4120dbacebeSHans Verkuil 		*duration_hr = (msg->msg[3] >> 4) * 10 + (msg->msg[3] & 0xf);
4130dbacebeSHans Verkuil 		*duration_min = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
4140dbacebeSHans Verkuil 	} else {
4150dbacebeSHans Verkuil 		*duration_hr = *duration_min = 0;
4160dbacebeSHans Verkuil 	}
4170dbacebeSHans Verkuil }
4180dbacebeSHans Verkuil 
4190dbacebeSHans Verkuil static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,
4200dbacebeSHans Verkuil 						__u8 timer_cleared_status)
4210dbacebeSHans Verkuil {
4220dbacebeSHans Verkuil 	msg->len = 3;
4230dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS;
4240dbacebeSHans Verkuil 	msg->msg[2] = timer_cleared_status;
4250dbacebeSHans Verkuil }
4260dbacebeSHans Verkuil 
4270dbacebeSHans Verkuil static inline void cec_ops_timer_cleared_status(const struct cec_msg *msg,
4280dbacebeSHans Verkuil 						__u8 *timer_cleared_status)
4290dbacebeSHans Verkuil {
4300dbacebeSHans Verkuil 	*timer_cleared_status = msg->msg[2];
4310dbacebeSHans Verkuil }
4320dbacebeSHans Verkuil 
4330dbacebeSHans Verkuil static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
4343145c754SHans Verkuil 						int reply,
4350dbacebeSHans Verkuil 						__u8 day,
4360dbacebeSHans Verkuil 						__u8 month,
4370dbacebeSHans Verkuil 						__u8 start_hr,
4380dbacebeSHans Verkuil 						__u8 start_min,
4390dbacebeSHans Verkuil 						__u8 duration_hr,
4400dbacebeSHans Verkuil 						__u8 duration_min,
4410dbacebeSHans Verkuil 						__u8 recording_seq,
4420dbacebeSHans Verkuil 						__u8 ana_bcast_type,
4430dbacebeSHans Verkuil 						__u16 ana_freq,
4440dbacebeSHans Verkuil 						__u8 bcast_system)
4450dbacebeSHans Verkuil {
4460dbacebeSHans Verkuil 	msg->len = 13;
4470dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER;
4480dbacebeSHans Verkuil 	msg->msg[2] = day;
4490dbacebeSHans Verkuil 	msg->msg[3] = month;
4500dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
4510dbacebeSHans Verkuil 	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
4520dbacebeSHans Verkuil 	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
4530dbacebeSHans Verkuil 	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
4540dbacebeSHans Verkuil 	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
4550dbacebeSHans Verkuil 	msg->msg[8] = recording_seq;
4560dbacebeSHans Verkuil 	msg->msg[9] = ana_bcast_type;
4570dbacebeSHans Verkuil 	msg->msg[10] = ana_freq >> 8;
4580dbacebeSHans Verkuil 	msg->msg[11] = ana_freq & 0xff;
4590dbacebeSHans Verkuil 	msg->msg[12] = bcast_system;
4600dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
4610dbacebeSHans Verkuil }
4620dbacebeSHans Verkuil 
4630dbacebeSHans Verkuil static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
4640dbacebeSHans Verkuil 						__u8 *day,
4650dbacebeSHans Verkuil 						__u8 *month,
4660dbacebeSHans Verkuil 						__u8 *start_hr,
4670dbacebeSHans Verkuil 						__u8 *start_min,
4680dbacebeSHans Verkuil 						__u8 *duration_hr,
4690dbacebeSHans Verkuil 						__u8 *duration_min,
4700dbacebeSHans Verkuil 						__u8 *recording_seq,
4710dbacebeSHans Verkuil 						__u8 *ana_bcast_type,
4720dbacebeSHans Verkuil 						__u16 *ana_freq,
4730dbacebeSHans Verkuil 						__u8 *bcast_system)
4740dbacebeSHans Verkuil {
4750dbacebeSHans Verkuil 	*day = msg->msg[2];
4760dbacebeSHans Verkuil 	*month = msg->msg[3];
4770dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
4780dbacebeSHans Verkuil 	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
4790dbacebeSHans Verkuil 	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
4800dbacebeSHans Verkuil 	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
4810dbacebeSHans Verkuil 	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
4820dbacebeSHans Verkuil 	*recording_seq = msg->msg[8];
4830dbacebeSHans Verkuil 	*ana_bcast_type = msg->msg[9];
4840dbacebeSHans Verkuil 	*ana_freq = (msg->msg[10] << 8) | msg->msg[11];
4850dbacebeSHans Verkuil 	*bcast_system = msg->msg[12];
4860dbacebeSHans Verkuil }
4870dbacebeSHans Verkuil 
4880dbacebeSHans Verkuil static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
4893145c754SHans Verkuil 				int reply,
4900dbacebeSHans Verkuil 				__u8 day,
4910dbacebeSHans Verkuil 				__u8 month,
4920dbacebeSHans Verkuil 				__u8 start_hr,
4930dbacebeSHans Verkuil 				__u8 start_min,
4940dbacebeSHans Verkuil 				__u8 duration_hr,
4950dbacebeSHans Verkuil 				__u8 duration_min,
4960dbacebeSHans Verkuil 				__u8 recording_seq,
4970dbacebeSHans Verkuil 				const struct cec_op_digital_service_id *digital)
4980dbacebeSHans Verkuil {
4990dbacebeSHans Verkuil 	msg->len = 16;
5000dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
5010dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER;
5020dbacebeSHans Verkuil 	msg->msg[2] = day;
5030dbacebeSHans Verkuil 	msg->msg[3] = month;
5040dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
5050dbacebeSHans Verkuil 	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
5060dbacebeSHans Verkuil 	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
5070dbacebeSHans Verkuil 	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
5080dbacebeSHans Verkuil 	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
5090dbacebeSHans Verkuil 	msg->msg[8] = recording_seq;
5100dbacebeSHans Verkuil 	cec_set_digital_service_id(msg->msg + 9, digital);
5110dbacebeSHans Verkuil }
5120dbacebeSHans Verkuil 
5130dbacebeSHans Verkuil static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg,
5140dbacebeSHans Verkuil 				__u8 *day,
5150dbacebeSHans Verkuil 				__u8 *month,
5160dbacebeSHans Verkuil 				__u8 *start_hr,
5170dbacebeSHans Verkuil 				__u8 *start_min,
5180dbacebeSHans Verkuil 				__u8 *duration_hr,
5190dbacebeSHans Verkuil 				__u8 *duration_min,
5200dbacebeSHans Verkuil 				__u8 *recording_seq,
5210dbacebeSHans Verkuil 				struct cec_op_digital_service_id *digital)
5220dbacebeSHans Verkuil {
5230dbacebeSHans Verkuil 	*day = msg->msg[2];
5240dbacebeSHans Verkuil 	*month = msg->msg[3];
5250dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
5260dbacebeSHans Verkuil 	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
5270dbacebeSHans Verkuil 	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
5280dbacebeSHans Verkuil 	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
5290dbacebeSHans Verkuil 	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
5300dbacebeSHans Verkuil 	*recording_seq = msg->msg[8];
5310dbacebeSHans Verkuil 	cec_get_digital_service_id(msg->msg + 9, digital);
5320dbacebeSHans Verkuil }
5330dbacebeSHans Verkuil 
5340dbacebeSHans Verkuil static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
5353145c754SHans Verkuil 					   int reply,
5360dbacebeSHans Verkuil 					   __u8 day,
5370dbacebeSHans Verkuil 					   __u8 month,
5380dbacebeSHans Verkuil 					   __u8 start_hr,
5390dbacebeSHans Verkuil 					   __u8 start_min,
5400dbacebeSHans Verkuil 					   __u8 duration_hr,
5410dbacebeSHans Verkuil 					   __u8 duration_min,
5420dbacebeSHans Verkuil 					   __u8 recording_seq,
5430dbacebeSHans Verkuil 					   __u8 ext_src_spec,
5440dbacebeSHans Verkuil 					   __u8 plug,
5450dbacebeSHans Verkuil 					   __u16 phys_addr)
5460dbacebeSHans Verkuil {
5470dbacebeSHans Verkuil 	msg->len = 13;
5480dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER;
5490dbacebeSHans Verkuil 	msg->msg[2] = day;
5500dbacebeSHans Verkuil 	msg->msg[3] = month;
5510dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
5520dbacebeSHans Verkuil 	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
5530dbacebeSHans Verkuil 	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
5540dbacebeSHans Verkuil 	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
5550dbacebeSHans Verkuil 	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
5560dbacebeSHans Verkuil 	msg->msg[8] = recording_seq;
5570dbacebeSHans Verkuil 	msg->msg[9] = ext_src_spec;
5580dbacebeSHans Verkuil 	msg->msg[10] = plug;
5590dbacebeSHans Verkuil 	msg->msg[11] = phys_addr >> 8;
5600dbacebeSHans Verkuil 	msg->msg[12] = phys_addr & 0xff;
5610dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
5620dbacebeSHans Verkuil }
5630dbacebeSHans Verkuil 
5640dbacebeSHans Verkuil static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg,
5650dbacebeSHans Verkuil 					   __u8 *day,
5660dbacebeSHans Verkuil 					   __u8 *month,
5670dbacebeSHans Verkuil 					   __u8 *start_hr,
5680dbacebeSHans Verkuil 					   __u8 *start_min,
5690dbacebeSHans Verkuil 					   __u8 *duration_hr,
5700dbacebeSHans Verkuil 					   __u8 *duration_min,
5710dbacebeSHans Verkuil 					   __u8 *recording_seq,
5720dbacebeSHans Verkuil 					   __u8 *ext_src_spec,
5730dbacebeSHans Verkuil 					   __u8 *plug,
5740dbacebeSHans Verkuil 					   __u16 *phys_addr)
5750dbacebeSHans Verkuil {
5760dbacebeSHans Verkuil 	*day = msg->msg[2];
5770dbacebeSHans Verkuil 	*month = msg->msg[3];
5780dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
5790dbacebeSHans Verkuil 	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
5800dbacebeSHans Verkuil 	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
5810dbacebeSHans Verkuil 	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
5820dbacebeSHans Verkuil 	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
5830dbacebeSHans Verkuil 	*recording_seq = msg->msg[8];
5840dbacebeSHans Verkuil 	*ext_src_spec = msg->msg[9];
5850dbacebeSHans Verkuil 	*plug = msg->msg[10];
5860dbacebeSHans Verkuil 	*phys_addr = (msg->msg[11] << 8) | msg->msg[12];
5870dbacebeSHans Verkuil }
5880dbacebeSHans Verkuil 
5890dbacebeSHans Verkuil static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
5903145c754SHans Verkuil 					      int reply,
5910dbacebeSHans Verkuil 					      __u8 day,
5920dbacebeSHans Verkuil 					      __u8 month,
5930dbacebeSHans Verkuil 					      __u8 start_hr,
5940dbacebeSHans Verkuil 					      __u8 start_min,
5950dbacebeSHans Verkuil 					      __u8 duration_hr,
5960dbacebeSHans Verkuil 					      __u8 duration_min,
5970dbacebeSHans Verkuil 					      __u8 recording_seq,
5980dbacebeSHans Verkuil 					      __u8 ana_bcast_type,
5990dbacebeSHans Verkuil 					      __u16 ana_freq,
6000dbacebeSHans Verkuil 					      __u8 bcast_system)
6010dbacebeSHans Verkuil {
6020dbacebeSHans Verkuil 	msg->len = 13;
6030dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER;
6040dbacebeSHans Verkuil 	msg->msg[2] = day;
6050dbacebeSHans Verkuil 	msg->msg[3] = month;
6060dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
6070dbacebeSHans Verkuil 	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
6080dbacebeSHans Verkuil 	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
6090dbacebeSHans Verkuil 	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
6100dbacebeSHans Verkuil 	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
6110dbacebeSHans Verkuil 	msg->msg[8] = recording_seq;
6120dbacebeSHans Verkuil 	msg->msg[9] = ana_bcast_type;
6130dbacebeSHans Verkuil 	msg->msg[10] = ana_freq >> 8;
6140dbacebeSHans Verkuil 	msg->msg[11] = ana_freq & 0xff;
6150dbacebeSHans Verkuil 	msg->msg[12] = bcast_system;
6160dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
6170dbacebeSHans Verkuil }
6180dbacebeSHans Verkuil 
6190dbacebeSHans Verkuil static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg,
6200dbacebeSHans Verkuil 					      __u8 *day,
6210dbacebeSHans Verkuil 					      __u8 *month,
6220dbacebeSHans Verkuil 					      __u8 *start_hr,
6230dbacebeSHans Verkuil 					      __u8 *start_min,
6240dbacebeSHans Verkuil 					      __u8 *duration_hr,
6250dbacebeSHans Verkuil 					      __u8 *duration_min,
6260dbacebeSHans Verkuil 					      __u8 *recording_seq,
6270dbacebeSHans Verkuil 					      __u8 *ana_bcast_type,
6280dbacebeSHans Verkuil 					      __u16 *ana_freq,
6290dbacebeSHans Verkuil 					      __u8 *bcast_system)
6300dbacebeSHans Verkuil {
6310dbacebeSHans Verkuil 	*day = msg->msg[2];
6320dbacebeSHans Verkuil 	*month = msg->msg[3];
6330dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
6340dbacebeSHans Verkuil 	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
6350dbacebeSHans Verkuil 	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
6360dbacebeSHans Verkuil 	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
6370dbacebeSHans Verkuil 	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
6380dbacebeSHans Verkuil 	*recording_seq = msg->msg[8];
6390dbacebeSHans Verkuil 	*ana_bcast_type = msg->msg[9];
6400dbacebeSHans Verkuil 	*ana_freq = (msg->msg[10] << 8) | msg->msg[11];
6410dbacebeSHans Verkuil 	*bcast_system = msg->msg[12];
6420dbacebeSHans Verkuil }
6430dbacebeSHans Verkuil 
6440dbacebeSHans Verkuil static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
6453145c754SHans Verkuil 			int reply,
6460dbacebeSHans Verkuil 			__u8 day,
6470dbacebeSHans Verkuil 			__u8 month,
6480dbacebeSHans Verkuil 			__u8 start_hr,
6490dbacebeSHans Verkuil 			__u8 start_min,
6500dbacebeSHans Verkuil 			__u8 duration_hr,
6510dbacebeSHans Verkuil 			__u8 duration_min,
6520dbacebeSHans Verkuil 			__u8 recording_seq,
6530dbacebeSHans Verkuil 			const struct cec_op_digital_service_id *digital)
6540dbacebeSHans Verkuil {
6550dbacebeSHans Verkuil 	msg->len = 16;
6560dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
6570dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER;
6580dbacebeSHans Verkuil 	msg->msg[2] = day;
6590dbacebeSHans Verkuil 	msg->msg[3] = month;
6600dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
6610dbacebeSHans Verkuil 	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
6620dbacebeSHans Verkuil 	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
6630dbacebeSHans Verkuil 	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
6640dbacebeSHans Verkuil 	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
6650dbacebeSHans Verkuil 	msg->msg[8] = recording_seq;
6660dbacebeSHans Verkuil 	cec_set_digital_service_id(msg->msg + 9, digital);
6670dbacebeSHans Verkuil }
6680dbacebeSHans Verkuil 
6690dbacebeSHans Verkuil static inline void cec_ops_set_digital_timer(const struct cec_msg *msg,
6700dbacebeSHans Verkuil 			__u8 *day,
6710dbacebeSHans Verkuil 			__u8 *month,
6720dbacebeSHans Verkuil 			__u8 *start_hr,
6730dbacebeSHans Verkuil 			__u8 *start_min,
6740dbacebeSHans Verkuil 			__u8 *duration_hr,
6750dbacebeSHans Verkuil 			__u8 *duration_min,
6760dbacebeSHans Verkuil 			__u8 *recording_seq,
6770dbacebeSHans Verkuil 			struct cec_op_digital_service_id *digital)
6780dbacebeSHans Verkuil {
6790dbacebeSHans Verkuil 	*day = msg->msg[2];
6800dbacebeSHans Verkuil 	*month = msg->msg[3];
6810dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
6820dbacebeSHans Verkuil 	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
6830dbacebeSHans Verkuil 	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
6840dbacebeSHans Verkuil 	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
6850dbacebeSHans Verkuil 	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
6860dbacebeSHans Verkuil 	*recording_seq = msg->msg[8];
6870dbacebeSHans Verkuil 	cec_get_digital_service_id(msg->msg + 9, digital);
6880dbacebeSHans Verkuil }
6890dbacebeSHans Verkuil 
6900dbacebeSHans Verkuil static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
6913145c754SHans Verkuil 					 int reply,
6920dbacebeSHans Verkuil 					 __u8 day,
6930dbacebeSHans Verkuil 					 __u8 month,
6940dbacebeSHans Verkuil 					 __u8 start_hr,
6950dbacebeSHans Verkuil 					 __u8 start_min,
6960dbacebeSHans Verkuil 					 __u8 duration_hr,
6970dbacebeSHans Verkuil 					 __u8 duration_min,
6980dbacebeSHans Verkuil 					 __u8 recording_seq,
6990dbacebeSHans Verkuil 					 __u8 ext_src_spec,
7000dbacebeSHans Verkuil 					 __u8 plug,
7010dbacebeSHans Verkuil 					 __u16 phys_addr)
7020dbacebeSHans Verkuil {
7030dbacebeSHans Verkuil 	msg->len = 13;
7040dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_EXT_TIMER;
7050dbacebeSHans Verkuil 	msg->msg[2] = day;
7060dbacebeSHans Verkuil 	msg->msg[3] = month;
7070dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
7080dbacebeSHans Verkuil 	msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
7090dbacebeSHans Verkuil 	msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
7100dbacebeSHans Verkuil 	msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
7110dbacebeSHans Verkuil 	msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
7120dbacebeSHans Verkuil 	msg->msg[8] = recording_seq;
7130dbacebeSHans Verkuil 	msg->msg[9] = ext_src_spec;
7140dbacebeSHans Verkuil 	msg->msg[10] = plug;
7150dbacebeSHans Verkuil 	msg->msg[11] = phys_addr >> 8;
7160dbacebeSHans Verkuil 	msg->msg[12] = phys_addr & 0xff;
7170dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
7180dbacebeSHans Verkuil }
7190dbacebeSHans Verkuil 
7200dbacebeSHans Verkuil static inline void cec_ops_set_ext_timer(const struct cec_msg *msg,
7210dbacebeSHans Verkuil 					 __u8 *day,
7220dbacebeSHans Verkuil 					 __u8 *month,
7230dbacebeSHans Verkuil 					 __u8 *start_hr,
7240dbacebeSHans Verkuil 					 __u8 *start_min,
7250dbacebeSHans Verkuil 					 __u8 *duration_hr,
7260dbacebeSHans Verkuil 					 __u8 *duration_min,
7270dbacebeSHans Verkuil 					 __u8 *recording_seq,
7280dbacebeSHans Verkuil 					 __u8 *ext_src_spec,
7290dbacebeSHans Verkuil 					 __u8 *plug,
7300dbacebeSHans Verkuil 					 __u16 *phys_addr)
7310dbacebeSHans Verkuil {
7320dbacebeSHans Verkuil 	*day = msg->msg[2];
7330dbacebeSHans Verkuil 	*month = msg->msg[3];
7340dbacebeSHans Verkuil 	/* Hours and minutes are in BCD format */
7350dbacebeSHans Verkuil 	*start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
7360dbacebeSHans Verkuil 	*start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
7370dbacebeSHans Verkuil 	*duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
7380dbacebeSHans Verkuil 	*duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
7390dbacebeSHans Verkuil 	*recording_seq = msg->msg[8];
7400dbacebeSHans Verkuil 	*ext_src_spec = msg->msg[9];
7410dbacebeSHans Verkuil 	*plug = msg->msg[10];
7420dbacebeSHans Verkuil 	*phys_addr = (msg->msg[11] << 8) | msg->msg[12];
7430dbacebeSHans Verkuil }
7440dbacebeSHans Verkuil 
7450dbacebeSHans Verkuil static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,
7460dbacebeSHans Verkuil 						   const char *prog_title)
7470dbacebeSHans Verkuil {
7480dbacebeSHans Verkuil 	unsigned int len = strlen(prog_title);
7490dbacebeSHans Verkuil 
7500dbacebeSHans Verkuil 	if (len > 14)
7510dbacebeSHans Verkuil 		len = 14;
7520dbacebeSHans Verkuil 	msg->len = 2 + len;
7530dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE;
7540dbacebeSHans Verkuil 	memcpy(msg->msg + 2, prog_title, len);
7550dbacebeSHans Verkuil }
7560dbacebeSHans Verkuil 
7570dbacebeSHans Verkuil static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,
7580dbacebeSHans Verkuil 						   char *prog_title)
7590dbacebeSHans Verkuil {
7600dbacebeSHans Verkuil 	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
7610dbacebeSHans Verkuil 
7620dbacebeSHans Verkuil 	if (len > 14)
7630dbacebeSHans Verkuil 		len = 14;
7640dbacebeSHans Verkuil 	memcpy(prog_title, msg->msg + 2, len);
7650dbacebeSHans Verkuil 	prog_title[len] = '\0';
7660dbacebeSHans Verkuil }
7670dbacebeSHans Verkuil 
7680dbacebeSHans Verkuil /* System Information Feature */
7690dbacebeSHans Verkuil static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
7700dbacebeSHans Verkuil {
7710dbacebeSHans Verkuil 	msg->len = 3;
7720dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CEC_VERSION;
7730dbacebeSHans Verkuil 	msg->msg[2] = cec_version;
7740dbacebeSHans Verkuil }
7750dbacebeSHans Verkuil 
7760dbacebeSHans Verkuil static inline void cec_ops_cec_version(const struct cec_msg *msg,
7770dbacebeSHans Verkuil 				       __u8 *cec_version)
7780dbacebeSHans Verkuil {
7790dbacebeSHans Verkuil 	*cec_version = msg->msg[2];
7800dbacebeSHans Verkuil }
7810dbacebeSHans Verkuil 
7820dbacebeSHans Verkuil static inline void cec_msg_get_cec_version(struct cec_msg *msg,
7833145c754SHans Verkuil 					   int reply)
7840dbacebeSHans Verkuil {
7850dbacebeSHans Verkuil 	msg->len = 2;
7860dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GET_CEC_VERSION;
7870dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;
7880dbacebeSHans Verkuil }
7890dbacebeSHans Verkuil 
7900dbacebeSHans Verkuil static inline void cec_msg_report_physical_addr(struct cec_msg *msg,
7910dbacebeSHans Verkuil 					__u16 phys_addr, __u8 prim_devtype)
7920dbacebeSHans Verkuil {
7930dbacebeSHans Verkuil 	msg->len = 5;
7940dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
7950dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_PHYSICAL_ADDR;
7960dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
7970dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
7980dbacebeSHans Verkuil 	msg->msg[4] = prim_devtype;
7990dbacebeSHans Verkuil }
8000dbacebeSHans Verkuil 
8010dbacebeSHans Verkuil static inline void cec_ops_report_physical_addr(const struct cec_msg *msg,
8020dbacebeSHans Verkuil 					__u16 *phys_addr, __u8 *prim_devtype)
8030dbacebeSHans Verkuil {
8040dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
8050dbacebeSHans Verkuil 	*prim_devtype = msg->msg[4];
8060dbacebeSHans Verkuil }
8070dbacebeSHans Verkuil 
8080dbacebeSHans Verkuil static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
8093145c754SHans Verkuil 					      int reply)
8100dbacebeSHans Verkuil {
8110dbacebeSHans Verkuil 	msg->len = 2;
8120dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR;
8130dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;
8140dbacebeSHans Verkuil }
8150dbacebeSHans Verkuil 
8160dbacebeSHans Verkuil static inline void cec_msg_set_menu_language(struct cec_msg *msg,
8170dbacebeSHans Verkuil 					     const char *language)
8180dbacebeSHans Verkuil {
8190dbacebeSHans Verkuil 	msg->len = 5;
8200dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
8210dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE;
8220dbacebeSHans Verkuil 	memcpy(msg->msg + 2, language, 3);
8230dbacebeSHans Verkuil }
8240dbacebeSHans Verkuil 
8250dbacebeSHans Verkuil static inline void cec_ops_set_menu_language(const struct cec_msg *msg,
8260dbacebeSHans Verkuil 					     char *language)
8270dbacebeSHans Verkuil {
8280dbacebeSHans Verkuil 	memcpy(language, msg->msg + 2, 3);
8290dbacebeSHans Verkuil 	language[3] = '\0';
8300dbacebeSHans Verkuil }
8310dbacebeSHans Verkuil 
8320dbacebeSHans Verkuil static inline void cec_msg_get_menu_language(struct cec_msg *msg,
8333145c754SHans Verkuil 					     int reply)
8340dbacebeSHans Verkuil {
8350dbacebeSHans Verkuil 	msg->len = 2;
8360dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE;
8370dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0;
8380dbacebeSHans Verkuil }
8390dbacebeSHans Verkuil 
8400dbacebeSHans Verkuil /*
8410dbacebeSHans Verkuil  * Assumes a single RC Profile byte and a single Device Features byte,
8420dbacebeSHans Verkuil  * i.e. no extended features are supported by this helper function.
8430dbacebeSHans Verkuil  *
8440dbacebeSHans Verkuil  * As of CEC 2.0 no extended features are defined, should those be added
8450dbacebeSHans Verkuil  * in the future, then this function needs to be adapted or a new function
8460dbacebeSHans Verkuil  * should be added.
8470dbacebeSHans Verkuil  */
8480dbacebeSHans Verkuil static inline void cec_msg_report_features(struct cec_msg *msg,
8490dbacebeSHans Verkuil 				__u8 cec_version, __u8 all_device_types,
8500dbacebeSHans Verkuil 				__u8 rc_profile, __u8 dev_features)
8510dbacebeSHans Verkuil {
8520dbacebeSHans Verkuil 	msg->len = 6;
8530dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
8540dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_FEATURES;
8550dbacebeSHans Verkuil 	msg->msg[2] = cec_version;
8560dbacebeSHans Verkuil 	msg->msg[3] = all_device_types;
8570dbacebeSHans Verkuil 	msg->msg[4] = rc_profile;
8580dbacebeSHans Verkuil 	msg->msg[5] = dev_features;
8590dbacebeSHans Verkuil }
8600dbacebeSHans Verkuil 
8610dbacebeSHans Verkuil static inline void cec_ops_report_features(const struct cec_msg *msg,
8620dbacebeSHans Verkuil 			__u8 *cec_version, __u8 *all_device_types,
8630dbacebeSHans Verkuil 			const __u8 **rc_profile, const __u8 **dev_features)
8640dbacebeSHans Verkuil {
8650dbacebeSHans Verkuil 	const __u8 *p = &msg->msg[4];
8660dbacebeSHans Verkuil 
8670dbacebeSHans Verkuil 	*cec_version = msg->msg[2];
8680dbacebeSHans Verkuil 	*all_device_types = msg->msg[3];
8690dbacebeSHans Verkuil 	*rc_profile = p;
87079bcd34cSHans Verkuil 	*dev_features = NULL;
8710dbacebeSHans Verkuil 	while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))
8720dbacebeSHans Verkuil 		p++;
8730dbacebeSHans Verkuil 	if (!(*p & CEC_OP_FEAT_EXT)) {
8740dbacebeSHans Verkuil 		*dev_features = p + 1;
8750dbacebeSHans Verkuil 		while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))
8760dbacebeSHans Verkuil 			p++;
8770dbacebeSHans Verkuil 	}
8780dbacebeSHans Verkuil 	if (*p & CEC_OP_FEAT_EXT)
8790dbacebeSHans Verkuil 		*rc_profile = *dev_features = NULL;
8800dbacebeSHans Verkuil }
8810dbacebeSHans Verkuil 
8820dbacebeSHans Verkuil static inline void cec_msg_give_features(struct cec_msg *msg,
8833145c754SHans Verkuil 					 int reply)
8840dbacebeSHans Verkuil {
8850dbacebeSHans Verkuil 	msg->len = 2;
8860dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_FEATURES;
8870dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;
8880dbacebeSHans Verkuil }
8890dbacebeSHans Verkuil 
8900dbacebeSHans Verkuil /* Deck Control Feature */
8910dbacebeSHans Verkuil static inline void cec_msg_deck_control(struct cec_msg *msg,
8920dbacebeSHans Verkuil 					__u8 deck_control_mode)
8930dbacebeSHans Verkuil {
8940dbacebeSHans Verkuil 	msg->len = 3;
8950dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_DECK_CONTROL;
8960dbacebeSHans Verkuil 	msg->msg[2] = deck_control_mode;
8970dbacebeSHans Verkuil }
8980dbacebeSHans Verkuil 
8990dbacebeSHans Verkuil static inline void cec_ops_deck_control(const struct cec_msg *msg,
9000dbacebeSHans Verkuil 					__u8 *deck_control_mode)
9010dbacebeSHans Verkuil {
9020dbacebeSHans Verkuil 	*deck_control_mode = msg->msg[2];
9030dbacebeSHans Verkuil }
9040dbacebeSHans Verkuil 
9050dbacebeSHans Verkuil static inline void cec_msg_deck_status(struct cec_msg *msg,
9060dbacebeSHans Verkuil 				       __u8 deck_info)
9070dbacebeSHans Verkuil {
9080dbacebeSHans Verkuil 	msg->len = 3;
9090dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_DECK_STATUS;
9100dbacebeSHans Verkuil 	msg->msg[2] = deck_info;
9110dbacebeSHans Verkuil }
9120dbacebeSHans Verkuil 
9130dbacebeSHans Verkuil static inline void cec_ops_deck_status(const struct cec_msg *msg,
9140dbacebeSHans Verkuil 				       __u8 *deck_info)
9150dbacebeSHans Verkuil {
9160dbacebeSHans Verkuil 	*deck_info = msg->msg[2];
9170dbacebeSHans Verkuil }
9180dbacebeSHans Verkuil 
9190dbacebeSHans Verkuil static inline void cec_msg_give_deck_status(struct cec_msg *msg,
9203145c754SHans Verkuil 					    int reply,
9210dbacebeSHans Verkuil 					    __u8 status_req)
9220dbacebeSHans Verkuil {
9230dbacebeSHans Verkuil 	msg->len = 3;
9240dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS;
9250dbacebeSHans Verkuil 	msg->msg[2] = status_req;
9269b211f9cSHans Verkuil 	msg->reply = (reply && status_req != CEC_OP_STATUS_REQ_OFF) ?
9279b211f9cSHans Verkuil 				CEC_MSG_DECK_STATUS : 0;
9280dbacebeSHans Verkuil }
9290dbacebeSHans Verkuil 
9300dbacebeSHans Verkuil static inline void cec_ops_give_deck_status(const struct cec_msg *msg,
9310dbacebeSHans Verkuil 					    __u8 *status_req)
9320dbacebeSHans Verkuil {
9330dbacebeSHans Verkuil 	*status_req = msg->msg[2];
9340dbacebeSHans Verkuil }
9350dbacebeSHans Verkuil 
9360dbacebeSHans Verkuil static inline void cec_msg_play(struct cec_msg *msg,
9370dbacebeSHans Verkuil 				__u8 play_mode)
9380dbacebeSHans Verkuil {
9390dbacebeSHans Verkuil 	msg->len = 3;
9400dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_PLAY;
9410dbacebeSHans Verkuil 	msg->msg[2] = play_mode;
9420dbacebeSHans Verkuil }
9430dbacebeSHans Verkuil 
9440dbacebeSHans Verkuil static inline void cec_ops_play(const struct cec_msg *msg,
9450dbacebeSHans Verkuil 				__u8 *play_mode)
9460dbacebeSHans Verkuil {
9470dbacebeSHans Verkuil 	*play_mode = msg->msg[2];
9480dbacebeSHans Verkuil }
9490dbacebeSHans Verkuil 
9500dbacebeSHans Verkuil 
9510dbacebeSHans Verkuil /* Tuner Control Feature */
9520dbacebeSHans Verkuil struct cec_op_tuner_device_info {
9530dbacebeSHans Verkuil 	__u8 rec_flag;
9540dbacebeSHans Verkuil 	__u8 tuner_display_info;
9553145c754SHans Verkuil 	__u8 is_analog;
9560dbacebeSHans Verkuil 	union {
9570dbacebeSHans Verkuil 		struct cec_op_digital_service_id digital;
9580dbacebeSHans Verkuil 		struct {
9590dbacebeSHans Verkuil 			__u8 ana_bcast_type;
9600dbacebeSHans Verkuil 			__u16 ana_freq;
9610dbacebeSHans Verkuil 			__u8 bcast_system;
9620dbacebeSHans Verkuil 		} analog;
9630dbacebeSHans Verkuil 	};
9640dbacebeSHans Verkuil };
9650dbacebeSHans Verkuil 
9660dbacebeSHans Verkuil static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
9670dbacebeSHans Verkuil 						      __u8 rec_flag,
9680dbacebeSHans Verkuil 						      __u8 tuner_display_info,
9690dbacebeSHans Verkuil 						      __u8 ana_bcast_type,
9700dbacebeSHans Verkuil 						      __u16 ana_freq,
9710dbacebeSHans Verkuil 						      __u8 bcast_system)
9720dbacebeSHans Verkuil {
9730dbacebeSHans Verkuil 	msg->len = 7;
9740dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
9750dbacebeSHans Verkuil 	msg->msg[2] = (rec_flag << 7) | tuner_display_info;
9760dbacebeSHans Verkuil 	msg->msg[3] = ana_bcast_type;
9770dbacebeSHans Verkuil 	msg->msg[4] = ana_freq >> 8;
9780dbacebeSHans Verkuil 	msg->msg[5] = ana_freq & 0xff;
9790dbacebeSHans Verkuil 	msg->msg[6] = bcast_system;
9800dbacebeSHans Verkuil }
9810dbacebeSHans Verkuil 
9820dbacebeSHans Verkuil static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
9830dbacebeSHans Verkuil 		   __u8 rec_flag, __u8 tuner_display_info,
9840dbacebeSHans Verkuil 		   const struct cec_op_digital_service_id *digital)
9850dbacebeSHans Verkuil {
9860dbacebeSHans Verkuil 	msg->len = 10;
9870dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
9880dbacebeSHans Verkuil 	msg->msg[2] = (rec_flag << 7) | tuner_display_info;
9890dbacebeSHans Verkuil 	cec_set_digital_service_id(msg->msg + 3, digital);
9900dbacebeSHans Verkuil }
9910dbacebeSHans Verkuil 
9920dbacebeSHans Verkuil static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
9930dbacebeSHans Verkuil 			const struct cec_op_tuner_device_info *tuner_dev_info)
9940dbacebeSHans Verkuil {
9950dbacebeSHans Verkuil 	if (tuner_dev_info->is_analog)
9960dbacebeSHans Verkuil 		cec_msg_tuner_device_status_analog(msg,
9970dbacebeSHans Verkuil 			tuner_dev_info->rec_flag,
9980dbacebeSHans Verkuil 			tuner_dev_info->tuner_display_info,
9990dbacebeSHans Verkuil 			tuner_dev_info->analog.ana_bcast_type,
10000dbacebeSHans Verkuil 			tuner_dev_info->analog.ana_freq,
10010dbacebeSHans Verkuil 			tuner_dev_info->analog.bcast_system);
10020dbacebeSHans Verkuil 	else
10030dbacebeSHans Verkuil 		cec_msg_tuner_device_status_digital(msg,
10040dbacebeSHans Verkuil 			tuner_dev_info->rec_flag,
10050dbacebeSHans Verkuil 			tuner_dev_info->tuner_display_info,
10060dbacebeSHans Verkuil 			&tuner_dev_info->digital);
10070dbacebeSHans Verkuil }
10080dbacebeSHans Verkuil 
10090dbacebeSHans Verkuil static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
10100dbacebeSHans Verkuil 				struct cec_op_tuner_device_info *tuner_dev_info)
10110dbacebeSHans Verkuil {
10120dbacebeSHans Verkuil 	tuner_dev_info->is_analog = msg->len < 10;
10130dbacebeSHans Verkuil 	tuner_dev_info->rec_flag = msg->msg[2] >> 7;
10140dbacebeSHans Verkuil 	tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
10150dbacebeSHans Verkuil 	if (tuner_dev_info->is_analog) {
10160dbacebeSHans Verkuil 		tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
10170dbacebeSHans Verkuil 		tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
10180dbacebeSHans Verkuil 		tuner_dev_info->analog.bcast_system = msg->msg[6];
10190dbacebeSHans Verkuil 		return;
10200dbacebeSHans Verkuil 	}
10210dbacebeSHans Verkuil 	cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
10220dbacebeSHans Verkuil }
10230dbacebeSHans Verkuil 
10240dbacebeSHans Verkuil static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
10253145c754SHans Verkuil 						    int reply,
10260dbacebeSHans Verkuil 						    __u8 status_req)
10270dbacebeSHans Verkuil {
10280dbacebeSHans Verkuil 	msg->len = 3;
10290dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
10300dbacebeSHans Verkuil 	msg->msg[2] = status_req;
10319b211f9cSHans Verkuil 	msg->reply = (reply && status_req != CEC_OP_STATUS_REQ_OFF) ?
10329b211f9cSHans Verkuil 				CEC_MSG_TUNER_DEVICE_STATUS : 0;
10330dbacebeSHans Verkuil }
10340dbacebeSHans Verkuil 
10350dbacebeSHans Verkuil static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
10360dbacebeSHans Verkuil 						    __u8 *status_req)
10370dbacebeSHans Verkuil {
10380dbacebeSHans Verkuil 	*status_req = msg->msg[2];
10390dbacebeSHans Verkuil }
10400dbacebeSHans Verkuil 
10410dbacebeSHans Verkuil static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
10420dbacebeSHans Verkuil 						   __u8 ana_bcast_type,
10430dbacebeSHans Verkuil 						   __u16 ana_freq,
10440dbacebeSHans Verkuil 						   __u8 bcast_system)
10450dbacebeSHans Verkuil {
10460dbacebeSHans Verkuil 	msg->len = 6;
10470dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
10480dbacebeSHans Verkuil 	msg->msg[2] = ana_bcast_type;
10490dbacebeSHans Verkuil 	msg->msg[3] = ana_freq >> 8;
10500dbacebeSHans Verkuil 	msg->msg[4] = ana_freq & 0xff;
10510dbacebeSHans Verkuil 	msg->msg[5] = bcast_system;
10520dbacebeSHans Verkuil }
10530dbacebeSHans Verkuil 
10540dbacebeSHans Verkuil static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
10550dbacebeSHans Verkuil 						   __u8 *ana_bcast_type,
10560dbacebeSHans Verkuil 						   __u16 *ana_freq,
10570dbacebeSHans Verkuil 						   __u8 *bcast_system)
10580dbacebeSHans Verkuil {
10590dbacebeSHans Verkuil 	*ana_bcast_type = msg->msg[2];
10600dbacebeSHans Verkuil 	*ana_freq = (msg->msg[3] << 8) | msg->msg[4];
10610dbacebeSHans Verkuil 	*bcast_system = msg->msg[5];
10620dbacebeSHans Verkuil }
10630dbacebeSHans Verkuil 
10640dbacebeSHans Verkuil static inline void cec_msg_select_digital_service(struct cec_msg *msg,
10650dbacebeSHans Verkuil 				const struct cec_op_digital_service_id *digital)
10660dbacebeSHans Verkuil {
10670dbacebeSHans Verkuil 	msg->len = 9;
10680dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
10690dbacebeSHans Verkuil 	cec_set_digital_service_id(msg->msg + 2, digital);
10700dbacebeSHans Verkuil }
10710dbacebeSHans Verkuil 
10720dbacebeSHans Verkuil static inline void cec_ops_select_digital_service(const struct cec_msg *msg,
10730dbacebeSHans Verkuil 				struct cec_op_digital_service_id *digital)
10740dbacebeSHans Verkuil {
10750dbacebeSHans Verkuil 	cec_get_digital_service_id(msg->msg + 2, digital);
10760dbacebeSHans Verkuil }
10770dbacebeSHans Verkuil 
10780dbacebeSHans Verkuil static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
10790dbacebeSHans Verkuil {
10800dbacebeSHans Verkuil 	msg->len = 2;
10810dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
10820dbacebeSHans Verkuil }
10830dbacebeSHans Verkuil 
10840dbacebeSHans Verkuil static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
10850dbacebeSHans Verkuil {
10860dbacebeSHans Verkuil 	msg->len = 2;
10870dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
10880dbacebeSHans Verkuil }
10890dbacebeSHans Verkuil 
10900dbacebeSHans Verkuil 
10910dbacebeSHans Verkuil /* Vendor Specific Commands Feature */
10920dbacebeSHans Verkuil static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
10930dbacebeSHans Verkuil {
10940dbacebeSHans Verkuil 	msg->len = 5;
10950dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
10960dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
10970dbacebeSHans Verkuil 	msg->msg[2] = vendor_id >> 16;
10980dbacebeSHans Verkuil 	msg->msg[3] = (vendor_id >> 8) & 0xff;
10990dbacebeSHans Verkuil 	msg->msg[4] = vendor_id & 0xff;
11000dbacebeSHans Verkuil }
11010dbacebeSHans Verkuil 
11020dbacebeSHans Verkuil static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
11030dbacebeSHans Verkuil 					    __u32 *vendor_id)
11040dbacebeSHans Verkuil {
11050dbacebeSHans Verkuil 	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
11060dbacebeSHans Verkuil }
11070dbacebeSHans Verkuil 
11080dbacebeSHans Verkuil static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
11093145c754SHans Verkuil 						 int reply)
11100dbacebeSHans Verkuil {
11110dbacebeSHans Verkuil 	msg->len = 2;
11120dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
11130dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
11140dbacebeSHans Verkuil }
11150dbacebeSHans Verkuil 
11160dbacebeSHans Verkuil static inline void cec_msg_vendor_command(struct cec_msg *msg,
11170dbacebeSHans Verkuil 					  __u8 size, const __u8 *vendor_cmd)
11180dbacebeSHans Verkuil {
11190dbacebeSHans Verkuil 	if (size > 14)
11200dbacebeSHans Verkuil 		size = 14;
11210dbacebeSHans Verkuil 	msg->len = 2 + size;
11220dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_VENDOR_COMMAND;
11230dbacebeSHans Verkuil 	memcpy(msg->msg + 2, vendor_cmd, size);
11240dbacebeSHans Verkuil }
11250dbacebeSHans Verkuil 
11260dbacebeSHans Verkuil static inline void cec_ops_vendor_command(const struct cec_msg *msg,
11270dbacebeSHans Verkuil 					  __u8 *size,
11280dbacebeSHans Verkuil 					  const __u8 **vendor_cmd)
11290dbacebeSHans Verkuil {
11300dbacebeSHans Verkuil 	*size = msg->len - 2;
11310dbacebeSHans Verkuil 
11320dbacebeSHans Verkuil 	if (*size > 14)
11330dbacebeSHans Verkuil 		*size = 14;
11340dbacebeSHans Verkuil 	*vendor_cmd = msg->msg + 2;
11350dbacebeSHans Verkuil }
11360dbacebeSHans Verkuil 
11370dbacebeSHans Verkuil static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
11380dbacebeSHans Verkuil 						  __u32 vendor_id, __u8 size,
11390dbacebeSHans Verkuil 						  const __u8 *vendor_cmd)
11400dbacebeSHans Verkuil {
11410dbacebeSHans Verkuil 	if (size > 11)
11420dbacebeSHans Verkuil 		size = 11;
11430dbacebeSHans Verkuil 	msg->len = 5 + size;
11440dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_VENDOR_COMMAND_WITH_ID;
11450dbacebeSHans Verkuil 	msg->msg[2] = vendor_id >> 16;
11460dbacebeSHans Verkuil 	msg->msg[3] = (vendor_id >> 8) & 0xff;
11470dbacebeSHans Verkuil 	msg->msg[4] = vendor_id & 0xff;
11480dbacebeSHans Verkuil 	memcpy(msg->msg + 5, vendor_cmd, size);
11490dbacebeSHans Verkuil }
11500dbacebeSHans Verkuil 
11510dbacebeSHans Verkuil static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
11520dbacebeSHans Verkuil 						  __u32 *vendor_id,  __u8 *size,
11530dbacebeSHans Verkuil 						  const __u8 **vendor_cmd)
11540dbacebeSHans Verkuil {
11550dbacebeSHans Verkuil 	*size = msg->len - 5;
11560dbacebeSHans Verkuil 
11570dbacebeSHans Verkuil 	if (*size > 11)
11580dbacebeSHans Verkuil 		*size = 11;
11590dbacebeSHans Verkuil 	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
11600dbacebeSHans Verkuil 	*vendor_cmd = msg->msg + 5;
11610dbacebeSHans Verkuil }
11620dbacebeSHans Verkuil 
11630dbacebeSHans Verkuil static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
11640dbacebeSHans Verkuil 						     __u8 size,
11650dbacebeSHans Verkuil 						     const __u8 *rc_code)
11660dbacebeSHans Verkuil {
11670dbacebeSHans Verkuil 	if (size > 14)
11680dbacebeSHans Verkuil 		size = 14;
11690dbacebeSHans Verkuil 	msg->len = 2 + size;
11700dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN;
11710dbacebeSHans Verkuil 	memcpy(msg->msg + 2, rc_code, size);
11720dbacebeSHans Verkuil }
11730dbacebeSHans Verkuil 
11740dbacebeSHans Verkuil static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
11750dbacebeSHans Verkuil 						     __u8 *size,
11760dbacebeSHans Verkuil 						     const __u8 **rc_code)
11770dbacebeSHans Verkuil {
11780dbacebeSHans Verkuil 	*size = msg->len - 2;
11790dbacebeSHans Verkuil 
11800dbacebeSHans Verkuil 	if (*size > 14)
11810dbacebeSHans Verkuil 		*size = 14;
11820dbacebeSHans Verkuil 	*rc_code = msg->msg + 2;
11830dbacebeSHans Verkuil }
11840dbacebeSHans Verkuil 
11850dbacebeSHans Verkuil static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
11860dbacebeSHans Verkuil {
11870dbacebeSHans Verkuil 	msg->len = 2;
11880dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
11890dbacebeSHans Verkuil }
11900dbacebeSHans Verkuil 
11910dbacebeSHans Verkuil 
11920dbacebeSHans Verkuil /* OSD Display Feature */
11930dbacebeSHans Verkuil static inline void cec_msg_set_osd_string(struct cec_msg *msg,
11940dbacebeSHans Verkuil 					  __u8 disp_ctl,
11950dbacebeSHans Verkuil 					  const char *osd)
11960dbacebeSHans Verkuil {
11970dbacebeSHans Verkuil 	unsigned int len = strlen(osd);
11980dbacebeSHans Verkuil 
11990dbacebeSHans Verkuil 	if (len > 13)
12000dbacebeSHans Verkuil 		len = 13;
12010dbacebeSHans Verkuil 	msg->len = 3 + len;
12020dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_OSD_STRING;
12030dbacebeSHans Verkuil 	msg->msg[2] = disp_ctl;
12040dbacebeSHans Verkuil 	memcpy(msg->msg + 3, osd, len);
12050dbacebeSHans Verkuil }
12060dbacebeSHans Verkuil 
12070dbacebeSHans Verkuil static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
12080dbacebeSHans Verkuil 					  __u8 *disp_ctl,
12090dbacebeSHans Verkuil 					  char *osd)
12100dbacebeSHans Verkuil {
12110dbacebeSHans Verkuil 	unsigned int len = msg->len > 3 ? msg->len - 3 : 0;
12120dbacebeSHans Verkuil 
12130dbacebeSHans Verkuil 	*disp_ctl = msg->msg[2];
12140dbacebeSHans Verkuil 	if (len > 13)
12150dbacebeSHans Verkuil 		len = 13;
12160dbacebeSHans Verkuil 	memcpy(osd, msg->msg + 3, len);
12170dbacebeSHans Verkuil 	osd[len] = '\0';
12180dbacebeSHans Verkuil }
12190dbacebeSHans Verkuil 
12200dbacebeSHans Verkuil 
12210dbacebeSHans Verkuil /* Device OSD Transfer Feature */
12220dbacebeSHans Verkuil static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
12230dbacebeSHans Verkuil {
12240dbacebeSHans Verkuil 	unsigned int len = strlen(name);
12250dbacebeSHans Verkuil 
12260dbacebeSHans Verkuil 	if (len > 14)
12270dbacebeSHans Verkuil 		len = 14;
12280dbacebeSHans Verkuil 	msg->len = 2 + len;
12290dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_OSD_NAME;
12300dbacebeSHans Verkuil 	memcpy(msg->msg + 2, name, len);
12310dbacebeSHans Verkuil }
12320dbacebeSHans Verkuil 
12330dbacebeSHans Verkuil static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
12340dbacebeSHans Verkuil 					char *name)
12350dbacebeSHans Verkuil {
12360dbacebeSHans Verkuil 	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
12370dbacebeSHans Verkuil 
12380dbacebeSHans Verkuil 	if (len > 14)
12390dbacebeSHans Verkuil 		len = 14;
12400dbacebeSHans Verkuil 	memcpy(name, msg->msg + 2, len);
12410dbacebeSHans Verkuil 	name[len] = '\0';
12420dbacebeSHans Verkuil }
12430dbacebeSHans Verkuil 
12440dbacebeSHans Verkuil static inline void cec_msg_give_osd_name(struct cec_msg *msg,
12453145c754SHans Verkuil 					 int reply)
12460dbacebeSHans Verkuil {
12470dbacebeSHans Verkuil 	msg->len = 2;
12480dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
12490dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
12500dbacebeSHans Verkuil }
12510dbacebeSHans Verkuil 
12520dbacebeSHans Verkuil 
12530dbacebeSHans Verkuil /* Device Menu Control Feature */
12540dbacebeSHans Verkuil static inline void cec_msg_menu_status(struct cec_msg *msg,
12550dbacebeSHans Verkuil 				       __u8 menu_state)
12560dbacebeSHans Verkuil {
12570dbacebeSHans Verkuil 	msg->len = 3;
12580dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_MENU_STATUS;
12590dbacebeSHans Verkuil 	msg->msg[2] = menu_state;
12600dbacebeSHans Verkuil }
12610dbacebeSHans Verkuil 
12620dbacebeSHans Verkuil static inline void cec_ops_menu_status(const struct cec_msg *msg,
12630dbacebeSHans Verkuil 				       __u8 *menu_state)
12640dbacebeSHans Verkuil {
12650dbacebeSHans Verkuil 	*menu_state = msg->msg[2];
12660dbacebeSHans Verkuil }
12670dbacebeSHans Verkuil 
12680dbacebeSHans Verkuil static inline void cec_msg_menu_request(struct cec_msg *msg,
12693145c754SHans Verkuil 					int reply,
12700dbacebeSHans Verkuil 					__u8 menu_req)
12710dbacebeSHans Verkuil {
12720dbacebeSHans Verkuil 	msg->len = 3;
12730dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_MENU_REQUEST;
12740dbacebeSHans Verkuil 	msg->msg[2] = menu_req;
12750dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
12760dbacebeSHans Verkuil }
12770dbacebeSHans Verkuil 
12780dbacebeSHans Verkuil static inline void cec_ops_menu_request(const struct cec_msg *msg,
12790dbacebeSHans Verkuil 					__u8 *menu_req)
12800dbacebeSHans Verkuil {
12810dbacebeSHans Verkuil 	*menu_req = msg->msg[2];
12820dbacebeSHans Verkuil }
12830dbacebeSHans Verkuil 
12840dbacebeSHans Verkuil struct cec_op_ui_command {
12850dbacebeSHans Verkuil 	__u8 ui_cmd;
12863145c754SHans Verkuil 	__u8 has_opt_arg;
12870dbacebeSHans Verkuil 	union {
12880dbacebeSHans Verkuil 		struct cec_op_channel_data channel_identifier;
12890dbacebeSHans Verkuil 		__u8 ui_broadcast_type;
12900dbacebeSHans Verkuil 		__u8 ui_sound_presentation_control;
12910dbacebeSHans Verkuil 		__u8 play_mode;
12920dbacebeSHans Verkuil 		__u8 ui_function_media;
12930dbacebeSHans Verkuil 		__u8 ui_function_select_av_input;
12940dbacebeSHans Verkuil 		__u8 ui_function_select_audio_input;
12950dbacebeSHans Verkuil 	};
12960dbacebeSHans Verkuil };
12970dbacebeSHans Verkuil 
12980dbacebeSHans Verkuil static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
12990dbacebeSHans Verkuil 					const struct cec_op_ui_command *ui_cmd)
13000dbacebeSHans Verkuil {
13010dbacebeSHans Verkuil 	msg->len = 3;
13020dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
13030dbacebeSHans Verkuil 	msg->msg[2] = ui_cmd->ui_cmd;
13040dbacebeSHans Verkuil 	if (!ui_cmd->has_opt_arg)
13050dbacebeSHans Verkuil 		return;
13060dbacebeSHans Verkuil 	switch (ui_cmd->ui_cmd) {
1307d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_BROADCAST_TYPE:
1308d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_SOUND_PRESENTATION:
1309d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_PLAY_FUNCTION:
1310d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_MEDIA_FUNCTION:
1311d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_AV_INPUT_FUNCTION:
1312d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_AUDIO_INPUT_FUNCTION:
13130dbacebeSHans Verkuil 		/* The optional operand is one byte for all these ui commands */
13140dbacebeSHans Verkuil 		msg->len++;
13150dbacebeSHans Verkuil 		msg->msg[3] = ui_cmd->play_mode;
13160dbacebeSHans Verkuil 		break;
1317d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_TUNE_FUNCTION:
13180dbacebeSHans Verkuil 		msg->len += 4;
13190dbacebeSHans Verkuil 		msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
13200dbacebeSHans Verkuil 			      (ui_cmd->channel_identifier.major >> 8);
13210dbacebeSHans Verkuil 		msg->msg[4] = ui_cmd->channel_identifier.major & 0xff;
13220dbacebeSHans Verkuil 		msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
13230dbacebeSHans Verkuil 		msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
13240dbacebeSHans Verkuil 		break;
13250dbacebeSHans Verkuil 	}
13260dbacebeSHans Verkuil }
13270dbacebeSHans Verkuil 
13280dbacebeSHans Verkuil static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
13290dbacebeSHans Verkuil 						struct cec_op_ui_command *ui_cmd)
13300dbacebeSHans Verkuil {
13310dbacebeSHans Verkuil 	ui_cmd->ui_cmd = msg->msg[2];
13323145c754SHans Verkuil 	ui_cmd->has_opt_arg = 0;
13330dbacebeSHans Verkuil 	if (msg->len == 3)
13340dbacebeSHans Verkuil 		return;
13350dbacebeSHans Verkuil 	switch (ui_cmd->ui_cmd) {
1336d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_BROADCAST_TYPE:
1337d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_SOUND_PRESENTATION:
1338d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_PLAY_FUNCTION:
1339d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_MEDIA_FUNCTION:
1340d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_AV_INPUT_FUNCTION:
1341d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_SELECT_AUDIO_INPUT_FUNCTION:
13420dbacebeSHans Verkuil 		/* The optional operand is one byte for all these ui commands */
13430dbacebeSHans Verkuil 		ui_cmd->play_mode = msg->msg[3];
13443145c754SHans Verkuil 		ui_cmd->has_opt_arg = 1;
13450dbacebeSHans Verkuil 		break;
1346d7ca5afdSHans Verkuil 	case CEC_OP_UI_CMD_TUNE_FUNCTION:
13470dbacebeSHans Verkuil 		if (msg->len < 7)
13480dbacebeSHans Verkuil 			break;
13493145c754SHans Verkuil 		ui_cmd->has_opt_arg = 1;
13500dbacebeSHans Verkuil 		ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
13510dbacebeSHans Verkuil 		ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
13520dbacebeSHans Verkuil 		ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
13530dbacebeSHans Verkuil 		break;
13540dbacebeSHans Verkuil 	}
13550dbacebeSHans Verkuil }
13560dbacebeSHans Verkuil 
13570dbacebeSHans Verkuil static inline void cec_msg_user_control_released(struct cec_msg *msg)
13580dbacebeSHans Verkuil {
13590dbacebeSHans Verkuil 	msg->len = 2;
13600dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
13610dbacebeSHans Verkuil }
13620dbacebeSHans Verkuil 
13630dbacebeSHans Verkuil /* Remote Control Passthrough Feature */
13640dbacebeSHans Verkuil 
13650dbacebeSHans Verkuil /* Power Status Feature */
13660dbacebeSHans Verkuil static inline void cec_msg_report_power_status(struct cec_msg *msg,
13670dbacebeSHans Verkuil 					       __u8 pwr_state)
13680dbacebeSHans Verkuil {
13690dbacebeSHans Verkuil 	msg->len = 3;
13700dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
13710dbacebeSHans Verkuil 	msg->msg[2] = pwr_state;
13720dbacebeSHans Verkuil }
13730dbacebeSHans Verkuil 
13740dbacebeSHans Verkuil static inline void cec_ops_report_power_status(const struct cec_msg *msg,
13750dbacebeSHans Verkuil 					       __u8 *pwr_state)
13760dbacebeSHans Verkuil {
13770dbacebeSHans Verkuil 	*pwr_state = msg->msg[2];
13780dbacebeSHans Verkuil }
13790dbacebeSHans Verkuil 
13800dbacebeSHans Verkuil static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
13813145c754SHans Verkuil 						    int reply)
13820dbacebeSHans Verkuil {
13830dbacebeSHans Verkuil 	msg->len = 2;
13840dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
13850dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
13860dbacebeSHans Verkuil }
13870dbacebeSHans Verkuil 
13880dbacebeSHans Verkuil /* General Protocol Messages */
13890dbacebeSHans Verkuil static inline void cec_msg_feature_abort(struct cec_msg *msg,
13900dbacebeSHans Verkuil 					 __u8 abort_msg, __u8 reason)
13910dbacebeSHans Verkuil {
13920dbacebeSHans Verkuil 	msg->len = 4;
13930dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
13940dbacebeSHans Verkuil 	msg->msg[2] = abort_msg;
13950dbacebeSHans Verkuil 	msg->msg[3] = reason;
13960dbacebeSHans Verkuil }
13970dbacebeSHans Verkuil 
13980dbacebeSHans Verkuil static inline void cec_ops_feature_abort(const struct cec_msg *msg,
13990dbacebeSHans Verkuil 					 __u8 *abort_msg, __u8 *reason)
14000dbacebeSHans Verkuil {
14010dbacebeSHans Verkuil 	*abort_msg = msg->msg[2];
14020dbacebeSHans Verkuil 	*reason = msg->msg[3];
14030dbacebeSHans Verkuil }
14040dbacebeSHans Verkuil 
14050dbacebeSHans Verkuil /* This changes the current message into a feature abort message */
14060dbacebeSHans Verkuil static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
14070dbacebeSHans Verkuil {
14080dbacebeSHans Verkuil 	cec_msg_set_reply_to(msg, msg);
14090dbacebeSHans Verkuil 	msg->len = 4;
14100dbacebeSHans Verkuil 	msg->msg[2] = msg->msg[1];
14110dbacebeSHans Verkuil 	msg->msg[3] = reason;
14120dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
14130dbacebeSHans Verkuil }
14140dbacebeSHans Verkuil 
14150dbacebeSHans Verkuil static inline void cec_msg_abort(struct cec_msg *msg)
14160dbacebeSHans Verkuil {
14170dbacebeSHans Verkuil 	msg->len = 2;
14180dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_ABORT;
14190dbacebeSHans Verkuil }
14200dbacebeSHans Verkuil 
14210dbacebeSHans Verkuil 
14220dbacebeSHans Verkuil /* System Audio Control Feature */
14230dbacebeSHans Verkuil static inline void cec_msg_report_audio_status(struct cec_msg *msg,
14240dbacebeSHans Verkuil 					       __u8 aud_mute_status,
14250dbacebeSHans Verkuil 					       __u8 aud_vol_status)
14260dbacebeSHans Verkuil {
14270dbacebeSHans Verkuil 	msg->len = 3;
14280dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
14290dbacebeSHans Verkuil 	msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
14300dbacebeSHans Verkuil }
14310dbacebeSHans Verkuil 
14320dbacebeSHans Verkuil static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
14330dbacebeSHans Verkuil 					       __u8 *aud_mute_status,
14340dbacebeSHans Verkuil 					       __u8 *aud_vol_status)
14350dbacebeSHans Verkuil {
14360dbacebeSHans Verkuil 	*aud_mute_status = msg->msg[2] >> 7;
14370dbacebeSHans Verkuil 	*aud_vol_status = msg->msg[2] & 0x7f;
14380dbacebeSHans Verkuil }
14390dbacebeSHans Verkuil 
14400dbacebeSHans Verkuil static inline void cec_msg_give_audio_status(struct cec_msg *msg,
14413145c754SHans Verkuil 					     int reply)
14420dbacebeSHans Verkuil {
14430dbacebeSHans Verkuil 	msg->len = 2;
14440dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
14450dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
14460dbacebeSHans Verkuil }
14470dbacebeSHans Verkuil 
14480dbacebeSHans Verkuil static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
14490dbacebeSHans Verkuil 						 __u8 sys_aud_status)
14500dbacebeSHans Verkuil {
14510dbacebeSHans Verkuil 	msg->len = 3;
14520dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
14530dbacebeSHans Verkuil 	msg->msg[2] = sys_aud_status;
14540dbacebeSHans Verkuil }
14550dbacebeSHans Verkuil 
14560dbacebeSHans Verkuil static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
14570dbacebeSHans Verkuil 						 __u8 *sys_aud_status)
14580dbacebeSHans Verkuil {
14590dbacebeSHans Verkuil 	*sys_aud_status = msg->msg[2];
14600dbacebeSHans Verkuil }
14610dbacebeSHans Verkuil 
14620dbacebeSHans Verkuil static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
14633145c754SHans Verkuil 						     int reply,
14640dbacebeSHans Verkuil 						     __u16 phys_addr)
14650dbacebeSHans Verkuil {
14660dbacebeSHans Verkuil 	msg->len = phys_addr == 0xffff ? 2 : 4;
14670dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
14680dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
14690dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
14700dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
14710dbacebeSHans Verkuil 
14720dbacebeSHans Verkuil }
14730dbacebeSHans Verkuil 
14740dbacebeSHans Verkuil static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
14750dbacebeSHans Verkuil 						     __u16 *phys_addr)
14760dbacebeSHans Verkuil {
14770dbacebeSHans Verkuil 	if (msg->len < 4)
14780dbacebeSHans Verkuil 		*phys_addr = 0xffff;
14790dbacebeSHans Verkuil 	else
14800dbacebeSHans Verkuil 		*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
14810dbacebeSHans Verkuil }
14820dbacebeSHans Verkuil 
14830dbacebeSHans Verkuil static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
14840dbacebeSHans Verkuil 						    __u8 sys_aud_status)
14850dbacebeSHans Verkuil {
14860dbacebeSHans Verkuil 	msg->len = 3;
14870dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
14880dbacebeSHans Verkuil 	msg->msg[2] = sys_aud_status;
14890dbacebeSHans Verkuil }
14900dbacebeSHans Verkuil 
14910dbacebeSHans Verkuil static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
14920dbacebeSHans Verkuil 						    __u8 *sys_aud_status)
14930dbacebeSHans Verkuil {
14940dbacebeSHans Verkuil 	*sys_aud_status = msg->msg[2];
14950dbacebeSHans Verkuil }
14960dbacebeSHans Verkuil 
14970dbacebeSHans Verkuil static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
14983145c754SHans Verkuil 							 int reply)
14990dbacebeSHans Verkuil {
15000dbacebeSHans Verkuil 	msg->len = 2;
15010dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
15020dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
15030dbacebeSHans Verkuil }
15040dbacebeSHans Verkuil 
15050dbacebeSHans Verkuil static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
15060dbacebeSHans Verkuil 					__u8 num_descriptors,
15070dbacebeSHans Verkuil 					const __u32 *descriptors)
15080dbacebeSHans Verkuil {
15090dbacebeSHans Verkuil 	unsigned int i;
15100dbacebeSHans Verkuil 
15110dbacebeSHans Verkuil 	if (num_descriptors > 4)
15120dbacebeSHans Verkuil 		num_descriptors = 4;
15130dbacebeSHans Verkuil 	msg->len = 2 + num_descriptors * 3;
15140dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
15150dbacebeSHans Verkuil 	for (i = 0; i < num_descriptors; i++) {
15160dbacebeSHans Verkuil 		msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
15170dbacebeSHans Verkuil 		msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
15180dbacebeSHans Verkuil 		msg->msg[4 + i * 3] = descriptors[i] & 0xff;
15190dbacebeSHans Verkuil 	}
15200dbacebeSHans Verkuil }
15210dbacebeSHans Verkuil 
15220dbacebeSHans Verkuil static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
15230dbacebeSHans Verkuil 							 __u8 *num_descriptors,
15240dbacebeSHans Verkuil 							 __u32 *descriptors)
15250dbacebeSHans Verkuil {
15260dbacebeSHans Verkuil 	unsigned int i;
15270dbacebeSHans Verkuil 
15280dbacebeSHans Verkuil 	*num_descriptors = (msg->len - 2) / 3;
15290dbacebeSHans Verkuil 	if (*num_descriptors > 4)
15300dbacebeSHans Verkuil 		*num_descriptors = 4;
15310dbacebeSHans Verkuil 	for (i = 0; i < *num_descriptors; i++)
15320dbacebeSHans Verkuil 		descriptors[i] = (msg->msg[2 + i * 3] << 16) |
15330dbacebeSHans Verkuil 			(msg->msg[3 + i * 3] << 8) |
15340dbacebeSHans Verkuil 			msg->msg[4 + i * 3];
15350dbacebeSHans Verkuil }
15360dbacebeSHans Verkuil 
15370dbacebeSHans Verkuil static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
15383145c754SHans Verkuil 					int reply,
15390dbacebeSHans Verkuil 					__u8 num_descriptors,
15400dbacebeSHans Verkuil 					const __u8 *audio_format_id,
15410dbacebeSHans Verkuil 					const __u8 *audio_format_code)
15420dbacebeSHans Verkuil {
15430dbacebeSHans Verkuil 	unsigned int i;
15440dbacebeSHans Verkuil 
15450dbacebeSHans Verkuil 	if (num_descriptors > 4)
15460dbacebeSHans Verkuil 		num_descriptors = 4;
15470dbacebeSHans Verkuil 	msg->len = 2 + num_descriptors;
15480dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
15490dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR : 0;
15500dbacebeSHans Verkuil 	for (i = 0; i < num_descriptors; i++)
15510dbacebeSHans Verkuil 		msg->msg[2 + i] = (audio_format_id[i] << 6) |
15520dbacebeSHans Verkuil 				  (audio_format_code[i] & 0x3f);
15530dbacebeSHans Verkuil }
15540dbacebeSHans Verkuil 
15550dbacebeSHans Verkuil static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
15560dbacebeSHans Verkuil 					__u8 *num_descriptors,
15570dbacebeSHans Verkuil 					__u8 *audio_format_id,
15580dbacebeSHans Verkuil 					__u8 *audio_format_code)
15590dbacebeSHans Verkuil {
15600dbacebeSHans Verkuil 	unsigned int i;
15610dbacebeSHans Verkuil 
15620dbacebeSHans Verkuil 	*num_descriptors = msg->len - 2;
15630dbacebeSHans Verkuil 	if (*num_descriptors > 4)
15640dbacebeSHans Verkuil 		*num_descriptors = 4;
15650dbacebeSHans Verkuil 	for (i = 0; i < *num_descriptors; i++) {
15660dbacebeSHans Verkuil 		audio_format_id[i] = msg->msg[2 + i] >> 6;
15670dbacebeSHans Verkuil 		audio_format_code[i] = msg->msg[2 + i] & 0x3f;
15680dbacebeSHans Verkuil 	}
15690dbacebeSHans Verkuil }
15700dbacebeSHans Verkuil 
15710dbacebeSHans Verkuil 
15720dbacebeSHans Verkuil /* Audio Rate Control Feature */
15730dbacebeSHans Verkuil static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
15740dbacebeSHans Verkuil 					  __u8 audio_rate)
15750dbacebeSHans Verkuil {
15760dbacebeSHans Verkuil 	msg->len = 3;
15770dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
15780dbacebeSHans Verkuil 	msg->msg[2] = audio_rate;
15790dbacebeSHans Verkuil }
15800dbacebeSHans Verkuil 
15810dbacebeSHans Verkuil static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
15820dbacebeSHans Verkuil 					  __u8 *audio_rate)
15830dbacebeSHans Verkuil {
15840dbacebeSHans Verkuil 	*audio_rate = msg->msg[2];
15850dbacebeSHans Verkuil }
15860dbacebeSHans Verkuil 
15870dbacebeSHans Verkuil 
15880dbacebeSHans Verkuil /* Audio Return Channel Control Feature */
15890dbacebeSHans Verkuil static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
15900dbacebeSHans Verkuil {
15910dbacebeSHans Verkuil 	msg->len = 2;
15920dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
15930dbacebeSHans Verkuil }
15940dbacebeSHans Verkuil 
15950dbacebeSHans Verkuil static inline void cec_msg_initiate_arc(struct cec_msg *msg,
15963145c754SHans Verkuil 					int reply)
15970dbacebeSHans Verkuil {
15980dbacebeSHans Verkuil 	msg->len = 2;
15990dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_INITIATE_ARC;
16000dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
16010dbacebeSHans Verkuil }
16020dbacebeSHans Verkuil 
16030dbacebeSHans Verkuil static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
16043145c754SHans Verkuil 						  int reply)
16050dbacebeSHans Verkuil {
16060dbacebeSHans Verkuil 	msg->len = 2;
16070dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
16080dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
16090dbacebeSHans Verkuil }
16100dbacebeSHans Verkuil 
16110dbacebeSHans Verkuil static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
16120dbacebeSHans Verkuil {
16130dbacebeSHans Verkuil 	msg->len = 2;
16140dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
16150dbacebeSHans Verkuil }
16160dbacebeSHans Verkuil 
16170dbacebeSHans Verkuil static inline void cec_msg_terminate_arc(struct cec_msg *msg,
16183145c754SHans Verkuil 					 int reply)
16190dbacebeSHans Verkuil {
16200dbacebeSHans Verkuil 	msg->len = 2;
16210dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_TERMINATE_ARC;
16220dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
16230dbacebeSHans Verkuil }
16240dbacebeSHans Verkuil 
16250dbacebeSHans Verkuil static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
16263145c754SHans Verkuil 						   int reply)
16270dbacebeSHans Verkuil {
16280dbacebeSHans Verkuil 	msg->len = 2;
16290dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
16300dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
16310dbacebeSHans Verkuil }
16320dbacebeSHans Verkuil 
16330dbacebeSHans Verkuil 
16340dbacebeSHans Verkuil /* Dynamic Audio Lipsync Feature */
16350dbacebeSHans Verkuil /* Only for CEC 2.0 and up */
16360dbacebeSHans Verkuil static inline void cec_msg_report_current_latency(struct cec_msg *msg,
16370dbacebeSHans Verkuil 						  __u16 phys_addr,
16380dbacebeSHans Verkuil 						  __u8 video_latency,
16390dbacebeSHans Verkuil 						  __u8 low_latency_mode,
16400dbacebeSHans Verkuil 						  __u8 audio_out_compensated,
16410dbacebeSHans Verkuil 						  __u8 audio_out_delay)
16420dbacebeSHans Verkuil {
1643f3854973SHans Verkuil 	msg->len = 6;
16440dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
16450dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
16460dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
16470dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
16480dbacebeSHans Verkuil 	msg->msg[4] = video_latency;
16490dbacebeSHans Verkuil 	msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
1650f3854973SHans Verkuil 	if (audio_out_compensated == 3)
1651f3854973SHans Verkuil 		msg->msg[msg->len++] = audio_out_delay;
16520dbacebeSHans Verkuil }
16530dbacebeSHans Verkuil 
16540dbacebeSHans Verkuil static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
16550dbacebeSHans Verkuil 						  __u16 *phys_addr,
16560dbacebeSHans Verkuil 						  __u8 *video_latency,
16570dbacebeSHans Verkuil 						  __u8 *low_latency_mode,
16580dbacebeSHans Verkuil 						  __u8 *audio_out_compensated,
16590dbacebeSHans Verkuil 						  __u8 *audio_out_delay)
16600dbacebeSHans Verkuil {
16610dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
16620dbacebeSHans Verkuil 	*video_latency = msg->msg[4];
16630dbacebeSHans Verkuil 	*low_latency_mode = (msg->msg[5] >> 2) & 1;
16640dbacebeSHans Verkuil 	*audio_out_compensated = msg->msg[5] & 3;
1665f3854973SHans Verkuil 	if (*audio_out_compensated == 3 && msg->len >= 7)
16660dbacebeSHans Verkuil 		*audio_out_delay = msg->msg[6];
1667f3854973SHans Verkuil 	else
1668f3854973SHans Verkuil 		*audio_out_delay = 0;
16690dbacebeSHans Verkuil }
16700dbacebeSHans Verkuil 
16710dbacebeSHans Verkuil static inline void cec_msg_request_current_latency(struct cec_msg *msg,
16723145c754SHans Verkuil 						   int reply,
16730dbacebeSHans Verkuil 						   __u16 phys_addr)
16740dbacebeSHans Verkuil {
16750dbacebeSHans Verkuil 	msg->len = 4;
16760dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
16770dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
16780dbacebeSHans Verkuil 	msg->msg[2] = phys_addr >> 8;
16790dbacebeSHans Verkuil 	msg->msg[3] = phys_addr & 0xff;
16800dbacebeSHans Verkuil 	msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
16810dbacebeSHans Verkuil }
16820dbacebeSHans Verkuil 
16830dbacebeSHans Verkuil static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
16840dbacebeSHans Verkuil 						   __u16 *phys_addr)
16850dbacebeSHans Verkuil {
16860dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
16870dbacebeSHans Verkuil }
16880dbacebeSHans Verkuil 
16890dbacebeSHans Verkuil 
16900dbacebeSHans Verkuil /* Capability Discovery and Control Feature */
16910dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
16920dbacebeSHans Verkuil 						 __u16 phys_addr1,
16930dbacebeSHans Verkuil 						 __u16 phys_addr2)
16940dbacebeSHans Verkuil {
16950dbacebeSHans Verkuil 	msg->len = 9;
16960dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
16970dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
16980dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
16990dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
17000dbacebeSHans Verkuil 	msg->msg[5] = phys_addr1 >> 8;
17010dbacebeSHans Verkuil 	msg->msg[6] = phys_addr1 & 0xff;
17020dbacebeSHans Verkuil 	msg->msg[7] = phys_addr2 >> 8;
17030dbacebeSHans Verkuil 	msg->msg[8] = phys_addr2 & 0xff;
17040dbacebeSHans Verkuil }
17050dbacebeSHans Verkuil 
17060dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
17070dbacebeSHans Verkuil 						 __u16 *phys_addr,
17080dbacebeSHans Verkuil 						 __u16 *phys_addr1,
17090dbacebeSHans Verkuil 						 __u16 *phys_addr2)
17100dbacebeSHans Verkuil {
17110dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
17120dbacebeSHans Verkuil 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
17130dbacebeSHans Verkuil 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
17140dbacebeSHans Verkuil }
17150dbacebeSHans Verkuil 
17160dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
17170dbacebeSHans Verkuil 						__u16 target_phys_addr,
17180dbacebeSHans Verkuil 						__u8 hec_func_state,
17190dbacebeSHans Verkuil 						__u8 host_func_state,
17200dbacebeSHans Verkuil 						__u8 enc_func_state,
17210dbacebeSHans Verkuil 						__u8 cdc_errcode,
17220dbacebeSHans Verkuil 						__u8 has_field,
17230dbacebeSHans Verkuil 						__u16 hec_field)
17240dbacebeSHans Verkuil {
17250dbacebeSHans Verkuil 	msg->len = has_field ? 10 : 8;
17260dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
17270dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
17280dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
17290dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
17300dbacebeSHans Verkuil 	msg->msg[5] = target_phys_addr >> 8;
17310dbacebeSHans Verkuil 	msg->msg[6] = target_phys_addr & 0xff;
17320dbacebeSHans Verkuil 	msg->msg[7] = (hec_func_state << 6) |
17330dbacebeSHans Verkuil 		      (host_func_state << 4) |
17340dbacebeSHans Verkuil 		      (enc_func_state << 2) |
17350dbacebeSHans Verkuil 		      cdc_errcode;
17360dbacebeSHans Verkuil 	if (has_field) {
17370dbacebeSHans Verkuil 		msg->msg[8] = hec_field >> 8;
17380dbacebeSHans Verkuil 		msg->msg[9] = hec_field & 0xff;
17390dbacebeSHans Verkuil 	}
17400dbacebeSHans Verkuil }
17410dbacebeSHans Verkuil 
17420dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
17430dbacebeSHans Verkuil 						__u16 *phys_addr,
17440dbacebeSHans Verkuil 						__u16 *target_phys_addr,
17450dbacebeSHans Verkuil 						__u8 *hec_func_state,
17460dbacebeSHans Verkuil 						__u8 *host_func_state,
17470dbacebeSHans Verkuil 						__u8 *enc_func_state,
17480dbacebeSHans Verkuil 						__u8 *cdc_errcode,
17490dbacebeSHans Verkuil 						__u8 *has_field,
17500dbacebeSHans Verkuil 						__u16 *hec_field)
17510dbacebeSHans Verkuil {
17520dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
17530dbacebeSHans Verkuil 	*target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
17540dbacebeSHans Verkuil 	*hec_func_state = msg->msg[7] >> 6;
17550dbacebeSHans Verkuil 	*host_func_state = (msg->msg[7] >> 4) & 3;
17560dbacebeSHans Verkuil 	*enc_func_state = (msg->msg[7] >> 4) & 3;
17570dbacebeSHans Verkuil 	*cdc_errcode = msg->msg[7] & 3;
17580dbacebeSHans Verkuil 	*has_field = msg->len >= 10;
17590dbacebeSHans Verkuil 	*hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
17600dbacebeSHans Verkuil }
17610dbacebeSHans Verkuil 
17620dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
17630dbacebeSHans Verkuil 					     __u16 phys_addr1,
17640dbacebeSHans Verkuil 					     __u16 phys_addr2,
17650dbacebeSHans Verkuil 					     __u8 hec_set_state,
17660dbacebeSHans Verkuil 					     __u16 phys_addr3,
17670dbacebeSHans Verkuil 					     __u16 phys_addr4,
17680dbacebeSHans Verkuil 					     __u16 phys_addr5)
17690dbacebeSHans Verkuil {
17700dbacebeSHans Verkuil 	msg->len = 10;
17710dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
17720dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
17730dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
17740dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
17750dbacebeSHans Verkuil 	msg->msg[5] = phys_addr1 >> 8;
17760dbacebeSHans Verkuil 	msg->msg[6] = phys_addr1 & 0xff;
17770dbacebeSHans Verkuil 	msg->msg[7] = phys_addr2 >> 8;
17780dbacebeSHans Verkuil 	msg->msg[8] = phys_addr2 & 0xff;
17790dbacebeSHans Verkuil 	msg->msg[9] = hec_set_state;
17800dbacebeSHans Verkuil 	if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
17810dbacebeSHans Verkuil 		msg->msg[msg->len++] = phys_addr3 >> 8;
17820dbacebeSHans Verkuil 		msg->msg[msg->len++] = phys_addr3 & 0xff;
17830dbacebeSHans Verkuil 		if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
17840dbacebeSHans Verkuil 			msg->msg[msg->len++] = phys_addr4 >> 8;
17850dbacebeSHans Verkuil 			msg->msg[msg->len++] = phys_addr4 & 0xff;
17860dbacebeSHans Verkuil 			if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
17870dbacebeSHans Verkuil 				msg->msg[msg->len++] = phys_addr5 >> 8;
17880dbacebeSHans Verkuil 				msg->msg[msg->len++] = phys_addr5 & 0xff;
17890dbacebeSHans Verkuil 			}
17900dbacebeSHans Verkuil 		}
17910dbacebeSHans Verkuil 	}
17920dbacebeSHans Verkuil }
17930dbacebeSHans Verkuil 
17940dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
17950dbacebeSHans Verkuil 					     __u16 *phys_addr,
17960dbacebeSHans Verkuil 					     __u16 *phys_addr1,
17970dbacebeSHans Verkuil 					     __u16 *phys_addr2,
17980dbacebeSHans Verkuil 					     __u8 *hec_set_state,
17990dbacebeSHans Verkuil 					     __u16 *phys_addr3,
18000dbacebeSHans Verkuil 					     __u16 *phys_addr4,
18010dbacebeSHans Verkuil 					     __u16 *phys_addr5)
18020dbacebeSHans Verkuil {
18030dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
18040dbacebeSHans Verkuil 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
18050dbacebeSHans Verkuil 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
18060dbacebeSHans Verkuil 	*hec_set_state = msg->msg[9];
18070dbacebeSHans Verkuil 	*phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
18080dbacebeSHans Verkuil 	if (msg->len >= 12)
18090dbacebeSHans Verkuil 		*phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
18100dbacebeSHans Verkuil 	if (msg->len >= 14)
18110dbacebeSHans Verkuil 		*phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
18120dbacebeSHans Verkuil 	if (msg->len >= 16)
18130dbacebeSHans Verkuil 		*phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
18140dbacebeSHans Verkuil }
18150dbacebeSHans Verkuil 
18160dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
18170dbacebeSHans Verkuil 						      __u16 phys_addr1,
18180dbacebeSHans Verkuil 						      __u8 hec_set_state)
18190dbacebeSHans Verkuil {
18200dbacebeSHans Verkuil 	msg->len = 8;
18210dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
18220dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
18230dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
18240dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
18250dbacebeSHans Verkuil 	msg->msg[5] = phys_addr1 >> 8;
18260dbacebeSHans Verkuil 	msg->msg[6] = phys_addr1 & 0xff;
18270dbacebeSHans Verkuil 	msg->msg[7] = hec_set_state;
18280dbacebeSHans Verkuil }
18290dbacebeSHans Verkuil 
18300dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
18310dbacebeSHans Verkuil 						      __u16 *phys_addr,
18320dbacebeSHans Verkuil 						      __u16 *phys_addr1,
18330dbacebeSHans Verkuil 						      __u8 *hec_set_state)
18340dbacebeSHans Verkuil {
18350dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
18360dbacebeSHans Verkuil 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
18370dbacebeSHans Verkuil 	*hec_set_state = msg->msg[7];
18380dbacebeSHans Verkuil }
18390dbacebeSHans Verkuil 
18400dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
18410dbacebeSHans Verkuil 							__u16 phys_addr1,
18420dbacebeSHans Verkuil 							__u16 phys_addr2,
18430dbacebeSHans Verkuil 							__u16 phys_addr3)
18440dbacebeSHans Verkuil {
18450dbacebeSHans Verkuil 	msg->len = 11;
18460dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
18470dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
18480dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
18490dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
18500dbacebeSHans Verkuil 	msg->msg[5] = phys_addr1 >> 8;
18510dbacebeSHans Verkuil 	msg->msg[6] = phys_addr1 & 0xff;
18520dbacebeSHans Verkuil 	msg->msg[7] = phys_addr2 >> 8;
18530dbacebeSHans Verkuil 	msg->msg[8] = phys_addr2 & 0xff;
18540dbacebeSHans Verkuil 	msg->msg[9] = phys_addr3 >> 8;
18550dbacebeSHans Verkuil 	msg->msg[10] = phys_addr3 & 0xff;
18560dbacebeSHans Verkuil }
18570dbacebeSHans Verkuil 
18580dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
18590dbacebeSHans Verkuil 							__u16 *phys_addr,
18600dbacebeSHans Verkuil 							__u16 *phys_addr1,
18610dbacebeSHans Verkuil 							__u16 *phys_addr2,
18620dbacebeSHans Verkuil 							__u16 *phys_addr3)
18630dbacebeSHans Verkuil {
18640dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
18650dbacebeSHans Verkuil 	*phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
18660dbacebeSHans Verkuil 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
18670dbacebeSHans Verkuil 	*phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
18680dbacebeSHans Verkuil }
18690dbacebeSHans Verkuil 
18700dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
18710dbacebeSHans Verkuil {
18720dbacebeSHans Verkuil 	msg->len = 5;
18730dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
18740dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
18750dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
18760dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
18770dbacebeSHans Verkuil }
18780dbacebeSHans Verkuil 
18790dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
18800dbacebeSHans Verkuil 						__u16 *phys_addr)
18810dbacebeSHans Verkuil {
18820dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
18830dbacebeSHans Verkuil }
18840dbacebeSHans Verkuil 
18850dbacebeSHans Verkuil static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
18860dbacebeSHans Verkuil {
18870dbacebeSHans Verkuil 	msg->len = 5;
18880dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
18890dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
18900dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
18910dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
18920dbacebeSHans Verkuil }
18930dbacebeSHans Verkuil 
18940dbacebeSHans Verkuil static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
18950dbacebeSHans Verkuil 					    __u16 *phys_addr)
18960dbacebeSHans Verkuil {
18970dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
18980dbacebeSHans Verkuil }
18990dbacebeSHans Verkuil 
19000dbacebeSHans Verkuil static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
19010dbacebeSHans Verkuil 					     __u8 input_port,
19020dbacebeSHans Verkuil 					     __u8 hpd_state)
19030dbacebeSHans Verkuil {
19040dbacebeSHans Verkuil 	msg->len = 6;
19050dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
19060dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
19070dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
19080dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
19090dbacebeSHans Verkuil 	msg->msg[5] = (input_port << 4) | hpd_state;
19100dbacebeSHans Verkuil }
19110dbacebeSHans Verkuil 
19120dbacebeSHans Verkuil static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
19130dbacebeSHans Verkuil 					    __u16 *phys_addr,
19140dbacebeSHans Verkuil 					    __u8 *input_port,
19150dbacebeSHans Verkuil 					    __u8 *hpd_state)
19160dbacebeSHans Verkuil {
19170dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
19180dbacebeSHans Verkuil 	*input_port = msg->msg[5] >> 4;
19190dbacebeSHans Verkuil 	*hpd_state = msg->msg[5] & 0xf;
19200dbacebeSHans Verkuil }
19210dbacebeSHans Verkuil 
19220dbacebeSHans Verkuil static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
19230dbacebeSHans Verkuil 						__u8 hpd_state,
19240dbacebeSHans Verkuil 						__u8 hpd_error)
19250dbacebeSHans Verkuil {
19260dbacebeSHans Verkuil 	msg->len = 6;
19270dbacebeSHans Verkuil 	msg->msg[0] |= 0xf; /* broadcast */
19280dbacebeSHans Verkuil 	msg->msg[1] = CEC_MSG_CDC_MESSAGE;
19290dbacebeSHans Verkuil 	/* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
19300dbacebeSHans Verkuil 	msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
19310dbacebeSHans Verkuil 	msg->msg[5] = (hpd_state << 4) | hpd_error;
19320dbacebeSHans Verkuil }
19330dbacebeSHans Verkuil 
19340dbacebeSHans Verkuil static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
19350dbacebeSHans Verkuil 						__u16 *phys_addr,
19360dbacebeSHans Verkuil 						__u8 *hpd_state,
19370dbacebeSHans Verkuil 						__u8 *hpd_error)
19380dbacebeSHans Verkuil {
19390dbacebeSHans Verkuil 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
19400dbacebeSHans Verkuil 	*hpd_state = msg->msg[5] >> 4;
19410dbacebeSHans Verkuil 	*hpd_error = msg->msg[5] & 0xf;
19420dbacebeSHans Verkuil }
19430dbacebeSHans Verkuil 
19440dbacebeSHans Verkuil #endif
1945