drivers/gpu/drm/bridge/adv7511/adv7511_cec.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
Extension
.c
Size
10620 bytes
Lines
384
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
 *
 * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/clk.h>

#include <media/cec.h>

#include <drm/display/drm_hdmi_cec_helper.h>

#include "adv7511.h"

static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = {
	ADV7511_REG_CEC_RX1_FRAME_HDR,
	ADV7511_REG_CEC_RX2_FRAME_HDR,
	ADV7511_REG_CEC_RX3_FRAME_HDR,
};

static const u8 ADV7511_REG_CEC_RX_FRAME_LEN[] = {
	ADV7511_REG_CEC_RX1_FRAME_LEN,
	ADV7511_REG_CEC_RX2_FRAME_LEN,
	ADV7511_REG_CEC_RX3_FRAME_LEN,
};

#define ADV7511_INT1_CEC_MASK \
	(ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
	 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1 | \
	 ADV7511_INT1_CEC_RX_READY2 | ADV7511_INT1_CEC_RX_READY3)

static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
{
	unsigned int offset = adv7511->info->reg_cec_offset;
	unsigned int val;

	if (regmap_read(adv7511->regmap_cec,
			ADV7511_REG_CEC_TX_ENABLE + offset, &val))
		return;

	if ((val & 0x01) == 0)
		return;

	if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
		drm_connector_hdmi_cec_transmit_attempt_done(adv7511->cec_connector,
							     CEC_TX_STATUS_ARB_LOST);
		return;
	}
	if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
		u8 status;
		u8 err_cnt = 0;
		u8 nack_cnt = 0;
		u8 low_drive_cnt = 0;
		unsigned int cnt;

		/*
		 * We set this status bit since this hardware performs
		 * retransmissions.
		 */
		status = CEC_TX_STATUS_MAX_RETRIES;
		if (regmap_read(adv7511->regmap_cec,
			    ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) {
			err_cnt = 1;
			status |= CEC_TX_STATUS_ERROR;
		} else {
			nack_cnt = cnt & 0xf;
			if (nack_cnt)
				status |= CEC_TX_STATUS_NACK;
			low_drive_cnt = cnt >> 4;
			if (low_drive_cnt)
				status |= CEC_TX_STATUS_LOW_DRIVE;
		}
		drm_connector_hdmi_cec_transmit_done(adv7511->cec_connector, status,
						     0, nack_cnt, low_drive_cnt,
						     err_cnt);
		return;
	}
	if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
		drm_connector_hdmi_cec_transmit_attempt_done(adv7511->cec_connector,
							     CEC_TX_STATUS_OK);
		return;
	}
}

static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
{

Annotation

Implementation Notes