drivers/dpll/zl3073x/out.c

Source file repositories/reference/linux-study-clean/drivers/dpll/zl3073x/out.c

File Facts

System
Linux kernel
Corpus path
drivers/dpll/zl3073x/out.c
Extension
.c
Size
4743 bytes
Lines
173
Domain
Driver Families
Bucket
drivers/dpll
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

#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/dev_printk.h>
#include <linux/string.h>
#include <linux/string_choices.h>
#include <linux/types.h>

#include "core.h"
#include "out.h"

/**
 * zl3073x_out_state_fetch - fetch output state from hardware
 * @zldev: pointer to zl3073x_dev structure
 * @index: output index to fetch state for
 *
 * Function fetches state of the given output from hardware and stores it
 * for later use.
 *
 * Return: 0 on success, <0 on error
 */
int zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index)
{
	struct zl3073x_out *out = &zldev->out[index];
	int rc;

	/* Read output configuration */
	rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_CTRL(index), &out->ctrl);
	if (rc)
		return rc;

	dev_dbg(zldev->dev, "OUT%u is %s and connected to SYNTH%u\n", index,
		str_enabled_disabled(zl3073x_out_is_enabled(out)),
		zl3073x_out_synth_get(out));

	guard(mutex)(&zldev->multiop_lock);

	/* Read output configuration */
	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
			   ZL_REG_OUTPUT_MB_MASK, BIT(index));
	if (rc)
		return rc;

	/* Read output mode */
	rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &out->mode);
	if (rc)
		return rc;

	dev_dbg(zldev->dev, "OUT%u has signal format 0x%02x\n", index,
		zl3073x_out_signal_format_get(out));

	/* Read output divisor */
	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_DIV, &out->div);
	if (rc)
		return rc;

	if (!out->div) {
		dev_err(zldev->dev, "Zero divisor for OUT%u got from device\n",
			index);
		return -EINVAL;
	}

	dev_dbg(zldev->dev, "OUT%u divisor: %u\n", index, out->div);

	/* Read output width */
	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_WIDTH, &out->width);
	if (rc)
		return rc;

	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD,
			      &out->esync_n_period);
	if (rc)
		return rc;

	if (!out->esync_n_period) {
		dev_err(zldev->dev,
			"Zero esync divisor for OUT%u got from device\n",
			index);
		return -EINVAL;
	}

	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_WIDTH,
			      &out->esync_n_width);
	if (rc)
		return rc;

	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_PHASE_COMP,
			      &out->phase_comp);
	if (rc)

Annotation

Implementation Notes